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

412 lines
7.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. 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ÅÍ<E2809A>âΗˆÈ¢ª”Ö×
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:
};