func: void eeprom93xx_write(eeprom_t *eeprom, int eecs, int eesk, int eedi)
  
  {
  
      uint8_t tick = eeprom->tick;
  
      uint8_t eedo = eeprom->eedo;
  
      uint16_t address = eeprom->address;
  
      uint8_t command = eeprom->command;
  
  
  
      logout("CS=%u SK=%u DI=%u DO=%u, tick = %u\n",
  
             eecs, eesk, eedi, eedo, tick);
  
  
  
      if (! eeprom->eecs && eecs) {
  
          /* Start chip select cycle. */
  
          logout("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->writable) {
  
              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) {
  
                  logout("Got correct 1st start bit, waiting for 2nd start bit (1)\n");
  
                  tick++;
  
              } else {
  
                  logout("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) {
  
                  logout("Got correct 2nd start bit, getting command + address\n");
  
                  tick++;
  
              } else {
  
                  logout("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) {
  
                  logout("%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:
  
                              logout("write disable command\n");
  
                              eeprom->writable = 0;
  
                              break;
  
                          case 1:
  
                              logout("write all command\n");
  
                              break;
  
                          case 2:
  
                              logout("erase all command\n");
  
                              break;
  
                          case 3:
  
                              logout("write enable command\n");
  
                              eeprom->writable = 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 {
  
              logout("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;
  
  }
  