]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Microwire EEPROM (9346)
authorToni Wilen <twilen@winuae.net>
Sat, 15 Oct 2016 16:28:16 +0000 (19:28 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 15 Oct 2016 16:28:16 +0000 (19:28 +0300)
flashrom.cpp
include/flashrom.h

index 696c782ef8d72845e93bbef527325a40993853f6..63571caa971797fa1274fa8d1887b9a82b399f51 100644 (file)
@@ -1,7 +1,9 @@
 /*
 * UAE - The Un*x Amiga Emulator
 *
-* Simple 29F010 flash ROM chip emulator
+* Simple 29Fxxx flash ROM chip emulator
+* I2C EEPROM (24C08)
+* MICROWIRE EEPROM (9346)
 *
 * (c) 2014 Toni Wilen
 */
 #define FLASH_LOG 0
 #define EEPROM_LOG 0
 
+/* MICROWIRE EEPROM */
+
+struct eeprom93xx_eeprom_t {
+       uint8_t  tick;
+       uint8_t  address;
+       uint8_t  command;
+       uint8_t  writeable;
+
+       uint8_t eecs;
+       uint8_t eesk;
+       uint8_t eedo;
+
+       uint8_t  addrbits;
+       uint16_t size;
+       uint16_t data;
+       uint16_t contents[256];
+
+       uae_u8 *memory;
+       struct zfile *zf;
+};
+
+static const char *opstring[] = { "extended", "write", "read", "erase" };
+
+void eeprom93xx_write(void *eepromp, int eecs, int eesk, int eedi)
+{
+       eeprom93xx_eeprom_t *eeprom = (eeprom93xx_eeprom_t*)eepromp;
+       uint8_t tick = eeprom->tick;
+       uint8_t eedo = eeprom->eedo;
+       uint16_t address = eeprom->address;
+       uint8_t command = eeprom->command;
+
+       //write_log("CS=%u SK=%u DI=%u DO=%u, tick = %u\n", eecs, eesk, eedi, eedo, tick);
+
+       if (!eeprom->eecs && eecs) {
+               /* Start chip select cycle. */
+               //write_log("Cycle start, waiting for 1st start bit (0)\n");
+               tick = 0;
+               command = 0x0;
+               address = 0x0;
+       }
+       else if (eeprom->eecs && !eecs) {
+               /* End chip select cycle. This triggers write / erase. */
+               if (eeprom->writeable) {
+                       uint8_t subcommand = address >> (eeprom->addrbits - 2);
+                       if (command == 0 && subcommand == 2) {
+                               /* Erase all. */
+                               for (address = 0; address < eeprom->size; address++) {
+                                       eeprom->contents[address] = 0xffff;
+                               }
+                       }
+                       else if (command == 3) {
+                               /* Erase word. */
+                               eeprom->contents[address] = 0xffff;
+                       }
+                       else if (tick >= 2 + 2 + eeprom->addrbits + 16) {
+                               if (command == 1) {
+                                       /* Write word. */
+                                       eeprom->contents[address] &= eeprom->data;
+                               }
+                               else if (command == 0 && subcommand == 1) {
+                                       /* Write all. */
+                                       for (address = 0; address < eeprom->size; address++) {
+                                               eeprom->contents[address] &= eeprom->data;
+                                       }
+                               }
+                       }
+               }
+               /* Output DO is tristate, read results in 1. */
+               eedo = 1;
+       }
+       else if (eecs && !eeprom->eesk && eesk) {
+               /* Raising edge of clock shifts data in. */
+               if (tick == 0) {
+                       /* Wait for 1st start bit. */
+                       if (eedi == 0) {
+                               //write_log("Got correct 1st start bit, waiting for 2nd start bit (1)\n");
+                               tick++;
+                       }
+                       else {
+                               //write_log("wrong 1st start bit (is 1, should be 0)\n");
+                               tick = 2;
+                               //~ assert(!"wrong start bit");
+                       }
+               }
+               else if (tick == 1) {
+                       /* Wait for 2nd start bit. */
+                       if (eedi != 0) {
+                               //write_log("Got correct 2nd start bit, getting command + address\n");
+                               tick++;
+                       }
+                       else {
+                               ;//write_log("1st start bit is longer than needed\n");
+                       }
+               }
+               else if (tick < 2 + 2) {
+                       /* Got 2 start bits, transfer 2 opcode bits. */
+                       tick++;
+                       command <<= 1;
+                       if (eedi) {
+                               command += 1;
+                       }
+               }
+               else if (tick < 2 + 2 + eeprom->addrbits) {
+                       /* Got 2 start bits and 2 opcode bits, transfer all address bits. */
+                       tick++;
+                       address = ((address << 1) | eedi);
+                       if (tick == 2 + 2 + eeprom->addrbits) {
+                               //write_log("%s command, address = 0x%02x (value 0x%04x)\n", opstring[command], address, eeprom->contents[address]);
+                               if (command == 2) {
+                                       eedo = 0;
+                               }
+                               address = address % eeprom->size;
+                               if (command == 0) {
+                                       /* Command code in upper 2 bits of address. */
+                                       switch (address >> (eeprom->addrbits - 2)) {
+                                       case 0:
+                                               //write_log("write disable command\n");
+                                               eeprom->writeable = 0;
+                                               break;
+                                       case 1:
+                                               //write_log("write all command\n");
+                                               break;
+                                       case 2:
+                                               //write_log("erase all command\n");
+                                               break;
+                                       case 3:
+                                               //write_log("write enable command\n");
+                                               eeprom->writeable = 1;
+                                               break;
+                                       }
+                               }
+                               else {
+                                       /* Read, write or erase word. */
+                                       eeprom->data = eeprom->contents[address];
+                               }
+                       }
+               }
+               else if (tick < 2 + 2 + eeprom->addrbits + 16) {
+                       /* Transfer 16 data bits. */
+                       tick++;
+                       if (command == 2) {
+                               /* Read word. */
+                               eedo = ((eeprom->data & 0x8000) != 0);
+                       }
+                       eeprom->data <<= 1;
+                       eeprom->data += eedi;
+               }
+               else {
+                       ;//write_log("additional unneeded tick, not processed\n");
+               }
+       }
+       /* Save status of EEPROM. */
+       eeprom->tick = tick;
+       eeprom->eecs = eecs;
+       eeprom->eesk = eesk;
+       eeprom->eedo = eedo;
+       eeprom->address = address;
+       eeprom->command = command;
+}
+
+uae_u16 eeprom93xx_read(void *eepromp)
+{
+       eeprom93xx_eeprom_t *eeprom = (eeprom93xx_eeprom_t*)eepromp;
+       /* Return status of pin DO (0 or 1). */
+       //write_log("CS=%u DO=%u\n", eeprom->eecs, eeprom->eedo);
+       return eeprom->eedo;
+}
+
+uae_u8 eeprom93xx_read_byte(void *eepromp, int offset)
+{
+       eeprom93xx_eeprom_t *eeprom = (eeprom93xx_eeprom_t*)eepromp;
+       if (offset & 1)
+               return eeprom->contents[offset / 2];
+       else
+               return eeprom->contents[offset / 2] >> 8;
+}
+
+void *eeprom93xx_new(const uae_u8 *memory, int nwords, struct zfile *zf)
+{
+       /* Add a new EEPROM (with 16, 64 or 256 words). */
+       eeprom93xx_eeprom_t *eeprom;
+       uint8_t addrbits;
+
+       switch (nwords) {
+       case 16:
+       case 64:
+               addrbits = 6;
+               break;
+       case 128:
+       case 256:
+               addrbits = 8;
+               break;
+       default:
+               return NULL;
+       }
+
+       eeprom = (eeprom93xx_eeprom_t *)xcalloc(eeprom93xx_eeprom_t, 1);
+       eeprom->size = nwords;
+       eeprom->addrbits = addrbits;
+       for (int i = 0; i < nwords; i++) {
+               eeprom->contents[i] = (memory[i * 2 + 0] << 8) | memory[i * 2 + 1];
+       }
+       /* Output DO is tristate, read results in 1. */
+       eeprom->eedo = 1;
+       write_log("eeprom = 0x%p, nwords = %u\n", eeprom, nwords);
+       return eeprom;
+}
+
+void eeprom93xx_free(void *eepromp)
+{
+       eeprom93xx_eeprom_t *eeprom = (eeprom93xx_eeprom_t*)eepromp;
+
+       /* Destroy EEPROM. */
+       write_log("eeprom = 0x%p\n", eeprom);
+       xfree(eeprom);
+}
+
 /* I2C EEPROM */
 
 #define NVRAM_PAGE_SIZE 16
index 158595382f2b1877ac852e8520224695d0ad6aed..3b4c89c8702369e2dc6b6b4a1399cf82a6a488bd 100644 (file)
@@ -13,7 +13,7 @@ uae_u32 flash_read(void *fdv, uaecptr addr);
 bool flash_active(void *fdv, uaecptr addr);
 int flash_size(void *fdv);
 
-/* EPROM */
+/* I2C EEPROM */
 
 #define BITBANG_I2C_SDA 0
 #define BITBANG_I2C_SCL 1
@@ -27,4 +27,13 @@ int eeprom_i2c_set(void *i2c, int line, int level);
 #define FLASHROM_EVERY_OTHER_BYTE_ODD 2
 #define FLASHROM_PARALLEL_EEPROM 4
 
+/* MICROWIRE EEPROM */
+
+void eeprom93xx_write(void *eepromp, int eecs, int eesk, int eedi);
+uae_u16 eeprom93xx_read(void *eepromp);
+void *eeprom93xx_new(const uae_u8 *memory, int nwords, struct zfile *zf);
+void eeprom93xx_free(void *eepromp);
+uae_u8 eeprom93xx_read_byte(void *eepromp, int offset);
+
+
 #endif /* UAE_FLASHROM_H */