29 static const int EG_BITS = 9;
30 static const unsigned EG_MUTE = 1 << EG_BITS;
33 static const int EG_DP_BITS = 23;
42 const std::string& name);
59 FB = value ? 8 - value : 0;
62 template<
typename Archive>
63 void serialize(Archive& ar,
unsigned version);
92 inline int calc_slot_hat(
int lfo_am,
int a,
int b,
int whitenoise);
100 template<
typename Archive>
101 void serialize(Archive& ar,
unsigned version);
123 static const unsigned MOD = 0;
124 static const unsigned CAR = 1;
133 template<
typename Archive>
134 void serialize(Archive& ar,
unsigned version);
145 unsigned sampleRam,
MSXAudio& audio);
162 template<
typename Archive>
163 void serialize(Archive& ar,
unsigned version);
167 virtual int getAmplificationFactor()
const;
168 virtual void generateChannels(
int** bufs,
unsigned num);
170 inline void keyOn_BD();
171 inline void keyOn_SD();
172 inline void keyOn_TOM();
173 inline void keyOn_HH();
174 inline void keyOn_CYM();
175 inline void keyOff_BD();
176 inline void keyOff_SD();
177 inline void keyOff_TOM();
178 inline void keyOff_HH();
179 inline void keyOff_CYM();
180 inline void setRythmMode(
int data);
182 bool checkMuteHelper();
184 void changeStatusMask(
byte newMask);
186 void callback(
byte flag);
191 const std::unique_ptr<Y8950Adpcm> adpcm;
192 const std::unique_ptr<Y8950KeyboardConnector> connector;
193 const std::unique_ptr<DACSound16S> dac13;
194 const std::unique_ptr<Y8950Debuggable> debuggable;
196 const std::unique_ptr<EmuTimer> timer1;
197 const std::unique_ptr<EmuTimer> timer2;
209 unsigned noiseA_phase;
210 unsigned noiseB_phase;
211 unsigned noiseA_dphase;
212 unsigned noiseB_dphase;
223 static const double EG_STEP = 0.1875;
224 static const double SL_STEP = 3.0;
225 static const double TL_STEP = 0.75;
226 static const double DB_STEP = 0.1875;
228 static const unsigned SL_PER_EG = 16;
229 static const unsigned TL_PER_EG = 4;
230 static const unsigned EG_PER_DB = 1;
233 static const double PM_SPEED = 6.4;
234 static const double PM_DEPTH = 13.75 / 2;
235 static const double PM_DEPTH2 = 13.75;
238 static const int SL_BITS = 4;
239 static const int SL_MUTE = 1 << SL_BITS;
241 static const int PG_BITS = 10;
242 static const int PG_WIDTH = 1 << PG_BITS;
243 static const int PG_MASK = PG_WIDTH - 1;
245 static const int DP_BITS = 19;
246 static const int DP_BASE_BITS = DP_BITS - PG_BITS;
251 static unsigned sintable[PG_WIDTH];
259 static int tllTable[16 * 8][4];
263 static unsigned AR_ADJUST_TABLE[1 << EG_BITS];
268 static const int DB_BITS = 9;
269 static const int DB_MUTE = 1 << DB_BITS;
271 static const int PM_AMP_BITS = 8;
272 static const int PM_AMP = 1 << PM_AMP_BITS;
275 static const int DB2LIN_AMP_BITS = 11;
276 static const int SLOT_AMP_BITS = DB2LIN_AMP_BITS;
279 static const int PM_PG_BITS = 8;
280 static const int PM_PG_WIDTH = 1 << PM_PG_BITS;
281 static const int PM_DP_BITS = 16;
282 static const int PM_DP_WIDTH = 1 << PM_DP_BITS;
283 static const int AM_PG_BITS = 8;
284 static const int AM_PG_WIDTH = 1 << AM_PG_BITS;
285 static const int AM_DP_BITS = 16;
286 static const int AM_DP_WIDTH = 1 << AM_DP_BITS;
290 static int pmtable[2][PM_PG_WIDTH];
293 static int dB2LinTab[(2 * DB_MUTE) * 2];
311 static const unsigned LFO_AM_TAB_ELEMENTS = 210;
312 static const byte lfo_am_table[LFO_AM_TAB_ELEMENTS] =
374 static inline unsigned DB_POS(
int x)
376 int result = int(x / DB_STEP);
377 assert(result < DB_MUTE);
381 static inline unsigned DB_NEG(
int x)
383 return 2 * DB_MUTE + DB_POS(x);
393 static void makeAdjustTable()
395 AR_ADJUST_TABLE[0] = EG_MUTE;
396 for (
int i = 1; i < (1 << EG_BITS); ++i) {
397 AR_ADJUST_TABLE[i] = int(
double(EG_MUTE) - 1 -
398 EG_MUTE * ::log(
double(i)) / ::log(
double(1 << EG_BITS))) >> 1;
399 assert(AR_ADJUST_TABLE[i] <= EG_MUTE);
400 assert(
int(AR_ADJUST_TABLE[i]) >= 0);
405 static void makeDB2LinTable()
407 for (
int i = 0; i < DB_MUTE; ++i) {
408 dB2LinTab[i] = int(
double((1 << DB2LIN_AMP_BITS) - 1) *
409 pow(10, -
double(i) * DB_STEP / 20));
411 assert(dB2LinTab[DB_MUTE - 1] == 0);
412 for (
int i = DB_MUTE; i < 2 * DB_MUTE; ++i) {
415 for (
int i = 0; i < 2 * DB_MUTE; ++i) {
416 dB2LinTab[i + 2 * DB_MUTE] = -dB2LinTab[i];
421 static unsigned lin2db(
double d)
427 int tmp = -int(20.0 * log10(d) / DB_STEP);
428 int result = std::min(tmp, DB_MUTE - 1);
430 assert(result <= DB_MUTE - 1);
435 static void makeSinTable()
437 for (
int i = 0; i < PG_WIDTH / 4; ++i) {
438 sintable[i] = lin2db(sin(2.0 * M_PI * i / PG_WIDTH));
440 for (
int i = 0; i < PG_WIDTH / 4; i++) {
441 sintable[PG_WIDTH / 2 - 1 - i] = sintable[i];
443 for (
int i = 0; i < PG_WIDTH / 2; i++) {
444 sintable[PG_WIDTH / 2 + i] = 2 * DB_MUTE + sintable[i];
449 static void makePmTable()
451 for (
int i = 0; i < PM_PG_WIDTH; ++i) {
452 pmtable[0][i] = int(
double(PM_AMP) * pow(2,
double(PM_DEPTH) * sin(2.0 * M_PI * i / PM_PG_WIDTH) / 1200));
453 pmtable[1][i] = int(
double(PM_AMP) * pow(2,
double(PM_DEPTH2) * sin(2.0 * M_PI * i / PM_PG_WIDTH) / 1200));
457 static void makeTllTable()
460 static const unsigned kltable[16] = {
461 0, 24, 32, 37, 40, 43, 45, 47, 48, 50, 51, 52, 53, 54, 55, 56
464 for (
unsigned freq = 0; freq < 16 * 8; ++freq) {
465 unsigned fnum = freq % 16;
466 unsigned block = freq / 16;
467 int tmp = 4 * kltable[fnum] - 32 * (7 - block);
468 for (
unsigned KL = 0; KL < 4; ++KL) {
469 tllTable[freq][KL] = (tmp <= 0 || KL == 0) ? 0 : (tmp >> (3 - KL));
475 static void makeDphaseARTable()
477 for (
unsigned Rks = 0; Rks < 16; ++Rks) {
479 for (
unsigned AR = 1; AR < 15; ++AR) {
480 unsigned RM = std::min(AR + (Rks >> 2), 15u);
481 unsigned RL = Rks & 3;
482 dphaseARTable[Rks][AR] =
485 dphaseARTable[Rks][15] = EG_DP_MAX;
490 static void makeDphaseDRTable()
492 for (
unsigned Rks = 0; Rks < 16; ++Rks) {
494 for (
unsigned DR = 1; DR < 16; ++DR) {
495 unsigned RM = std::min(DR + (Rks >> 2), 15u);
496 unsigned RL = Rks & 3;
497 dphaseDRTable[Rks][DR] =
547 static const int mltable[16] = {
548 1, 1*2, 2*2, 3*2, 4*2, 5*2, 6*2 , 7*2,
549 8*2, 9*2, 10*2, 10*2, 12*2, 12*2, 15*2, 15*2
552 unsigned fnum = freq % 1024;
553 unsigned block = freq / 1024;
554 dphase = ((fnum * mltable[
patch.
ML]) << block) >> (21 - DP_BITS);
564 unsigned rks = freq >>
patch.
KR;
667 , motherBoard(config.getMotherBoard())
668 , periphery(audio.createPeriphery(
getName()))
670 self, config, name, sampleRam))
672 motherBoard.getPluggingController()))
674 name +
" DAC",
"MSX-AUDIO 13-bit DAC", config))
677 , timer1(
EmuTimer::createOPL3_1(motherBoard.getScheduler(), *this))
678 , timer2(
EmuTimer::createOPL3_2(motherBoard.getScheduler(), *this))
679 , irq(motherBoard,
getName() +
".IRQ")
700 setInputRate(
int(input + 0.5));
703 registerSound(config);
719 for (
int i = 0; i < 9; ++i) {
736 for (
int i = 0; i < 0x100; ++i) {
751 void Y8950::Impl::keyOn_BD() { ch[6].keyOn(); }
752 void Y8950::Impl::keyOn_HH() { ch[7].slot[MOD].slotOn(); }
753 void Y8950::Impl::keyOn_SD() { ch[7].slot[CAR].slotOn(); }
754 void Y8950::Impl::keyOn_TOM() { ch[8].slot[MOD].slotOn(); }
755 void Y8950::Impl::keyOn_CYM() { ch[8].slot[CAR].slotOn(); }
758 void Y8950::Impl::keyOff_BD() { ch[6].keyOff(); }
759 void Y8950::Impl::keyOff_HH() { ch[7].slot[MOD].slotOff(); }
760 void Y8950::Impl::keyOff_SD() { ch[7].slot[CAR].slotOff(); }
761 void Y8950::Impl::keyOff_TOM(){ ch[8].slot[MOD].slotOff(); }
762 void Y8950::Impl::keyOff_CYM(){ ch[8].slot[CAR].slotOff(); }
765 void Y8950::Impl::setRythmMode(
int data)
767 bool newMode = (data & 32) != 0;
768 if (rythm_mode != newMode) {
769 rythm_mode = newMode;
772 ch[6].slot[MOD].eg_mode =
FINISH;
773 ch[6].slot[MOD].slotStatus =
false;
774 ch[6].slot[CAR].eg_mode =
FINISH;
775 ch[6].slot[CAR].slotStatus =
false;
776 ch[7].slot[MOD].eg_mode =
FINISH;
777 ch[7].slot[MOD].slotStatus =
false;
778 ch[7].slot[CAR].eg_mode =
FINISH;
779 ch[7].slot[CAR].slotStatus =
false;
780 ch[8].slot[MOD].eg_mode =
FINISH;
781 ch[8].slot[MOD].slotStatus =
false;
782 ch[8].slot[CAR].eg_mode =
FINISH;
783 ch[8].slot[CAR].slotStatus =
false;
794 static inline int wave2_8pi(
int e)
796 int shift = SLOT_AMP_BITS - PG_BITS - 2;
797 return (shift > 0) ? (e >> shift) : (e << -shift);
803 phase += (dphase * lfo_pm) >> PM_AMP_BITS;
807 return phase >> DP_BASE_BITS;
810 #define S2E(x) EnvPhaseIndex(int(x / EG_STEP))
820 eg_phase += eg_dphase;
821 if (eg_phase >= EG_DP_MAX) {
827 egout = AR_ADJUST_TABLE[eg_phase.toInt()];
832 eg_phase += eg_dphase;
833 if (eg_phase >= SL[patch.SL]) {
834 eg_phase = SL[patch.SL];
838 egout = eg_phase.toInt();
842 egout = eg_phase.toInt();
851 eg_phase += eg_dphase;
852 egout = eg_phase.toInt();
853 if (egout >= EG_MUTE) {
864 egout = ((egout + tll) * EG_PER_DB);
868 return std::min<unsigned>(egout, DB_MUTE - 1);
873 unsigned egout = calc_envelope(lfo_am);
874 int pgout = calc_phase(lfo_pm) + wave2_8pi(fm);
875 return dB2LinTab[sintable[pgout & PG_MASK] + egout];
880 unsigned egout = calc_envelope(lfo_am);
881 unsigned pgout = calc_phase(lfo_pm);
884 pgout += wave2_8pi(feedback) >> patch.FB;
886 int newOutput = dB2LinTab[sintable[pgout & PG_MASK] + egout];
887 feedback = (output + newOutput) >> 1;
894 unsigned egout = calc_envelope(lfo_am);
895 unsigned pgout = calc_phase(lfo_pm);
896 return dB2LinTab[sintable[pgout & PG_MASK] + egout];
901 unsigned egout = calc_envelope(lfo_am);
902 unsigned pgout = calc_phase(lfo_pm);
903 unsigned tmp = (pgout & (1 << (PG_BITS - 1))) ? 0 : 2 * DB_MUTE;
904 return (dB2LinTab[tmp + egout] + dB2LinTab[egout + whitenoise]) >> 1;
909 unsigned egout = calc_envelope(lfo_am);
910 return (dB2LinTab[egout + a] + dB2LinTab[egout + b]) >> 1;
916 unsigned egout = calc_envelope(lfo_am);
917 return (dB2LinTab[egout + whitenoise] +
918 dB2LinTab[egout + a] +
919 dB2LinTab[egout + b]) >> 2;
922 int Y8950::Impl::getAmplificationFactor()
const
924 return 1 << (15 - DB2LIN_AMP_BITS);
933 bool Y8950::Impl::checkMuteHelper()
938 for (
int i = 0; i < 6; ++i) {
939 if (ch[i].slot[CAR].isActive())
return false;
942 for(
int i = 6; i < 9; ++i) {
943 if (ch[i].slot[CAR].isActive())
return false;
946 if (ch[6].slot[CAR].isActive())
return false;
947 if (ch[7].slot[MOD].isActive())
return false;
948 if (ch[7].slot[CAR].isActive())
return false;
949 if (ch[8].slot[MOD].isActive())
return false;
950 if (ch[8].slot[CAR].isActive())
return false;
953 return adpcm->isMuted();
956 void Y8950::Impl::generateChannels(
int** bufs,
unsigned num)
959 if (checkMuteHelper()) {
963 for (
int i = 0; i < 9 + 5 + 1; ++i) {
969 for (
unsigned sample = 0; sample < num; ++sample) {
975 if (am_phase == (LFO_AM_TAB_ELEMENTS * 64)) am_phase = 0;
976 unsigned tmp = lfo_am_table[am_phase / 64];
977 int lfo_am = am_mode ? tmp : tmp / 4;
979 pm_phase = (pm_phase + PM_DPHASE) & (PM_DP_WIDTH - 1);
980 int lfo_pm = pmtable[pm_mode][pm_phase >> (PM_DP_BITS - PM_PG_BITS)];
982 if (noise_seed & 1) {
983 noise_seed ^= 0x24000;
986 int whitenoise = noise_seed & 1 ? DB_POS(6) : DB_NEG(6);
988 noiseA_phase += noiseA_dphase;
989 noiseA_phase &= (0x40 << 11) - 1;
990 if ((noiseA_phase >> 11) == 0x3f) {
993 int noiseA = noiseA_phase & (0x03 << 11) ? DB_POS(6) : DB_NEG(6);
995 noiseB_phase += noiseB_dphase;
996 noiseB_phase &= (0x10 << 11) - 1;
997 int noiseB = noiseB_phase & (0x0A << 11) ? DB_POS(6) : DB_NEG(6);
999 int m = rythm_mode ? 6 : 9;
1000 for (
int i = 0; i < m; ++i) {
1001 if (ch[i].slot[CAR].isActive()) {
1002 bufs[i][sample] += ch[i].alg
1003 ? ch[i].slot[CAR].calc_slot_car(lfo_pm, lfo_am, 0) +
1004 ch[i].slot[MOD].calc_slot_mod(lfo_pm, lfo_am)
1005 : ch[i].slot[CAR].calc_slot_car(lfo_pm, lfo_am,
1006 ch[i].slot[MOD].calc_slot_mod(lfo_pm, lfo_am));
1017 ch[7].slot[MOD].calc_phase(lfo_pm);
1018 ch[8].slot[CAR].calc_phase(lfo_pm);
1020 bufs[ 9][sample] += (ch[6].slot[CAR].isActive())
1021 ? 2 * ch[6].slot[CAR].calc_slot_car(lfo_pm, lfo_am,
1022 ch[6].slot[MOD].calc_slot_mod(lfo_pm, lfo_am))
1024 bufs[10][sample] += (ch[7].slot[CAR].isActive())
1025 ? 2 * ch[7].slot[CAR].calc_slot_snare(lfo_pm, lfo_am, whitenoise)
1027 bufs[11][sample] += (ch[8].slot[CAR].isActive())
1028 ? 2 * ch[8].slot[CAR].calc_slot_cym(lfo_am, noiseA, noiseB)
1030 bufs[12][sample] += (ch[7].slot[MOD].isActive())
1031 ? 2 * ch[7].slot[MOD].calc_slot_hat(lfo_am, noiseA, noiseB, whitenoise)
1033 bufs[13][sample] += (ch[8].slot[MOD].isActive())
1034 ? 2 * ch[8].slot[MOD].calc_slot_tom(lfo_pm, lfo_am)
1044 bufs[14][sample] += adpcm->calcSample();
1055 0, 2, 4, 1, 3, 5, -1, -1,
1056 6, 8, 10, 7, 9, 11, -1, -1,
1057 12, 14, 16, 13, 15, 17, -1, -1,
1058 -1, -1, -1, -1, -1, -1, -1, -1
1068 switch (rg & 0xe0) {
1103 timer1->setValue(data);
1108 timer2->setValue(data);
1116 changeStatusMask((~data) & 0x78);
1121 adpcm->resetStatus();
1125 connector->write(data, time);
1130 periphery.setSPOFF((data & 8) != 0, time);
1146 adpcm->writeReg(rg, data, time);
1151 if (reg[0x08] & 0x04) {
1152 int tmp =
static_cast<signed char>(reg[0x15]) * 256
1154 tmp = (tmp * 4) >> (7 - reg[0x17]);
1156 dac13->writeDAC(tmp, time);
1160 reg[rg] = data & 0xC0;
1163 reg[rg] = data & 0x07;
1170 periphery.write(reg[0x18], reg[0x19], time);
1175 periphery.write(reg[0x18], reg[0x19], time);
1181 int s = stbl[rg & 0x1f];
1185 slot.
patch.
AM = (data >> 7) & 1;
1186 slot.
patch.
PM = (data >> 6) & 1;
1187 slot.
patch.
EG = (data >> 5) & 1;
1189 slot.
patch.
ML = (data >> 0) & 15;
1196 int s = stbl[rg & 0x1f];
1200 slot.
patch.
KL = (data >> 6) & 3;
1201 slot.
patch.
TL = (data >> 0) & 63;
1208 int s = stbl[rg & 0x1f];
1210 Y8950Slot& slot = ch[s / 2].slot[s & 1];
1211 slot.
patch.
AR = (data >> 4) & 15;
1212 slot.
patch.
DR = (data >> 0) & 15;
1219 int s = stbl[rg & 0x1f];
1221 Y8950Slot& slot = ch[s / 2].slot[s & 1];
1222 slot.
patch.
SL = (data >> 4) & 15;
1223 slot.
patch.
RR = (data >> 0) & 15;
1231 am_mode = (data & 0x80) != 0;
1232 pm_mode = (data & 0x40) != 0;
1236 if (data & 0x10) keyOn_BD();
else keyOff_BD();
1237 if (data & 0x08) keyOn_SD();
else keyOff_SD();
1238 if (data & 0x04) keyOn_TOM();
else keyOff_TOM();
1239 if (data & 0x02) keyOn_CYM();
else keyOff_CYM();
1240 if (data & 0x01) keyOn_HH();
else keyOff_HH();
1242 ch[6].slot[MOD].updateAll(ch[6].freq);
1243 ch[6].slot[CAR].updateAll(ch[6].freq);
1244 ch[7].slot[MOD].updateAll(ch[7].freq);
1245 ch[7].slot[CAR].updateAll(ch[7].freq);
1246 ch[8].slot[MOD].updateAll(ch[8].freq);
1247 ch[8].slot[CAR].updateAll(ch[8].freq);
1252 unsigned c = rg & 0x0f;
1260 freq = data | ((reg[rg + 0x10] & 0x1F) << 8);
1268 freq = reg[rg - 0x10] | ((data & 0x1F) << 8);
1270 ch[c].setFreq(freq);
1271 unsigned fNum = freq % 1024;
1272 unsigned block = freq / 1024;
1274 case 7: noiseA_dphase = fNum << block;
1276 case 8: noiseB_dphase = fNum << block;
1279 ch[c].slot[CAR].updateAll(freq);
1280 ch[c].slot[MOD].updateAll(freq);
1288 ch[c].slot[MOD].patch.setFeedbackShift((data >> 1) & 7);
1289 ch[c].alg = data & 1;
1305 result = adpcm->readReg(rg, time);
1317 return connector->read(time);
1323 return adpcm->peekReg(rg, time);
1326 byte input = periphery.read(time);
1327 byte output = reg[0x19];
1328 byte enable = reg[0x18];
1329 return (output & enable) | (input & ~enable) | 0xF0;
1346 return (status & (0x80 | statusMask)) | 0x06;
1349 void Y8950::Impl::callback(
byte flag)
1357 if (status & statusMask) {
1365 if (!(status & statusMask)) {
1374 void Y8950::Impl::changeStatusMask(
byte newMask)
1376 statusMask = newMask;
1377 status &= statusMask;
1388 template<
typename Archive>
1391 ar.serialize(
"AM", AM);
1392 ar.serialize(
"PM", PM);
1393 ar.serialize(
"EG", EG);
1394 ar.serialize(
"KR", KR);
1395 ar.serialize(
"ML",
ML);
1396 ar.serialize(
"KL", KL);
1397 ar.serialize(
"TL", TL);
1398 ar.serialize(
"FB", FB);
1399 ar.serialize(
"AR", AR);
1400 ar.serialize(
"DR", DR);
1401 ar.serialize(
"SL", SL);
1402 ar.serialize(
"RR", RR);
1405 template<
typename Archive>
1408 ar.serialize(
"feedback", feedback);
1409 ar.serialize(
"output", output);
1410 ar.serialize(
"phase", phase);
1411 ar.serialize(
"eg_mode", eg_mode);
1412 ar.serialize(
"eg_phase", eg_phase);
1413 ar.serialize(
"patch", patch);
1414 ar.serialize(
"slotStatus", slotStatus);
1420 template<
typename Archive>
1423 ar.serialize(
"mod", slot[MOD]);
1424 ar.serialize(
"car", slot[CAR]);
1425 ar.serialize(
"freq", freq);
1426 ar.serialize(
"alg", alg);
1428 if (ar.isLoader()) {
1429 slot[MOD].updateAll(freq);
1430 slot[CAR].updateAll(freq);
1434 template<
typename Archive>
1437 ar.serialize(
"keyboardConnector", *connector);
1438 ar.serialize(
"adpcm", *adpcm);
1439 ar.serialize(
"timer1", *timer1);
1440 ar.serialize(
"timer2", *timer2);
1441 ar.serialize(
"irq", irq);
1442 ar.serialize_blob(
"registers", reg,
sizeof(reg));
1443 ar.serialize(
"pm_phase", pm_phase);
1444 ar.serialize(
"am_phase", am_phase);
1445 ar.serialize(
"noise_seed", noise_seed);
1446 ar.serialize(
"noiseA_phase", noiseA_phase);
1447 ar.serialize(
"noiseB_phase", noiseB_phase);
1448 ar.serialize(
"noiseA_dphase", noiseA_dphase);
1449 ar.serialize(
"noiseB_dphase", noiseB_dphase);
1450 ar.serialize(
"channels", ch);
1451 ar.serialize(
"status", status);
1452 ar.serialize(
"statusMask", statusMask);
1453 ar.serialize(
"rythm_mode", rythm_mode);
1454 ar.serialize(
"am_mode", am_mode);
1455 ar.serialize(
"pm_mode", pm_mode);
1456 ar.serialize(
"enabled", enabled);
1459 static const byte rewriteRegs[] = {
1463 if (ar.isLoader()) {
1465 for (
unsigned i = 0; i <
sizeof(rewriteRegs); ++i) {
1466 byte r = rewriteRegs[i];
1476 const std::string& name)
1484 return y8950.
peekReg(address, time);
1489 y8950.
writeReg(address, value, time);
1500 pimpl->init(config, time);
1509 pimpl->setEnabled(enabled, time);
1524 pimpl->writeReg(reg, data, time);
1529 return pimpl->readReg(reg, time);
1534 return pimpl->peekReg(reg, time);
1539 return pimpl->readStatus(time);
1544 return pimpl->peekStatus(time);
1549 pimpl->setStatus(flags);
1554 pimpl->resetStatus(flags);
1559 return pimpl->peekRawStatus();
1562 template<
typename Archive>
1565 pimpl->serialize(ar, version);