AxibugEmuOnline/References/virtuanessrc097-master/NES/Mapper/EEPROM.h
2024-08-05 17:58:53 +08:00

412 lines
16 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class X24C01
{
public:
X24C01() {
now_state = X24C01_IDLE;
next_state = X24C01_IDLE;
addr = 0;
data = 0;
sda = 0xFF;
scl_old = 0;
sda_old = 0;
pEEPDATA = NULL;
}
void Reset( LPBYTE ptr ) {
now_state = X24C01_IDLE;
next_state = X24C01_IDLE;
addr = 0;
data = 0;
sda = 0xFF;
scl_old = 0;
sda_old = 0;
pEEPDATA = ptr;
}
void Write( BYTE scl_in, BYTE sda_in ) {
// Clock line
BYTE scl_rise = ~scl_old & scl_in;
BYTE scl_fall = scl_old & ~scl_in;
// Data line
BYTE sda_rise = ~sda_old & sda_in;
BYTE sda_fall = sda_old & ~sda_in;
BYTE scl_old_temp = scl_old;
BYTE sda_old_temp = sda_old;
scl_old = scl_in;
sda_old = sda_in;
// Start condition?
if( scl_old_temp && sda_fall ) {
now_state = X24C01_ADDRESS;
bitcnt = 0;
addr = 0;
sda = 0xFF;
return;
}
// Stop condition?
if( scl_old_temp && sda_rise ) {
now_state = X24C01_IDLE;
sda = 0xFF;
return;
}
// SCL ____---- RISE
if( scl_rise ) {
switch( now_state ) {
case X24C01_ADDRESS:
if( bitcnt < 7 ) {
// 本来はMSB->LSB
addr &= ~(1<<bitcnt);
addr |= (sda_in?1:0)<<bitcnt;
} else {
if( sda_in ) {
next_state = X24C01_READ;
data = pEEPDATA[addr&0x7F];
} else {
next_state = X24C01_WRITE;
}
}
bitcnt++;
break;
case X24C01_ACK:
sda = 0; // ACK
break;
case X24C01_READ:
if( bitcnt < 8 ) {
// 本来はMSB->LSB
sda = (data&(1<<bitcnt))?1:0;
}
bitcnt++;
break;
case X24C01_WRITE:
if( bitcnt < 8 ) {
// 本来はMSB->LSB
data &= ~(1<<bitcnt);
data |= (sda_in?1:0)<<bitcnt;
}
bitcnt++;
break;
case X24C01_ACK_WAIT:
if( !sda_in ) {
next_state = X24C01_IDLE;
}
break;
}
}
// SCL ----____ FALL
if( scl_fall ) {
switch( now_state ) {
case X24C01_ADDRESS:
if( bitcnt >= 8 ) {
now_state = X24C01_ACK;
sda = 0xFF;
}
break;
case X24C01_ACK:
now_state = next_state;
bitcnt = 0;
sda = 0xFF;
break;
case X24C01_READ:
if( bitcnt >= 8 ) {
now_state = X24C01_ACK_WAIT;
addr = (addr+1)&0x7F;
}
break;
case X24C01_WRITE:
if( bitcnt >= 8 ) {
now_state = X24C01_ACK;
next_state = X24C01_IDLE;
pEEPDATA[addr&0x7F] = data;
addr = (addr+1)&0x7F;
}
break;
}
}
}
BYTE Read() {
return sda;
}
// For State save
void Load( LPBYTE p )
{
now_state = *((INT*)&p[0]);
next_state = *((INT*)&p[4]);
bitcnt = *((INT*)&p[8]);
addr = p[12];
data = p[13];
sda = p[14];
scl_old = p[15];
sda_old = p[16];
}
void Save( LPBYTE p )
{
*((INT*)&p[0]) = now_state;
*((INT*)&p[4]) = next_state;
*((INT*)&p[8]) = bitcnt;
p[12] = addr;
p[13] = data;
p[14] = sda;
p[15] = scl_old;
p[16] = sda_old;
}
protected:
enum {
X24C01_IDLE = 0, // Idle
X24C01_ADDRESS, // Address set
X24C01_READ, // Read
X24C01_WRITE, // Write
X24C01_ACK, // Acknowledge
X24C01_ACK_WAIT, // Acknowledge wait
};
INT now_state, next_state;
INT bitcnt;
BYTE addr, data;
BYTE sda;
BYTE scl_old, sda_old;
LPBYTE pEEPDATA;
private:
};
class X24C02
{
public:
X24C02() {
now_state = X24C02_IDLE;
next_state = X24C02_IDLE;
addr = 0;
data = 0;
rw = 0;
sda = 0xFF;
scl_old = 0;
sda_old = 0;
pEEPDATA = NULL;
}
void Reset( LPBYTE ptr ) {
now_state = X24C02_IDLE;
next_state = X24C02_IDLE;
addr = 0;
data = 0;
rw = 0;
sda = 0xFF;
scl_old = 0;
sda_old = 0;
pEEPDATA = ptr;
}
void Write( BYTE scl_in, BYTE sda_in ) {
// Clock line
BYTE scl_rise = ~scl_old & scl_in;
BYTE scl_fall = scl_old & ~scl_in;
// Data line
BYTE sda_rise = ~sda_old & sda_in;
BYTE sda_fall = sda_old & ~sda_in;
BYTE scl_old_temp = scl_old;
BYTE sda_old_temp = sda_old;
scl_old = scl_in;
sda_old = sda_in;
// Start condition?
if( scl_old_temp && sda_fall ) {
now_state = X24C02_DEVADDR;
bitcnt = 0;
sda = 0xFF;
return;
}
// Stop condition?
if( scl_old_temp && sda_rise ) {
now_state = X24C02_IDLE;
sda = 0xFF;
return;
}
// SCL ____---- RISE
if( scl_rise ) {
switch( now_state ) {
case X24C02_DEVADDR:
if( bitcnt < 8 ) {
data &= ~(1<<(7-bitcnt));
data |= (sda_in?1:0)<<(7-bitcnt);
}
bitcnt++;
break;
case X24C02_ADDRESS:
if( bitcnt < 8 ) {
addr &= ~(1<<(7-bitcnt));
addr |= (sda_in?1:0)<<(7-bitcnt);
}
bitcnt++;
break;
case X24C02_READ:
if( bitcnt < 8 ) {
sda = (data&(1<<(7-bitcnt)))?1:0;
}
bitcnt++;
break;
case X24C02_WRITE:
if( bitcnt < 8 ) {
data &= ~(1<<(7-bitcnt));
data |= (sda_in?1:0)<<(7-bitcnt);
}
bitcnt++;
break;
case X24C02_NAK:
sda = 0xFF; // NAK
break;
case X24C02_ACK:
sda = 0; // ACK
break;
case X24C02_ACK_WAIT:
if( !sda_in ) {
next_state = X24C02_READ;
data = pEEPDATA[addr];
}
break;
}
}
// SCL ----____ FALL
if( scl_fall ) {
switch( now_state ) {
case X24C02_DEVADDR:
if( bitcnt >= 8 ) {
if( (data & 0xA0) == 0xA0 ) {
now_state = X24C02_ACK;
rw = data & 0x01;
sda = 0xFF;
if( rw ) {
// Now address read
next_state = X24C02_READ;
data = pEEPDATA[addr];
} else {
next_state = X24C02_ADDRESS;
}
bitcnt = 0;
} else {
now_state = X24C02_NAK;
next_state = X24C02_IDLE;
sda = 0xFF;
}
}
break;
case X24C02_ADDRESS:
if( bitcnt >= 8 ) {
now_state = X24C02_ACK;
sda = 0xFF;
if( rw ) {
// Readでは絶対来ないが念の為
next_state = X24C02_IDLE;
} else {
// to Data Write
next_state = X24C02_WRITE;
}
bitcnt = 0;
}
break;
case X24C02_READ:
if( bitcnt >= 8 ) {
now_state = X24C02_ACK_WAIT;
addr = (addr+1)&0xFF;
}
break;
case X24C02_WRITE:
if( bitcnt >= 8 ) {
pEEPDATA[addr] = data;
now_state = X24C02_ACK;
next_state = X24C02_WRITE;
addr = (addr+1)&0xFF;
bitcnt = 0;
}
break;
case X24C02_NAK:
now_state = X24C02_IDLE;
bitcnt = 0;
sda = 0xFF;
break;
case X24C02_ACK:
now_state = next_state;
bitcnt = 0;
sda = 0xFF;
break;
case X24C02_ACK_WAIT:
now_state = next_state;
bitcnt = 0;
sda = 0xFF;
break;
}
}
}
BYTE Read() {
return sda;
}
// For State save
void Load( LPBYTE p )
{
now_state = *((INT*)&p[0]);
next_state = *((INT*)&p[4]);
bitcnt = *((INT*)&p[8]);
addr = p[12];
data = p[13];
rw = p[14];
sda = p[15];
scl_old = p[16];
sda_old = p[17];
}
void Save( LPBYTE p )
{
*((INT*)&p[0]) = now_state;
*((INT*)&p[4]) = next_state;
*((INT*)&p[8]) = bitcnt;
p[12] = addr;
p[13] = data;
p[14] = rw;
p[15] = sda;
p[16] = scl_old;
p[17] = sda_old;
}
protected:
enum {
X24C02_IDLE = 0, // Idle
X24C02_DEVADDR, // Device address set
X24C02_ADDRESS, // Address set
X24C02_READ, // Read
X24C02_WRITE, // Write
X24C02_ACK, // Acknowledge
X24C02_NAK, // Not Acknowledge
X24C02_ACK_WAIT, // Acknowledge wait
};
INT now_state, next_state;
INT bitcnt;
BYTE addr, data, rw;
BYTE sda;
BYTE scl_old, sda_old;
LPBYTE pEEPDATA;
private:
};