Files
86Box-fork/src/tandy_eeprom.c

179 lines
5.7 KiB
C

#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "tandy_eeprom.h"
typedef struct
{
int state;
int count;
int addr;
int clock;
uint16_t data;
uint16_t store[64];
int romset;
} tandy_eeprom_t;
enum
{
EEPROM_IDLE,
EEPROM_GET_OPERATION,
EEPROM_READ,
EEPROM_WRITE
};
static int eeprom_data_out;
void tandy_eeprom_write(uint16_t addr, uint8_t val, void *p)
{
tandy_eeprom_t *eeprom = (tandy_eeprom_t *)p;
if ((val & 4) && !eeprom->clock)
{
// pclog("eeprom_write %02x %i %i\n", val, eeprom->state, eeprom->count);
switch (eeprom->state)
{
case EEPROM_IDLE:
switch (eeprom->count)
{
case 0:
if (!(val & 3))
eeprom->count = 1;
else
eeprom->count = 0;
break;
case 1:
if ((val & 3) == 2)
eeprom->count = 2;
else
eeprom->count = 0;
break;
case 2:
if ((val & 3) == 3)
eeprom->state = EEPROM_GET_OPERATION;
eeprom->count = 0;
break;
}
break;
case EEPROM_GET_OPERATION:
eeprom->data = (eeprom->data << 1) | (val & 1);
eeprom->count++;
if (eeprom->count == 8)
{
eeprom->count = 0;
// pclog("EEPROM get operation %02x\n", eeprom->data);
eeprom->addr = eeprom->data & 0x3f;
switch (eeprom->data & 0xc0)
{
case 0x40:
eeprom->state = EEPROM_WRITE;
break;
case 0x80:
eeprom->state = EEPROM_READ;
eeprom->data = eeprom->store[eeprom->addr];
// pclog("EEPROM read data %02x %04x\n", eeprom->addr, eeprom->data);
break;
default:
eeprom->state = EEPROM_IDLE;
break;
}
}
break;
case EEPROM_READ:
eeprom_data_out = eeprom->data & 0x8000;
eeprom->data <<= 1;
eeprom->count++;
if (eeprom->count == 16)
{
eeprom->count = 0;
eeprom->state = EEPROM_IDLE;
}
break;
case EEPROM_WRITE:
eeprom->data = (eeprom->data << 1) | (val & 1);
eeprom->count++;
if (eeprom->count == 16)
{
eeprom->count = 0;
eeprom->state = EEPROM_IDLE;
// pclog("EEPROM write %04x to %02x\n", eeprom->data, eeprom->addr);
eeprom->store[eeprom->addr] = eeprom->data;
}
break;
}
}
eeprom->clock = val & 4;
}
int tandy_eeprom_read()
{
// pclog("tandy_eeprom_read: data_out=%x\n", eeprom_data_out);
return eeprom_data_out;
}
void *tandy_eeprom_init()
{
tandy_eeprom_t *eeprom = malloc(sizeof(tandy_eeprom_t));
FILE *f;
memset(eeprom, 0, sizeof(tandy_eeprom_t));
eeprom->romset = romset;
switch (romset)
{
case ROM_TANDY1000HX:
f = romfopen("nvr/tandy1000hx.bin" ,"rb");
break;
case ROM_TANDY1000SL2:
f = romfopen("nvr/tandy1000sl2.bin" ,"rb");
break;
}
if (f)
{
fread(eeprom->store, 128, 1, f);
fclose(f);
}
else
memset(eeprom->store, 0, 128);
io_sethandler(0x037c, 0x0001, NULL, NULL, NULL, tandy_eeprom_write, NULL, NULL, eeprom);
return eeprom;
}
void tandy_eeprom_close(void *p)
{
tandy_eeprom_t *eeprom = (tandy_eeprom_t *)p;
FILE *f;
switch (eeprom->romset)
{
case ROM_TANDY1000HX:
f = romfopen("nvr/tandy1000hx.bin" ,"wb");
break;
case ROM_TANDY1000SL2:
f = romfopen("nvr/tandy1000sl2.bin" ,"wb");
break;
}
fwrite(eeprom->store, 128, 1, f);
fclose(f);
free(eeprom);
}
device_t tandy_eeprom_device =
{
"Tandy EEPROM",
0,
tandy_eeprom_init,
tandy_eeprom_close,
NULL,
NULL,
NULL,
NULL,
NULL
};