/*
MicrowireEEPROM Arduino Library Source File to
Read and write a Microwire EEPROM.
Written by Timo S <[email protected]>
Mods by MarkGen (MG).
notes by kiev, 10/23/2019
This code was found on github in the public domain.
*/
#include "Arduino.h"
#include "MicrowireEEPROM.h"
// class :: member
MicrowireEEPROM::MicrowireEEPROM(int cs_pin, int clk_pin, int di_pin,
int do_pin, int pg_size, int addr_width,
int clock_period)
{
//use the "this" pointer for current class member reference
this->CS = cs_pin;
this->CLK = clk_pin;
this->DI = di_pin;
this->DO = do_pin;
this->ADDRWIDTH = addr_width;
this->PAGESIZE = pg_size;
this->HALF_CLOCK_PERIOD = clock_period / 2;
// make CS, CLK, DI outputs
pinMode(CS, OUTPUT);
pinMode(CLK, OUTPUT);
pinMode(DI, OUTPUT);
// make DO an input
pinMode(DO, INPUT);
}
// member function used to either send or read some data value
long MicrowireEEPROM::transmit(int data, int bits)
{
int dout = 0; //create loop to shift bits
for (int i=(bits-1); i>=0; i--) {
dout |= ((int) digitalRead(DO)) << i;//read bit, typecast it,
//then bitshift left and compound OR to get new dout integer
if ((1 << i) & data) {
digitalWrite(DI, HIGH);//send data
}
else {
digitalWrite(DI, LOW);
}
delayMicroseconds(HALF_CLOCK_PERIOD);
digitalWrite(CLK, HIGH);
delayMicroseconds(HALF_CLOCK_PERIOD);
digitalWrite(CLK, LOW);
}
digitalWrite(DI, LOW);
return dout;
}
void MicrowireEEPROM::send_opcode(char op)
{
//------
//MG added to ensure CS & DI are low before
//making them HIGH.
digitalWrite(CS, LOW);
digitalWrite(DI, LOW);
//----------
//MG - Commented out
//digitalWrite(CLK, HIGH);
//delayMicroseconds(HALF_CLOCK_PERIOD);
//----------
digitalWrite(CLK, LOW);
delayMicroseconds(HALF_CLOCK_PERIOD); //MG added to
//ensure adequate time for CLK to go LOW
//93LC86 Must have CS & DI High on positive
//edge of the clock bit
digitalWrite(CS, HIGH);
digitalWrite(DI, HIGH);
// transmit start bit and two bit opcode
transmit((1 << 2) | op, 3);
}
//class member function to read a memory address
int MicrowireEEPROM::read(int addr)
{
send_opcode(2); //the opcode for read is 02
transmit(addr, ADDRWIDTH); //sends the desired address
//a leading dummy zero is returned, add extra bit holder
long data = transmit(0, PAGESIZE+1); //return with the value
digitalWrite(CS, LOW);
return data;
}
void MicrowireEEPROM::writeEnable(void)
{
send_opcode(0);
//---------------------------------
//transmit(0xFF, ADDRWIDTH);
//MG - Increased 1's data from 8 bits to 16bit
//EEPROM 93LC86 has 11/10 bit Adress width
//0xFF is 0000 0000 1111 1111 results in sending
//leading zeros for ADW's > 8
//0xFFFF fills all 16 bits of the INT with 1's
//0xFFFF = 1111 1111 1111 1111
transmit(0xFFFF, ADDRWIDTH);
digitalWrite(CS, LOW);
}
void MicrowireEEPROM::writeDisable(void)
{
send_opcode(0);
transmit(0x00, ADDRWIDTH);
digitalWrite(CS, LOW);
}
void MicrowireEEPROM::write(int addr, int data)
{
send_opcode(1);
transmit(addr, ADDRWIDTH);
transmit(data, PAGESIZE);
digitalWrite(CS, LOW);
}