Go Down

Topic: i2c EEPROM modifier with LCD interface (Read 629 times) previous topic - next topic

FalconFour

Oct 20, 2010, 05:48 pm Last Edit: Oct 20, 2010, 05:59 pm by FalconFour Reason: 1
Only thing missing is figuring out why PS2Keyboard doesn't work, although I'm sure the interface could be modified to use an array of button inputs...

Anyway, this is a program I whipped up overnight to reprogram a laptop battery that I'd replaced the cells in, that had a corrupted "last discharge" reading... honestly, going into it I had no idea what I was in for, but once I was able to pull the string "SANYO" out of the memory, based on the controller's data sheet, I knew I was in the right place. From there I edited the values for the "last discharge", and sure enough, after resetting the controller (disconnecting/reconnecting the leads), it worked beautifully.

But that's beside the point. ;) This is a great little tool for reading small-capacity (8-bit address) EEPROMs. Taken from the code sample provided here (by the way, the link to ghettohax.com on that page is dead, anyone know an alternative? I had to wing-it on the I2C wiring), and modified for 8-bit addressing. Modify as desired for 16-bit addressing.

It's a little quick-and-dirty but I figured that, with all the internet-searching I was doing with this thing, this is the least I could do to contribute something back. :)

Without further adieu...
Code: [Select]
//#include <PS2Keyboard.h>
#include <LiquidCrystal.h>
#include <Wire.h>

LiquidCrystal lcd(12,13,3,4,5,6);
//PS2Keyboard keyboard;

char lcdBuffer[17] = "                ";
char byteBuffer[3] = "00";
int result = 0;
char outputString[3] = "00";
byte cursorPos = 0;
byte addrByte = 0;
boolean rwMode = false;

//const int DataPin = 9;
//const int IRQpin =  2;

boolean redrawScreen = true;

void setup() {
 Wire.begin();
 delay(1000);
//  keyboard.begin(DataPin, IRQpin);
 Serial.begin(9600);
 lcd.begin(16,2);
 lcd.cursor();
 lcd.blink();
 lcd.setCursor(0,0);
 lcd.print("Addr   Data    R");
}

void loop() {
 if (Serial.available()) {
   // do sh#t if key pressed
   char c = Serial.read();
   if (c == '!') {
     if (rwMode) {
       // write
       addrByte = strtol(byteBuffer,0,16);
       result = strtol(outputString,0,16);
       i2c_eeprom_write_byte(B1010000,addrByte,result);
     } else {
       // read
       addrByte = strtol(byteBuffer,0,16);
       result = i2c_eeprom_read_byte(B1010000,addrByte);
       itoa(result,outputString,16);
     }
     redrawScreen = true;
     lcd.setCursor(14,0);
     lcd.print('!');
   } else if (c == '<') {
     if (cursorPos > 0) cursorPos--;
     if (cursorPos == 6) cursorPos = 1;
     lcd.setCursor(cursorPos,1);
   } else if (c == '>') {
     if (rwMode) {
       if (cursorPos < 8) cursorPos++;
       if (cursorPos == 2) cursorPos = 7;
     } else {
       if (cursorPos < 1) cursorPos++;
     }
     lcd.setCursor(cursorPos,1);
   } else if (c == 'w') {
     rwMode = rwMode?false:true;
     if (!rwMode && cursorPos > 1) cursorPos = 1;
     redrawScreen = true;
   } else {
     // detect and enter keys
     // catch numbers
     if (c >= '0') {
       if (c <= '9') {
         if (cursorPos > 1) outputString[cursorPos-7] = c;
         else byteBuffer[cursorPos] = c;
       }
     }
     // catch capital A-F
     if (c >= 'A') {
       if (c <= 'F') {
         if (cursorPos > 1) outputString[cursorPos-7] = c;
         else byteBuffer[cursorPos] = c;
       }
     }
     if (cursorPos < 1) cursorPos++;
     redrawScreen = true;
     lcd.setCursor(14,0);
     lcd.print(' ');
   }
 }
 // sh#t to do every loop
 if (redrawScreen) {
   lcd.setCursor(15,0);
   lcd.print(rwMode?'W':'R');
   lcd.setCursor(0,1);
   lcd.print("                ");
   lcd.setCursor(0,1);
   lcd.print(byteBuffer);
   lcd.setCursor(7,1);
   lcd.print(outputString);    
   lcd.setCursor(cursorPos,1);
   delay(100);
   redrawScreen = false;
 }
}

byte i2c_eeprom_read_byte( int deviceaddress, byte eeaddress ) {
 byte rdata = 0xFF;
 Wire.beginTransmission(deviceaddress);
//  Wire.send((int)(eeaddress >> 8)); // MSB
 Wire.send(eeaddress); // LSB
 Wire.endTransmission();
 Wire.requestFrom(deviceaddress,1);
 if (Wire.available()) rdata = Wire.receive();
 return rdata;
}

void i2c_eeprom_write_byte( int deviceaddress, byte eeaddress, byte data ) {
 int rdata = data;
 Wire.beginTransmission(deviceaddress);
//  Wire.send((int)(eeaddress >> 8)); // MSB
 Wire.send(eeaddress); // LSB
 Wire.send(rdata);
 Wire.endTransmission();
}


And a little Fritzing (also my first time playing with that), and a photo...


Usage:

Screen shows two indicators in the upper-right corner: "!" and R/W. The "!" will appear when the read/write operation was completed (otherwise, well... the Arduino locks up). R or W indicates if it's currently in Read or Write mode.

Currently, in a serial console, you can send the following commands:
"w" (lowercase w): switch between read/write mode
"!": perform the read/write action (displays the value in read mode, writes the "Data" value in write mode)
"<": move the cursor to the left
">": move the cursor to the right
0-9, A-F: modify the selected digit under the cursor. Data can only be modified in write mode.

And of course, any tips for improvement will only help my Arduino addiction. ;)

Extra special thanks to you (specifically p. 38-40), and you, and you for helping me with the distinction between I2C device address and data address... :D

Go Up