How to change 93C46 libraray to 93C66

I'm new to writing and reading eeproms, sorry if my question is a bit stupid.

I want to try to read the 93c66 EEPROM, but I didn't find a suitable library for it, and I tried using this library from github GitHub - 0xJoey/Arduino_93C46: A simple library to interface an arduino with a 93C46 EEPROM chip
but the problem is that the data read is a little different when reading using ch341, there are some bytes that are different.

can someone help me what to change in the library to be able to read or write EEPROM 93c66 using arduino nano.

I appreciate all your answers, thank you.

They are from the same family and have a similar interface. From the data sheet the 93c66 uses more bits for addressing in the commands. It should be possible to modify a copy of the library to handle the 93c66 chip.

1 Like

I'm actually a programmer but I'm not good at electronics, and I don't understand how to read timing diagrams, is there a book that can teach about timing diagrams with Arduino?

The 93C is a serial EEPROM. This document may help
00536.pdf (154.7 KB)

You don't need to worry about the timing. The existing library handles that. Look at the address column in table 5 in the data sheet in the link in my post #2. The 93C66 uses 2 more address bits than the 93C46. The library code needs to be modified to send 2 more address bits. Some of the masks and shifts will need to be modified for the extra address bits.

where is the link to your post, I don't know how to see it, I very rarely use this forum

Scroll up 5 posts. This is post 7

OK, this was sufficiently interesting that I dug through my ancient chip collection and found a 93AA66 to try. Here are updated .h, .cpp and testcase for a 93xx66.

It supports both 8 and 16 bit modes. The author added 8 bit support even tho the documentation says 16 bit only.

Put in 93C66.h

=======================

/*
  93C66.h - Library for the 93C66 EEPROM chip in 64x16 mode
  Created by Joey Haas, Juli 7, 2018
  Released under the GNU General Public License v3.0
*/
#ifndef _93C66_h
#define _93C66_h

#include "Arduino.h"

#define EEPROM_93C66_MODE_8BIT 0
#define EEPROM_93C66_MODE_16BIT 1

class eeprom_93C66 {
  public:
  	eeprom_93C66(int pCS, int pSK, int pDI, int pDO);
    void set_mode(bool longMode);
  	void ew_disable();
  	void ew_enable();
  	bool is_ew_enabled();
  	void erase_all();
  	void write_all(word value);
  	void write(uint16_t addr, word value);
  	void erase(uint16_t addr);
    word read(uint16_t addr);
  private:
  	void send_bits(word value, int len);
  	void wait();
  	int _pCS;
  	int _pSK;
  	int _pDI;
  	int _pDO;
  	bool _ew;
    bool _mode;
};

#endif

===================================

Put in 93C66.cpp

====================================

/*
  93C66.h - Library for the 93C66 EEPROM chip in 64x16 mode
  Created by Joey Haas, Juli 7, 2018
  Released under the GNU General Public License v3.0
*/
#include "Arduino.h"
#include "93C66.h"

enum OP { // Operations
	WRITE 		= 0x40,
	READ 		= 0x80, 
	ERASE 		= 0xC0
};
enum CC { // Control Codes
	EW_DISABLE 	= 0x00, 
	WRITE_ALL 	= 0x40, 
	ERASE_ALL 	= 0x80, 
	EW_ENABLE 	= 0xC0
};

eeprom_93C66::eeprom_93C66(int pCS, int pSK, int pDI, int pDO) {
	pinMode(pCS, OUTPUT);
	pinMode(pSK, OUTPUT);
	pinMode(pDI, OUTPUT); 
	pinMode(pDO, INPUT);
	_pCS = pCS;
	_pSK = pSK;
	_pDI = pDI;
	_pDO = pDO;
	_ew = false;
	_mode = true;
};

void eeprom_93C66::set_mode(bool longMode) {
	_mode = longMode;
}

void eeprom_93C66::ew_enable() {
	digitalWrite(_pCS, HIGH);
	send_bits(HIGH, 1);
	if(_mode == EEPROM_93C66_MODE_16BIT) {
		send_bits(EW_ENABLE, 10);
	} else {
		send_bits(EW_ENABLE<<1, 11);
	}
	digitalWrite(_pCS, LOW);
	_ew = true;
};

void eeprom_93C66::ew_disable() {
	digitalWrite(_pCS, HIGH);
	send_bits(HIGH, 1);
	if(_mode == EEPROM_93C66_MODE_16BIT) {
		send_bits(EW_DISABLE, 10);
	} else {
		send_bits(EW_DISABLE<<1, 11);
	}
	digitalWrite(_pCS, LOW);
	_ew = false;
}

bool eeprom_93C66::is_ew_enabled() {
	return _ew;
}

void eeprom_93C66::erase_all() {
	if(!this->is_ew_enabled()) {
		return;
	}
	digitalWrite(_pCS, HIGH);
	send_bits(HIGH, 1);
	if(_mode == EEPROM_93C66_MODE_16BIT) {
		send_bits(ERASE_ALL, 10);
	} else {
		send_bits(ERASE_ALL<<1, 11);
	}
	digitalWrite(_pCS, LOW);
	wait();
}

void eeprom_93C66::write_all(word value) {
	if(!this->is_ew_enabled()) {
		return;
	}
	digitalWrite(_pCS, HIGH);
	send_bits(HIGH, 1);
	if(_mode == EEPROM_93C66_MODE_16BIT) {
		send_bits(WRITE_ALL, 10);
		send_bits(0xFFFF & value, 16);
	} else {
		send_bits(WRITE_ALL<<1, 11);
		send_bits(0xFF & value, 8);
	}
	digitalWrite(_pCS, LOW);
	wait();
}

void eeprom_93C66::write(uint16_t addr, word value) {
	if(!this->is_ew_enabled()) {
		return;
	}
	digitalWrite(_pCS, HIGH);
	send_bits(HIGH, 1);
	if(_mode == EEPROM_93C66_MODE_16BIT) {
		send_bits(((WRITE<<2) | (addr & 0xFF)), 10);
		send_bits(0xFFFF & value, 16);
	} else {
		send_bits(WRITE<<3| (addr & 0x1FF), 11);
		send_bits(0xFF & value, 8);
	}
	digitalWrite(_pCS, LOW);
	wait();
}

void eeprom_93C66::erase(uint16_t addr) {
	if(!this->is_ew_enabled()) {
		return;
	}
	digitalWrite(_pCS, HIGH);
	send_bits(HIGH, 1);
	if(_mode == EEPROM_93C66_MODE_16BIT) {
		send_bits(ERASE <<2 | (addr & 0xFF), 10);
	} else {
		send_bits(ERASE<<3 | (addr & 0x1FF), 11);
	}
	
	digitalWrite(_pCS, LOW);
	wait();
}

word eeprom_93C66::read(uint16_t addr) {
	word val = 0;
	digitalWrite(_pCS, HIGH);
	send_bits(HIGH, 1);
	int amtBits;
  
	if(_mode == EEPROM_93C66_MODE_16BIT) {
		send_bits(READ >> 6, 2);
		send_bits(addr, 8);
		amtBits = 16;
	} else {
		send_bits(READ<<3 | (addr & 0x1FF), 11);
		amtBits = 8;
	}
	// Read bits
	for(int i = amtBits; i>0; i--) {
		delayMicroseconds(1);
		digitalWrite(_pSK, HIGH);
		delayMicroseconds(1);
		byte in = digitalRead(_pDO) ? 1 : 0;
		digitalWrite(_pSK, LOW);
		val |= (in << (i-1));
	}
	digitalWrite(_pCS, LOW);
	return val;
}

void eeprom_93C66::send_bits(word value, int len) {

	for(int i = len-1; i>=0; i--)
	{
		bool toSend = (value & 1<<i);
		// Send bit
		digitalWrite(_pDI, toSend);
		delayMicroseconds(1);
		digitalWrite(_pSK, HIGH);
		delayMicroseconds(1);
		digitalWrite(_pSK, LOW);
		digitalWrite(_pDI, LOW);
	}
}

void eeprom_93C66::wait() {

	delayMicroseconds(1);

	//Wait until action is done.
	digitalWrite(_pCS, HIGH);
	while(digitalRead(_pDO) != HIGH) {
		delayMicroseconds(1);
	}
	digitalWrite(_pCS, LOW);

}

=================================

Put in write93C66.ino -- test program

=========================

#include "93C66.h"
/*
 * Example Sketch demonstration on how to write to (and read from) a 93C66 eeprom
 * 
 * Wiring:
 * Pin 7(CS) to Chip pin 1
 * Pin 9(SCK) to Chip pin 2
 * Pin 10(DI/MOSI) to Chip pin 3
 * Pin 11(DO/MISO) to Chip pin 4
 * 
 * (For some chips:) GND/VCC to Chip pin 6
 * This determines the organization:
 * HIGH is 256x16 (Use EEPROM_MODE_16BIT)
 * LOW is 512x8 (Use EEPROM_MODE_8BIT)
 * 
 */
#define pCS 7
#define pSK 9
#define pDI 10
#define pDO 11

// Prints all words of the buffer
void debugPrint(word* buff, int len) {
  Serial.print("\n\t00\t01\t02\t03\t04\t05\t06\t07\t08\t09\t0A\t0B\t0C\t0D\t0E\t0F");
  for(int i = 0; i < len; i++) {
    if(i % 16 == 0) {
      Serial.println();
      Serial.print(i, HEX);
    }
    Serial.print("\t");
    if(buff[i] < 0x10) {
      Serial.print("0");
    }
    Serial.print(buff[i], HEX);
  }
}

void setup() {
  bool longMode = EEPROM_93C66_MODE_16BIT;
 // bool longMode = EEPROM_93C66_MODE_8BIT ;
  
  eeprom_93C66 e = eeprom_93C66(pCS, pSK, pDI, pDO);
  e.set_mode(longMode);
  Serial.begin(115200);

  Serial.println("Writing data...");
  // First, enable EW (Erase/Write)
  e.ew_enable();

  String writeBuffer;
  if(longMode) {
    writeBuffer = "This is a string written in the 16-bit organization.\nHi, world!\0";
  } else {
    writeBuffer = "This is a string written in the 8-bit organization.\nAs you can see, the address space for this mode is much bigger!\nHey, world!\0";
  }

  int len = longMode ? 64 : 128;     // Increase size for more data up to 128 : 512
  // Write your data
  for(int i = 0; i < len; i++) {
    e.write(i, writeBuffer[i]);
  }

  // Optionally, disable EW after writing
  e.ew_disable();

  Serial.println("Reading data...\n");
  word readBuffer[len];
  for(int i = 0; i < len; i++) {
    word r = e.read(i);
    readBuffer[i] = r;
    Serial.print(char(r));
  //      Serial.print(" return value from read ");
  //      Serial.println(r,HEX);
  }
  debugPrint(readBuffer, len);
  Serial.println();
}

void loop() {}
1 Like

thank you for your help, I have tried to read eeprom with this and it is rather accurate although there are some bytes that are different but I think it is normal because in CH341 it is also so, but I have not tested to write EEPROM, later I will try to write eeprom and tell you whether it is a problem or not.

Thank you for your help

like there is an error, the data written is different, or there is a byte 00 that is not included in the data that has been written.

Code:

#include <93C66.h>

// #include "93C66.h"
/*
 * Example Sketch demonstration on how to write to (and read from) a 93C66 eeprom
 * 
 * Wiring:
 * Pin 7(CS) to Chip pin 1
 * Pin 9(SCK) to Chip pin 2
 * Pin 10(DI/MOSI) to Chip pin 3
 * Pin 11(DO/MISO) to Chip pin 4
 * 
 * (For some chips:) GND/VCC to Chip pin 6
 * This determines the organization:
 * HIGH is 256x16 (Use EEPROM_MODE_16BIT)
 * LOW is 512x8 (Use EEPROM_MODE_8BIT)
 * 
 */
#define pCS 7
#define pSK 9
#define pDI 10
#define pDO 11
uint8_t writeBuffer[512] = {
  0xA2, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xDA, 0x6E,
  0xFF, 0xFF, 0x4B, 0x30, 0x1C, 0x88, 0xFF, 0xFF,
  0x20, 0x00, 0x00, 0x00, 0x4B, 0x22, 0xD0, 0x07,
  0xA0, 0x0F, 0x70, 0x17, 0xE0, 0x2E, 0x2E, 0xA3,
  0xE9, 0x02, 0x99, 0x05, 0x2F, 0x08, 0x0B, 0x10,
  0xB4, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0x6C, 0x03, 0x12, 0x00, 0xFF, 0xFF,
  0x96, 0xFF, 0xEB, 0x00, 0xCE, 0x02, 0x9F, 0x02,
  0x6D, 0x02, 0x1B, 0x02, 0xD8, 0x77, 0x8B, 0x01,
  0xBC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x09,
  0x57, 0x01, 0x89, 0x01, 0xFF, 0xFF, 0xFF, 0xFF,
  0x21, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0x1F, 0x06, 0xE0, 0xF9, 0x1F, 0x06, 0xE0, 0xF9,
  0x1F, 0x06, 0xE0, 0xF9, 0x1F, 0x06, 0xE0, 0xF9,
  0x1F, 0x06, 0xE0, 0xF9, 0x1F, 0x06, 0xE0, 0xF9,
  0x1F, 0x06, 0xE0, 0xF9, 0x1F, 0x06, 0xE0, 0xF9,
  0x1F, 0x06, 0xE0, 0xF9, 0x1F, 0x06, 0xE0, 0xF9,
  0x1F, 0x06, 0xE0, 0xF9, 0x1F, 0x06, 0xE0, 0xF9,
  0x1F, 0x06, 0xE0, 0xF9, 0x1F, 0x06, 0xE0, 0xF9,
  0x1F, 0x06, 0xE0, 0xF9, 0x1F, 0x06, 0xE0, 0xF9,
  0x1F, 0x06, 0xE0, 0xF9, 0x1F, 0x06, 0xE0, 0xF9,
  0x1F, 0x06, 0xE0, 0xF9, 0x1F, 0x06, 0xE0, 0xF9,
  0x1F, 0x06, 0xE0, 0xF9, 0x1F, 0x06, 0xE0, 0xF9,
  0x1F, 0x06, 0xE0, 0xF9, 0x1F, 0x06, 0xE0, 0xF9,
  0xCE, 0x18, 0x31, 0xE7, 0xD6, 0x00, 0x29, 0xE2,
  0xB6, 0x6A, 0x23, 0xE2, 0xCE, 0x04, 0x35, 0xE3,
  0x80, 0x5E, 0x21, 0xE3, 0x34, 0x53, 0x98, 0xE2,
  0x7C, 0x60, 0xE3, 0xE2, 0x46, 0x0C, 0xB5, 0xE2,
  0xD2, 0x2B, 0x06, 0xE0, 0xA8, 0x1F, 0x48, 0xE3,
  0x12, 0x0B, 0xE6, 0x01, 0x00, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xEA, 0x00, 0x71,
  0x00, 0xFF, 0xFF, 0xFF, 0x64, 0x02
};
// Prints all words of the buffer
void debugPrint(word* buff, int len) {
  Serial.print("\n\t00\t01\t02\t03\t04\t05\t06\t07\t08\t09\t0A\t0B\t0C\t0D\t0E\t0F");
  for(int i = 0; i < len; i++) {
    if(i % 16 == 0) {
      Serial.println();
      Serial.print(i, HEX);
    }
    Serial.print("\t");
    if(buff[i] < 0x10) {
      Serial.print("0");
    }
    Serial.print(buff[i], HEX);
  }
}

word swapBytes(word value) {
    return (value >> 8) | (value << 8);
}


void setup() {
  bool longMode = EEPROM_93C66_MODE_16BIT;
//  bool longMode = EEPROM_93C66_MODE_8BIT ;
  
  eeprom_93C66 e = eeprom_93C66(pCS, pSK, pDI, pDO);
  e.set_mode(longMode);
  Serial.begin(115200);

  Serial.println("Writing data...");
  // First, enable EW (Erase/Write)
  e.ew_enable();

  // if(longMode) {
  //   writeBuffer = "This is a string written in the 16-bit organization.\nHi, world!\0";
  // } else {
  //   writeBuffer = "This is a string written in the 8-bit organization.\nAs you can see, the address space for this mode is much bigger!\nHey, world!\0";
  // }

  int len = 256;//longMode ? 128 : 512;     // Increase size for more data up to 128 : 512
  // Write your data
  for(int i = 0; i < len; i++) {
    e.write(i, writeBuffer[i]);
    Serial.println(String(i));
  }

  // Optionally, disable EW after writing
  e.ew_disable();
  Serial.println("Writing data succes");

  Serial.println("Reading data...\n");
  uint16_t readBuffer[len];
  for (int i = 0; i < len; i++) {
      word r = e.read(i); 
      word swapped = swapBytes(r); 
      readBuffer[i] = swapped; 
      
      char buffer[6];
      sprintf(buffer, "%04X", swapped);
      Serial.print(buffer);
      Serial.print(" ");
  }
}

void loop() {}

output:

Writing data...
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
....
254
255
Writing data succes
Reading data...
 A200 0000 FF00 FF00 FF00 FF0F DA00 6E00 FF00
 FF00 4B00 3000 1C00 8800 FF00 FF00 2000 0080
 0000 0000 4B00 2200 D000 0700 A000 0F00 7000
 1700 E000 FFFF 2E00 A300 E900 0200 9900 0500
 2F00 0800 0B00 1000 0000 F300 FF00 FF00 FF00
 FF00 FF00 FF00 FF00 FF00 FF00 FF00 0700 FF00
 FF00 FF00 FF00 FF00 6C00 0300 1200 0000 FF00
 FF00 0000 FF00 EB00 0000 CE00 0200 9F00 0200
 6D00 0200 1B00 0200 FF03 7700 8B00 0100 BC00
 0000 FF00 FF00 FF00 FF00 C900 0900 0080 0100
 8900 0100 FF00 FF00 FF00 FF00 2100 0F00 FF00
 FF00 F0FF FF00 FF00 FF00 1F00 0600 E000 F900
 1F00 0600 E000 FF00 FFFF 0600 E000 F900 1F00
 0600 E000 F900 1F00 0600 E000 0000 1F00 0600
 E000 F900 FFFF 0600 E000 F900 1F00 0600 E000
 0100 1F00 0600 E000 F900 FFFF FFFF FFFF FFFF
 FFFF FFFF FFFF 0000 FFFF FFFF FFFF FFFF FFFF

so every 1 byte step there is byte 00 which should not be included when written before, which should be A200FF instead of A2000000FF, so there are additional bytes that should not be there.

You are writing in 16 bit mode. each byte will be converted to 16 bits on the write. Change to 8 bit mode and ground the ORG pin (pin 5).

Comment out the 16 bit mode and uncomment 8 bit mode.

  bool longMode = EEPROM_93C66_MODE_16BIT;
//  bool longMode = EEPROM_93C66_MODE_8BIT ;

OOPS - The ORG pin is pin 6 (pin 5 is ground).

is it possible without org pins? because some devices don't use ORG pins.

okay problem solved

uint16_t writeBuffer[512] = {
  0xA200, 0xFFFF, 0xFFFF, 0xDA6E,
  0xFFFF, 0x4B30, 0x1C88, 0xFFFF,
  0x2000, 0x0000, 0x4B22, 0xD007,
  0xA00F, 0x7017, 0xE02E, 0x2EA3,
  0xE902, 0x9905, 0x2F08, 0x0B10,
  0xB4F3, 0xFFFF, 0xFFFF, 0xFFFF,
  0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
  0xFFFF, 0x6C03, 0x1200, 0xFFFF,
  0x96FF, 0xEB00, 0xCE02, 0x9F02,
  0x6D02, 0x1B02, 0xD877, 0x8B01,
  0xBC00, 0xFFFF, 0xFFFF, 0xC909,
  0x5701, 0x8901, 0xFFFF, 0xFFFF,
  0x210F, 0xFFFF, 0xFFFF, 0xFFFF,
  0x1F06, 0xE0F9, 0x1F06, 0xE0F9,
  0x1F06, 0xE0F9, 0x1F06, 0xE0F9,
  0x1F06, 0xE0F9, 0x1F06, 0xE0F9,
  0x1F06, 0xE0F9, 0x1F06, 0xE0F9,
  0x1F06, 0xE0F9, 0x1F06, 0xE0F9,
  0x1F06, 0xE0F9, 0x1F06, 0xE0F9,
  0x1F06, 0xE0F9, 0x1F06, 0xE0F9,
  0x1F06, 0xE0F9, 0x1F06, 0xE0F9,
  0x1F06, 0xE0F9, 0x1F06, 0xE0F9,
  0x1F06, 0xE0F9, 0x1F06, 0xE0F9,
  0x1F06, 0xE0F9, 0x1F06, 0xE0F9,
  0x1F06, 0xE0F9, 0x1F06, 0xE0F9,
  0xCE18, 0x31E7, 0xD600, 0x29E2,
  0xB66A, 0x23E2, 0xCE04, 0x35E3,
  0x805E, 0x21E3, 0x3453, 0x98E2,
  0x7C60, 0xE3E2, 0x460C, 0xB5E2,
  0xD22B, 0x06E0, 0xA81F, 0x48E3,
  0x120B, 0xE601, 0x00FF, 0xFFFF,
  0xFFFF, 0xFF00, 0x00EA, 0x0071,
  0x00FF, 0xFFFF, 0x6402
};

output

8
9
10
11
12
13
14
15
....
252
253
254
255
Writing data succes
Reading data...
00A2 FFFF FFFF 6EDA FFFF 304B 881C FFFF 
0020 0000 0000 07D0 0FA0 1770 FF00 A32E 
2000 0599 0000 100B F3B4 FFFF FFFF FFFF 
FFFF FFFF FFFF FFFF E000 036C 0012 FFFF 
FF96 00EB 0000 029F 026D 021B 77D8 
1000 00BC FFFF FFFF 09C9 0157 0189 
00FC FFFF 0F21 FFFF FFFF FF00 061F F9E0 
061F F9E0 061F F8E0 FFFF F9E0 061F F9E0 
061F FF00 061F F9E0 061F F9E0 061F F0E0 
0000 F9E0 061F F9E0 061F 0200 061F F9E0 
061F F9E0 061F FFE0 FFFF F9E0 061F F9E0 
061F 0900 061F F9E0 061F F9E0 061F 00E0 
0000 F9E0 061F F9E0 061F FF00 18CE E731 
00D6 E229 6AB6 7F20 04CE E335 5E80 E321 
5334 F900 607C E2E3 0C46 E2B5 2BD2 0000 
1FA8 E348 0B12 01E6 FF00 F900 FFFF 00FF 
EA00 7100 FF00 00FC 0264 0000 0000 0000 
0000 F900 0000 0000 0000 0000 0000 0000 
0000 0000 0000 0000 0000 F900 0000 0000 
0000 0000 0000 0000 0000 0000 0000 0000
 0000 F900 0000 0000 0000 0000 0000 0000 
00FF 0000 0000 0000 0000 F900 0000 0000 
0000 0000 0000 0000 F800 0000 0000 0000 
0000 F900 0000 0000 0000 0000 0000 0000 
FFFF 0000 0000 0000 0000 F900 0000 0000 
0000 0000 0000 0000 0000 0000 0000 0000 
0000 E200 0000 0000 0000 0000 0000 0000 
A2FE 0000 0000 0000 0000 E300 0000 0000 
0000 0000 0000 0000 0000 0000 0000 0000
 0000 E200 0000 0000 0000 0000 0000 0000 
A200 0000 0000 0000 0000 0100 0000 0000 
0000 0000 0000 0000 0000 0000 0000 0000 
0000 7100 

With the newer chips the A and B suffix are organized as 8bit and 16 bit only, so you can only use them in the fixed mode. The C suffix has the option.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.