Hi all,
Here a piece of code (for Olimexino using libmapple which is the same as the one used by Arduino) that allows read and write for a 93LC46B1 EEPROM chip memory.
I used it to reprogram my garage door transmitter 
#define PIN_CS D2
#define PIN_CLK D4
#define PIN_DI D5
#define PIN_DO D6
boolean _clockEnabled;
int _clockNextLevel;
int _readData = 0; // 0 = disabled, 1,2,3 = send opcode, 4,5,6,7,8,9 = send addr, ... read value
uint8 _readDataAddr = 0;
uint16 _readDataData = 0;
int _enableWrite = 0; // 0 = disabled
int _disableWrite = 0; // 0 = disabled
int _writeData = 0;
uint8 _writeDataAddr = 0;
uint16 _writeDataData = 0;
void setup() {
pinMode(PIN_CS, OUTPUT);
pinMode(PIN_CLK, OUTPUT);
pinMode(PIN_DI, OUTPUT);
pinMode(PIN_DO, INPUT);
_clockEnabled = false;
}
int _addressToRead = 0;
void loop() {
updateClock(); // Mandatory function
// Usage exemple : Be carreful : readAddress(), enableWrite(), disableWrite() and WriteAddress() are asynchronous.
if (SerialUSB.available()) {
int c = SerialUSB.read();
if (c == 'r') readAddress(42); // Read address 42
if (c == 'e') enableWrite(); // Enable write access! Required before any writeAddress call
if (c == 'd') disableWrite(); // Disable write access!
if (c == 'w') writeAddress(42, 6969); // Write 6969 to address 42
}
}
void updatePinStatus()
{
// Enable write command
if (_enableWrite > 0)
{
_enableWrite++;
switch(_enableWrite - 1)
{
case 1: digitalWrite(PIN_DI, HIGH); break;
case 2: digitalWrite(PIN_DI, LOW); break;
case 3: digitalWrite(PIN_DI, LOW); break;
case 4: digitalWrite(PIN_DI, HIGH); break;
case 5: digitalWrite(PIN_DI, HIGH); break;
case 6: digitalWrite(PIN_DI, HIGH); break; //X
case 7: digitalWrite(PIN_DI, HIGH); break; //X
case 8: digitalWrite(PIN_DI, HIGH); break; //X
case 9: digitalWrite(PIN_DI, HIGH); break; //X
case 10: digitalWrite(PIN_DI, HIGH); break; //X
case 11: digitalWrite(PIN_DI, HIGH); break; //X
case 12:
stopClock();
_enableWrite = 0;
delayMicroseconds(10); // Necessary according the datasheet (at least 250ns)
enableWriteComplete();
break;
}
}
// Disable write command
if (_disableWrite > 0)
{
_disableWrite++;
switch(_disableWrite - 1)
{
case 1: digitalWrite(PIN_DI, HIGH); break;
case 2: digitalWrite(PIN_DI, LOW); break;
case 3: digitalWrite(PIN_DI, LOW); break;
case 4: digitalWrite(PIN_DI, LOW); break;
case 5: digitalWrite(PIN_DI, LOW); break;
case 6: digitalWrite(PIN_DI, HIGH); break; //X
case 7: digitalWrite(PIN_DI, HIGH); break; //X
case 8: digitalWrite(PIN_DI, HIGH); break; //X
case 9: digitalWrite(PIN_DI, HIGH); break; //X
case 10: digitalWrite(PIN_DI, HIGH); break; //X
case 11: digitalWrite(PIN_DI, HIGH); break; //X
case 12:
stopClock();
_disableWrite = 0;
delayMicroseconds(10); // Necessary according the datasheet (at least 250ns)
disableWriteComplete();
break;
}
}
if (_writeData > 0) {
_writeData++;
switch(_writeData - 1)
{
case 1: digitalWrite(PIN_DI, HIGH); break;
case 2: digitalWrite(PIN_DI, LOW); break;
case 3: digitalWrite(PIN_DI, HIGH); break;
case 4: digitalWrite(PIN_DI, (_writeDataAddr >> 5) & 0x01); break;
case 5: digitalWrite(PIN_DI, (_writeDataAddr >> 4) & 0x01); break;
case 6: digitalWrite(PIN_DI, (_writeDataAddr >> 3) & 0x01); break;
case 7: digitalWrite(PIN_DI, (_writeDataAddr >> 2) & 0x01); break;
case 8: digitalWrite(PIN_DI, (_writeDataAddr >> 1) & 0x01); break;
case 9: digitalWrite(PIN_DI, (_writeDataAddr >> 0) & 0x01); break;
case 10: digitalWrite(PIN_DI, (_writeDataData >> 15) & 0x01); break;
case 11: digitalWrite(PIN_DI, (_writeDataData >> 14) & 0x01); break;
case 12: digitalWrite(PIN_DI, (_writeDataData >> 13) & 0x01); break;
case 13: digitalWrite(PIN_DI, (_writeDataData >> 12) & 0x01); break;
case 14: digitalWrite(PIN_DI, (_writeDataData >> 11) & 0x01); break;
case 15: digitalWrite(PIN_DI, (_writeDataData >> 10) & 0x01); break;
case 16: digitalWrite(PIN_DI, (_writeDataData >> 9) & 0x01); break;
case 17: digitalWrite(PIN_DI, (_writeDataData >> 8) & 0x01); break;
case 18: digitalWrite(PIN_DI, (_writeDataData >> 7) & 0x01); break;
case 19: digitalWrite(PIN_DI, (_writeDataData >> 6) & 0x01); break;
case 20: digitalWrite(PIN_DI, (_writeDataData >> 5) & 0x01); break;
case 21: digitalWrite(PIN_DI, (_writeDataData >> 4) & 0x01); break;
case 22: digitalWrite(PIN_DI, (_writeDataData >> 3) & 0x01); break;
case 23: digitalWrite(PIN_DI, (_writeDataData >> 2) & 0x01); break;
case 24: digitalWrite(PIN_DI, (_writeDataData >> 1) & 0x01); break;
case 25: digitalWrite(PIN_DI, (_writeDataData >> 0) & 0x01); break;
case 26:
digitalWrite(PIN_DI, LOW);
digitalWrite(PIN_CS, LOW);
break;
case 27:
digitalWrite(PIN_CS, HIGH);
break;
default:
if (digitalRead(PIN_DO) == HIGH) {
stopClock();
_writeData = 0;
writeAddressComplete();
_writeDataAddr = 0;
_writeDataData = 0;
}
break;
}
}
// Send address to read (16bits)
if (_readData > 0) {
_readData++;
switch(_readData - 1)
{
case 1: digitalWrite(PIN_DI, HIGH); break;
case 2: digitalWrite(PIN_DI, HIGH); break;
case 3: digitalWrite(PIN_DI, LOW); break;
case 4: digitalWrite(PIN_DI, (_readDataAddr >> 5) & 0x01); break;
case 5: digitalWrite(PIN_DI, (_readDataAddr >> 4) & 0x01); break;
case 6: digitalWrite(PIN_DI, (_readDataAddr >> 3) & 0x01); break;
case 7: digitalWrite(PIN_DI, (_readDataAddr >> 2) & 0x01); break;
case 8: digitalWrite(PIN_DI, (_readDataAddr >> 1) & 0x01); break;
case 9: digitalWrite(PIN_DI, (_readDataAddr >> 0) & 0x01); break;
case 10: digitalWrite(PIN_DI, LOW); break;
case 11: _readDataData += digitalRead(PIN_DO) << 15; break;
case 12: _readDataData += digitalRead(PIN_DO) << 14; break;
case 13: _readDataData += digitalRead(PIN_DO) << 13; break;
case 14: _readDataData += digitalRead(PIN_DO) << 12; break;
case 15: _readDataData += digitalRead(PIN_DO) << 11; break;
case 16: _readDataData += digitalRead(PIN_DO) << 10; break;
case 17: _readDataData += digitalRead(PIN_DO) << 9; break;
case 18: _readDataData += digitalRead(PIN_DO) << 8; break;
case 19: _readDataData += digitalRead(PIN_DO) << 7; break;
case 20: _readDataData += digitalRead(PIN_DO) << 6; break;
case 21: _readDataData += digitalRead(PIN_DO) << 5; break;
case 22: _readDataData += digitalRead(PIN_DO) << 4; break;
case 23: _readDataData += digitalRead(PIN_DO) << 3; break;
case 24: _readDataData += digitalRead(PIN_DO) << 2; break;
case 25: _readDataData += digitalRead(PIN_DO) << 1; break;
case 26: _readDataData += digitalRead(PIN_DO) << 0; break;
case 27:
stopClock();
_readData = 0;
readAddressComplete();
_readDataAddr = 0;
_readDataData = 0;
break;
}
}
}
void readAddress(uint8 addr) {
_readData = 1;
_readDataAddr = addr;
_readDataData = 0;
startClock();
}
void writeAddress(uint8 addr, uint16 data) {
_writeData = 1;
_writeDataAddr = addr;
_writeDataData = data;
startClock();
}
void disableWrite() {
_disableWrite = 1;
startClock();
}
void enableWrite() {
_enableWrite = 1;
startClock();
}
void readAddressComplete() {
SerialUSB.print("Read address [");
SerialUSB.print(_readDataAddr);
SerialUSB.print("] = ");
SerialUSB.println(_readDataData);
}
void writeAddressComplete() {
SerialUSB.print("Write address [");
SerialUSB.print(_writeDataAddr);
SerialUSB.print("] = ");
SerialUSB.println(_writeDataData);
}
void enableWriteComplete() {
SerialUSB.println("Write mode enabled");
}
void disableWriteComplete() {
SerialUSB.println("Write mode disabled");
}
void startClock() {
digitalWrite(PIN_CS, HIGH);
digitalWrite(PIN_DI, LOW);
digitalWrite(PIN_CLK, LOW);
_clockEnabled = true;
_clockNextLevel = HIGH;
}
void stopClock() {
digitalWrite(PIN_CS, LOW);
digitalWrite(PIN_DI, LOW);
digitalWrite(PIN_CLK, LOW);
_clockEnabled = false;
_clockNextLevel = LOW;
}
void updateClock() {
if (!_clockEnabled)
return ;
digitalWrite(PIN_CLK, _clockNextLevel);
if (_clockNextLevel == LOW) updatePinStatus();
_clockNextLevel = (_clockNextLevel == HIGH) ? LOW : HIGH;
delayMicroseconds(100); // Master clock period / 2
}