Skip to content

Instantly share code, notes, and snippets.

@justarandomgeek
Created April 24, 2021 22:02
Show Gist options
  • Save justarandomgeek/a28fd8783c7e69af33859a3b79f3191a to your computer and use it in GitHub Desktop.
Save justarandomgeek/a28fd8783c7e69af33859a3b79f3191a to your computer and use it in GitHub Desktop.
arduino mega eeprom read/write
/*
D = address 16..23
C = address 8..15
A = address 0..7
L = data 0..7
B0 = !OE
B1 = !WE
B2 = !CE
*/
constexpr uint8_t OE = 1;
constexpr uint8_t WE = 2;
constexpr uint8_t CE = 4;
constexpr int blocksize = 128;
void setaddr(uint32_t addr)
{
PORTD = (addr>>16)&0x0f;
PORTC = (addr>>8)&0xff;
PORTA = addr&0xff;
}
uint8_t readcurrentbyte()
{
uint8_t data;
DDRL=0x00;
PORTB&=~(OE|CE);
// exact nops required depends on speed class of memory
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
data=PINL;
PORTB|=(OE|WE|CE);
return data;
}
void writecurrentbyte(uint8_t data)
{
DDRL=0xFF;
PORTL=data;
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
PORTB&=~(WE|CE);
__asm__ __volatile__("nop\n\t"); // minimum WE/CE pulse time
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
PORTB|=(OE|WE|CE);
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
DDRL=0x00;
}
void blindwrite(uint32_t addr, uint8_t data)
{
setaddr(addr);
writecurrentbyte(data);
}
void write(uint32_t addr, uint8_t data)
{
blindwrite(addr,data);
while(readcurrentbyte() != data){}
}
void writepage(uint32_t addr, uint8_t data[blocksize])
{
for (uint8_t i = 0; i<blocksize; i++)
{
setaddr(addr+i);
writecurrentbyte(data[i]);
}
while(readcurrentbyte() != data[blocksize-1]){}
}
uint8_t read(uint32_t addr)
{
uint8_t data;
setaddr(addr);
return readcurrentbyte();
}
void print_block(uint32_t addr, uint32_t len)
{
for (uint32_t i = 0; i<len; i++)
{
if (i%32 == 0 && i != 0) Serial.println("");
uint8_t data = read(addr+i);
if (data<0x10) {Serial.print("0");}
Serial.print(data,HEX);
}
Serial.println("");
}
void setup() {
PORTB|=(OE|WE|CE);
DDRB|=(OE|WE|CE);
DDRC=0xFF;
DDRA=0xFF;
DDRD=0x0F;
setaddr(0);
Serial.begin(115200);
Serial.println("ready");
}
void loop() {
if (Serial.available() > 0) { //Loop until there's something in the serial buffer
int cmd = Serial.read();
switch (cmd)
{
case 'w':
{
while (Serial.available() < 3) {}
// read 24b start addr and 8b data
uint32_t addr = Serial.read();
addr = addr << 8;
addr += Serial.read();
addr = addr << 8;
addr += Serial.read();
uint8_t data = Serial.read();
write(addr,data);
// print "done"
Serial.println("done");
}
return;
case 'W':
{
while (Serial.available() < 3) {}
// read 24b start addr and (blocksize)x8b data
uint32_t addr = Serial.read();
addr = addr << 8;
addr += Serial.read();
addr = addr << 8;
addr += Serial.read();
uint8_t data[blocksize];
Serial.readBytes(data,blocksize);
writepage(addr,data);
print_block(addr, blocksize);
// print "done"
Serial.println("done");
}
return;
case 'p':
// dump memory card pages
{
uint8_t page = Serial.read();
blindwrite(0x000A,page);
// delay a bit in case something needs to slowly page...
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
__asm__ __volatile__("nop\n\t");
print_block(0, 0x20000);
// print "done"
Serial.println("done");
return;
}
case 'd':
{
print_block(0, 0x20000);
// print "done"
Serial.println("done");
return;
}
case 'r':
{
while (Serial.available() < 4) {}
// read 24b start addr and 16b length, then dump hex...
uint32_t addr = Serial.read();
addr = addr << 8;
addr += Serial.read();
addr = addr << 8;
addr += Serial.read();
uint16_t len = Serial.read();
len = len << 8;
len += Serial.read();
print_block(addr, len);
// print "done"
Serial.println("done");
return;
}
case 't':
{
return;
}
}
}
}
$data = Get-Content -Path "D:\Projects\atariportfolio\XROM.bin" -Encoding Byte
$port= new-Object System.IO.Ports.SerialPort COM8,115200,None,8,one
$port.open()
$port.ReadLine()
for ($i=0; $i -lt $data.Length; $i+=128) {
#write a block
$port.Write([char]'W')
$port.Write([byte[]]((($i -shr 16) -band 0xff),(($i -shr 8) -band 0xff),($i -band 0xff)),0,3)
$datalen = $data.Length - $i
if ($datalen -lt 128)
{
$port.Write($data,$i,$datalen)
$port.Write([byte[]](, 0 * 100),0,(128 - $datalen))
}
else
{
$port.Write($data,$i,128)
}
# 4 lines data readback
$port.ReadLine()
$port.ReadLine()
$port.ReadLine()
$port.ReadLine()
# "done"
$port.ReadLine()
start-sleep -m 10
}
$port.Write([char]'d')
do {
$dumpline = $port.ReadLine()
$dumpline
} while ($dumpline -notlike "*done*")
$port.Close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment