├── Python └── convert.py ├── README.md ├── Schematic └── schematic.png └── eeprom_programmer └── eeprom_programmer.ino /Python/convert.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | #Convert Commodore 64 binary input file from bin to ascii so it can 4 | #be used as a include file in an Arduino sketch for writing to W27C512 EEPROM 5 | 6 | import binascii 7 | import sys 8 | import os 9 | 10 | bytes=0 11 | 12 | if len(sys.argv) != 2: 13 | print ("Script to convert Commodore 64 file from bin the ascii for Arduino sketch") 14 | print ("Usage: convert.py inputfile") 15 | exit() 16 | 17 | 18 | try: 19 | file = open("bin_file.h","wb") 20 | except: 21 | print ("Unable to create bin_file.h") 22 | exit() 23 | 24 | try: 25 | statinfo = os.stat(sys.argv[1]) 26 | except: 27 | print ("Unable to open inputfile", sys.argv[1]) 28 | exit() 29 | 30 | if statinfo.st_size > 16384: 31 | print ("Binary file greater than 16k") 32 | exit() 33 | 34 | 35 | file.write("const byte bin_file[] PROGMEM = { \\".encode()) 36 | file.write("\n".encode()) 37 | try: 38 | with open(sys.argv[1], "rb") as f: 39 | b = True 40 | count=0 41 | while b: 42 | if count < 16 and bytes < statinfo.st_size-1: 43 | bytes = bytes + 1 44 | hexdata = f.read(1) 45 | file.write("0x".encode()) 46 | file.write(binascii.hexlify(hexdata)) 47 | file.write(",".encode()) 48 | count = count + 1 49 | elif bytes < statinfo.st_size-1: 50 | count = 0 51 | file.write(" \\".encode()) 52 | file.write("\n".encode()); 53 | elif bytes > statinfo.st_size-2: 54 | bytes = bytes + 1 55 | hexdata = f.read(1) 56 | file.write("0x".encode()) 57 | file.write(binascii.hexlify(hexdata)) 58 | file.write(" \\".encode()) 59 | file.write("\n".encode()) 60 | file.write("};".encode()) 61 | b = False 62 | 63 | except Exception as ex: 64 | print ("Unable to open", sys.argv[1]) 65 | print(ex) 66 | file.close() 67 | exit() 68 | 69 | file.close() 70 | f.close() 71 | print ("File converted. Created bin_file.h") 72 | 73 | 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Arduino EEPROM programmer 2 | 3 | Arduino EEPROM programmer based on https://github.com/bouletmarc/BMBurner 4 | 5 | Tested on Arduino IDE 1.8.9 with Arduino Uno 6 | 7 | The original sketch has been changed so I don't have a dependency on the Windows 8 | software to program the EEPROM. 9 | 10 | 11 | 12 | First step is to run the python program to convert the binary file to a include file which is then used 13 | in the Arduino sketch. I'm using the Arduino Uno which has 32k of program storage. 14 | 15 | `python convert.py inputfile` 16 | 17 | This will create a bin_file.h with the correct formatting to be used in the Arduino sketch 18 | `#include "bin_file.h"` 19 | 20 | Compile and upload to the Arduino. 21 | I've added in a menu system where you select the chip, start address and block sizes using the Serial monitor. 22 | 23 | This is still a work in progress. The original BMBurner code only allows you to read most of the chips, however with some hardware and code modification you should be able to read/write most of the chips. 24 | 25 | This is still a work in progress and so far I have only tested the W27C512 and 27C256 26 | 27 | -------------------------------------------------------------------------------- /Schematic/schematic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StormTrooper/eeprom_programmer/41e63e8cd7318acd6af9cbbfba8d34707c51a5e0/Schematic/schematic.png -------------------------------------------------------------------------------- /eeprom_programmer/eeprom_programmer.ino: -------------------------------------------------------------------------------- 1 | /* 2 | EEPROM Programmer 3 | 4 | Based on https://github.com/bouletmarc/BMBurner 5 | and modified to not need the Windows software to program 6 | 7 | Arduino Uno programmer which can read/write/blank check/erase E/EPROMsreads 8 | 9 | 27C256 - tested 10 | Winbond W27C512 (Electrically erasable) - tested 11 | 27C32 - not tested 12 | 27C64 - not tested 13 | 27C128 - not tested 14 | 27C512 - not tested 15 | 16 | Data write to the EPROM is contained in the bin_file.h which is generated from a convert.py python file 17 | 18 | For more information see https://blog.gjmccarthy.co.uk 19 | 20 | */ 21 | 22 | 23 | #include "bin_file.h" //Contents of binary file to be programmed 24 | 25 | //#define DEBUG 26 | 27 | //Define chips predefinied model numbers (2-5 is for moates compatibility, 4 is never ever as it should be used for 27SF040 which is not compatible with this project at all) 28 | unsigned int chipType; 29 | #define CHIP27C128 1 //Not tested 30 | #define CHIP27C256 2 //Not tested 31 | #define CHIP27C32 3 //INCLUDED : 2732A 32 | #define CHIP27SF512 5 //INCLUDED : 27C512, W27E512, W27C512 33 | #define CHIP28C64 6 //INCLUDED : 27C64 34 | #define CHIP28C256 7 35 | 36 | // define the IO lines for the data - bus 37 | #define D0 2 38 | #define D1 3 39 | #define D2 4 40 | #define D3 5 41 | #define D4 6 42 | #define D5 7 43 | #define D6 8 44 | #define D7 10 45 | 46 | // for high voltage programming supply 47 | #define VH 11 //Erase Pin (A9) 12v 48 | #define VPP 12 //OE Pin = VPP 12v 49 | #define VPP_27C256 9 // Vpp Pin for 27C256 12V 50 | 51 | // shiftOut part 52 | #define DS A0 53 | #define LATCH A1 54 | #define CLOCK A2 55 | 56 | // define the IO lines for the eeprom control 57 | #define CE A3 58 | #define OE A4 59 | #define A15VPP A5 //A15 on SST, VPP on 27C256 60 | #define A10 13 61 | 62 | // direct access to port 63 | #define STROBE_PORT PORTC 64 | #define STROBE_DS 0 65 | #define STROBE_LATCH 1 66 | #define STROBE_CLOCK 2 67 | #define STROBE_CE 3 68 | #define STROBE_OE 4 69 | #define STROBE_WE 5 70 | 71 | //a buffer for bytes to burn 72 | #define BUFFERSIZE 256 73 | byte buffer[BUFFERSIZE + 1]; // +1 for checksum 74 | 75 | //flag set if we are on the first write pass 76 | boolean firstWritePass = true; 77 | 78 | //Last Address (used for sending high/low output at only 1 specific location on the 74HC595 79 | unsigned int Last_Address = 0; 80 | 81 | int count = 0; //Memory size 82 | int mem_count; 83 | int arraySize; 84 | long BlockSize; 85 | String mode; 86 | 87 | long Start_Address; //0x0000, 0x2000, 0x4000, 0x6000, 0x8000, 0xa000, 0xc000, 0xe000 88 | 89 | //############################################################### 90 | // Setup 91 | //############################################################### 92 | void setup() { 93 | 94 | Serial.begin(115200); 95 | 96 | Serial.println("eeprom programmer v1.1"); 97 | Serial.println(""); 98 | 99 | arraySize = sizeof(bin_file) / sizeof(bin_file[0]); 100 | 101 | //define the shiftOut Pins as output 102 | pinMode(DS, OUTPUT); 103 | pinMode(LATCH, OUTPUT); 104 | pinMode(CLOCK, OUTPUT); 105 | 106 | //define the boost pins as output (take care that they are LOW) 107 | digitalWrite(VH, LOW); 108 | pinMode(VH, OUTPUT); 109 | digitalWrite(VPP, LOW); 110 | pinMode(VPP, OUTPUT); 111 | digitalWrite(VPP_27C256, LOW); 112 | pinMode(VPP_27C256, OUTPUT); 113 | 114 | //define the EEPROM Pins as output (take care that they are HIGH) 115 | digitalWrite(OE, HIGH); 116 | pinMode(OE, OUTPUT); 117 | digitalWrite(CE, HIGH); 118 | pinMode(CE, OUTPUT); 119 | digitalWrite(A15VPP, HIGH); 120 | pinMode(A15VPP, OUTPUT); 121 | digitalWrite(A10, HIGH); 122 | pinMode(A10, OUTPUT); 123 | 124 | Serial.println("Select Read, Write, Verify, Erase, BlankCheck [R/W/V/E/B]"); 125 | 126 | } 127 | 128 | //############################################################### 129 | // Main 130 | //############################################################### 131 | 132 | void loop() { 133 | 134 | if (Serial.available() > 0) { 135 | ReadSerial(); 136 | } 137 | 138 | if (mode == "V") { 139 | Serial.println(""); Serial.println("Verifying EEPROM against bin_file"); 140 | Verify(); 141 | resetVariables(); 142 | } 143 | 144 | if (mode == "R") { 145 | Serial.println(""); Serial.println("Read EEPROM"); 146 | getStartAddress(); 147 | getBlockSize(); 148 | Read(); 149 | resetVariables(); 150 | } 151 | 152 | if (mode == "W") { 153 | Serial.println(""); Serial.println("Writing to EEPROM"); 154 | getStartAddress(); 155 | Write(); 156 | resetVariables(); 157 | } 158 | 159 | if (mode == "E") { 160 | Serial.println(""); Serial.println("Erasing W27C512 EEPROM"); 161 | Serial.println("Starting in 5 secs"); 162 | delay(5000); 163 | Erase(); 164 | resetVariables(); 165 | } 166 | 167 | if (mode == "B") { 168 | Serial.println(""); Serial.println("Blank check EEPROM"); 169 | getStartAddress(); 170 | getBlockSize(); 171 | BlankCheck(); 172 | resetVariables(); 173 | } 174 | 175 | } 176 | 177 | //############################################################### 178 | // Functions 179 | //############################################################### 180 | //Almost the same as Verify 181 | 182 | void Read() { 183 | long addr = Start_Address; 184 | Last_Address = addr; 185 | 186 | Serial.println(BlockSize); 187 | 188 | for (int y = 0; y < BlockSize / 256; y++) { // Loop If bin_size is 8k then 8192/256 = 32 times to read 8K of memory 189 | 190 | Serial.println(""); 191 | 192 | read_start(); 193 | for (int x = 0; x < BUFFERSIZE; ++x) { //Loop and read first 256 bytes 194 | buffer[x] = read_byte(addr + 256 * y + x); 195 | delayMicroseconds(100); 196 | } 197 | read_end(); 198 | int count = 0; 199 | printHex((addr + 256 * y), 4); 200 | Serial.print(": "); 201 | 202 | for (long x = 0; x < BUFFERSIZE; x++) { 203 | count++; 204 | Serial.print(" "); 205 | 206 | printHex(buffer[x], 2); 207 | if ((count > 15) and (x < BUFFERSIZE - 1)) { 208 | count = 0; 209 | Serial.println(""); 210 | printHex((addr + 256 * y + x), 4); 211 | Serial.print(": "); 212 | } 213 | } 214 | } 215 | 216 | Serial.println(""); 217 | Serial.println(""); 218 | Serial.println("Read Completed"); 219 | } 220 | 221 | //############################################################### 222 | 223 | void Verify() { 224 | long addr = Start_Address; 225 | Last_Address = addr; 226 | 227 | for (int y = 0; y < arraySize / 256; y++) { // Loop 8192/256 = 32 times to read 8K of memory 228 | Serial.print("."); 229 | 230 | #ifdef DEBUG 231 | Serial.println(""); 232 | #endif 233 | 234 | read_start(); 235 | for (int x = 0; x < BUFFERSIZE; ++x) { //Loop and read first 256 bytes 236 | buffer[x] = read_byte(addr + 256 * y + x); 237 | delayMicroseconds(100); 238 | } 239 | read_end(); 240 | 241 | #ifdef DEBUG 242 | int count = 0; 243 | printHex((addr + 256 * y), 4); 244 | Serial.print(": "); 245 | #endif 246 | 247 | for (long x = 0; x < BUFFERSIZE; x++) { 248 | 249 | #ifdef DEBUG 250 | count++; 251 | Serial.print(" "); 252 | 253 | printHex(buffer[x], 2); 254 | if ((count > 15) and (x < BUFFERSIZE - 1)) { 255 | count = 0; 256 | Serial.println(""); 257 | printHex((addr + 256 * y + x), 2); 258 | Serial.print(": "); 259 | } 260 | 261 | #endif 262 | 263 | if (buffer[x] != pgm_read_byte(bin_file + 256 * y + x)) { 264 | Serial.println(""); 265 | Serial.print("Compare error at 0x"); 266 | Serial.print(x, HEX); 267 | Serial.println(""); 268 | Serial.print("Found: 0x"); 269 | printHex(buffer[x], 2); 270 | Serial.println(""); 271 | Serial.print("Expected: 0x"); 272 | printHex(pgm_read_byte(&bin_file[x + 256 * y]), 2); 273 | Serial.println(""); 274 | while (1) { 275 | // Halt 276 | } 277 | } 278 | } 279 | } 280 | 281 | Serial.println(""); 282 | Serial.println(""); 283 | Serial.println("Compare OK"); 284 | } 285 | 286 | //############################################################### 287 | 288 | void BlankCheck() { 289 | //Get Parameters 290 | long addr = 0; // Start checking from 0x0000 291 | Last_Address = addr; 292 | 293 | for (int y = 0; y < mem_count; y++) { // If mem_count is 32 then loop 32 * 256 times to read 8K of memory 294 | 295 | Serial.print("."); 296 | read_start(); 297 | for (int x = 0; x < BUFFERSIZE; ++x) { 298 | buffer[x] = read_byte(addr + 256 * y + x); 299 | delayMicroseconds(100); 300 | } 301 | read_end(); 302 | 303 | //return Array+Checksum to say it passed 304 | //ChecksumThis(); 305 | for (long x = 0; x < 0xff; x++) { 306 | 307 | //Serial.println(buffer[x]); 308 | if (buffer[x] != 0xFF) { 309 | Serial.println(""); 310 | Serial.println("EEPROM is not blank"); 311 | 312 | Serial.println(""); 313 | Serial.print("Found 0x"); 314 | printHex(buffer[x], 2); 315 | Serial.print(" at position 0x"); 316 | printHex((addr + 256 * y + x), 2); 317 | while (1) { 318 | 319 | } 320 | } 321 | } 322 | } 323 | Serial.println(""); 324 | Serial.println(""); 325 | Serial.println("E/EPROM is blank"); 326 | } 327 | 328 | //############################################################### 329 | 330 | void Write() { 331 | 332 | long addr = Start_Address; 333 | Last_Address = addr; 334 | 335 | //Check if bin_file is larger than the EPROM 336 | if (chipType == "27C128") { 337 | if ( (Start_Address + arraySize) > 16384) { 338 | Error(); 339 | } 340 | } 341 | 342 | if (chipType == "27C256") { 343 | if ( (Start_Address + arraySize) > 32768) { 344 | Error(); 345 | } 346 | } 347 | 348 | if ((chipType == "27C512") || (chipType == "W27C512") ) { 349 | if ( (Start_Address + arraySize) > 65535) { 350 | Error(); 351 | } 352 | } 353 | 354 | for (int y = 0; y < arraySize / 256; y++) { // Loop 8192/256 = 32 times to read 8K of memory 355 | 356 | #ifdef DEBUG 357 | int count = 0; 358 | Serial.println(""); 359 | printHex((addr + 256 * y), 4); 360 | Serial.print(": "); 361 | #endif 362 | 363 | #ifndef DEBUG 364 | Serial.print("."); 365 | #endif 366 | 367 | //Write 368 | write_start(); 369 | 370 | for (int x = 0; x < BUFFERSIZE; ++x) { 371 | #ifdef DEBUG 372 | count++; 373 | Serial.print(" "); 374 | 375 | printHex(pgm_read_byte(&bin_file[x + 256 * y]), 2); 376 | 377 | if ((count > 15) and (x < BUFFERSIZE - 1)) { 378 | count = 0; 379 | Serial.println(""); 380 | printHex((addr + 256 * y + x), 4); 381 | Serial.print(": "); 382 | } 383 | 384 | #endif 385 | 386 | fast_write(addr + 256 * y + x, pgm_read_byte(&bin_file[x + 256 * y])); 387 | 388 | } 389 | 390 | write_end(); 391 | } 392 | Serial.println(""); 393 | Serial.println(""); 394 | Serial.println("Write complete. Check with Read/Compare"); 395 | } 396 | 397 | //############################################################### 398 | 399 | void Erase() { 400 | set_ce(HIGH); 401 | set_oe(HIGH); 402 | set_vh(HIGH); 403 | set_vpp(HIGH); 404 | delay(1); 405 | 406 | //erase pulse 407 | set_ce(LOW); 408 | delay(350); 409 | set_ce(HIGH); 410 | delayMicroseconds(1); 411 | 412 | //Turning Off 413 | set_vh(LOW); 414 | set_vpp(LOW); 415 | delayMicroseconds(1); 416 | 417 | Serial.println("Erase complete. Run a blank check"); 418 | } 419 | 420 | //############################################################### 421 | // COMMANDS SUBS functions 422 | //############################################################### 423 | 424 | void read_start() { 425 | data_bus_input(); 426 | //enable chip select 427 | set_ce(LOW); 428 | //enable output 429 | set_oe(LOW); 430 | 431 | //Set VPP to Low/High (27C2128, 27C256) 432 | if (chipType == CHIP27C128) { 433 | digitalWrite(A15VPP, LOW); 434 | Set_Output_At(15, HIGH); //With 27C128 A15 becomes PGM 435 | } 436 | else if (chipType == CHIP27C256 || chipType == CHIP28C64) { 437 | digitalWrite(A15VPP, HIGH); //the 28C64 doesnt care but the 27C64 is VPP 438 | } 439 | else if (chipType == CHIP27C32) { 440 | digitalWrite(A15VPP, LOW); //normally used for A15/VPP, this pin is not used on 24pin chips 441 | Set_Output_At(15, LOW); //normally used for A14, this pin is not used on 24pin chips 442 | Set_Output_At(14, HIGH); //**** normally used for A13, this pin is now VCC (5v) **** 443 | Set_Output_At(13, LOW); //normally used for A12, this pin is not used on 24pin chips 444 | delayMicroseconds(5); 445 | } 446 | } 447 | 448 | void read_end() { 449 | //disable output 450 | set_oe(HIGH); 451 | //disable chip select 452 | set_ce(HIGH); 453 | 454 | //Set VPP to Low/High (27C2128, 27C256) 455 | if (chipType == CHIP27C128) Set_Output_At(15, LOW); //With 27C128 A15 becomes PGM 456 | else if (chipType == CHIP27C256) digitalWrite(A15VPP, LOW); 457 | } 458 | 459 | inline byte read_byte(unsigned int address) 460 | { 461 | set_address_bus(address); 462 | return read_data_bus(); 463 | } 464 | 465 | void write_start() { 466 | firstWritePass = true; 467 | //disable output 468 | set_oe(HIGH); 469 | 470 | set_vpp(HIGH); 471 | //Set VPP to low on 29C256 (not 27C256/27SF256 as its read only) 472 | if (chipType == CHIP27C256) { 473 | //Serial.print("."); 474 | digitalWrite(A15VPP, LOW); 475 | delayMicroseconds(5); 476 | } 477 | 478 | if (chipType == CHIP27C128) { 479 | Set_Output_At(15, LOW); //With 27C128 A15 becomes PGM, LOW when programming 480 | delayMicroseconds(5); 481 | } 482 | 483 | data_bus_output(); 484 | } 485 | 486 | void write_end() { 487 | set_vpp(LOW); 488 | data_bus_input(); 489 | 490 | } 491 | 492 | inline void fast_write(unsigned int address, byte data) 493 | { 494 | if (chipType == CHIP28C64 || chipType == CHIP28C256) { 495 | //this function uses /DATA polling to get the end of the page write cycle. This is much faster than waiting 10ms 496 | static unsigned int lastAddress = 0; 497 | static byte lastData = 0; 498 | 499 | //enable chip select 500 | set_ce(LOW); 501 | 502 | //data poll 503 | if (((lastAddress ^ address) & 0xFFC0 || chipType == CHIP28C64) && !firstWritePass) 504 | { 505 | unsigned long startTime = millis(); 506 | 507 | //poll data until data matches 508 | data_bus_input(); 509 | set_oe(LOW); 510 | 511 | //set timeout here longer than JBurn timeout 512 | while (lastData != read_data_bus()) { 513 | if (millis() - startTime > 3000) return false; 514 | } 515 | 516 | set_oe(HIGH); 517 | delayMicroseconds(1); 518 | data_bus_output(); 519 | } 520 | 521 | //set address and data for write 522 | set_address_bus(address); 523 | write_data_bus(data); 524 | delayMicroseconds(1); 525 | 526 | //strobe write 527 | set_we(LOW); 528 | set_we(HIGH); 529 | //disable chip select 530 | set_ce(HIGH); 531 | 532 | lastAddress = address; 533 | lastData = data; 534 | firstWritePass = false; 535 | } 536 | else 537 | { 538 | set_address_bus(address); 539 | write_data_bus(data); 540 | delayMicroseconds(1); 541 | 542 | //programming pulse 543 | set_ce(LOW); 544 | delayMicroseconds(100); // for W27E512, works for 27SF512 also (but 27SF512 should be 20ms) 545 | set_ce(HIGH); 546 | delayMicroseconds(1); 547 | } 548 | } 549 | 550 | //############################################################### 551 | // DATA BUS functions 552 | //############################################################### 553 | 554 | void data_bus_input() { 555 | pinMode(D0, INPUT); 556 | pinMode(D1, INPUT); 557 | pinMode(D2, INPUT); 558 | pinMode(D3, INPUT); 559 | pinMode(D4, INPUT); 560 | pinMode(D5, INPUT); 561 | pinMode(D6, INPUT); 562 | pinMode(D7, INPUT); 563 | } 564 | 565 | void data_bus_output() { 566 | pinMode(D0, OUTPUT); 567 | pinMode(D1, OUTPUT); 568 | pinMode(D2, OUTPUT); 569 | pinMode(D3, OUTPUT); 570 | pinMode(D4, OUTPUT); 571 | pinMode(D5, OUTPUT); 572 | pinMode(D6, OUTPUT); 573 | pinMode(D7, OUTPUT); 574 | } 575 | 576 | byte read_data_bus() 577 | { 578 | byte b = 0; 579 | if (digitalRead(D0) == HIGH) b |= 1; 580 | if (digitalRead(D1) == HIGH) b |= 2; 581 | if (digitalRead(D2) == HIGH) b |= 4; 582 | if (digitalRead(D3) == HIGH) b |= 8; 583 | if (digitalRead(D4) == HIGH) b |= 16; 584 | if (digitalRead(D5) == HIGH) b |= 32; 585 | if (digitalRead(D6) == HIGH) b |= 64; 586 | if (digitalRead(D7) == HIGH) b |= 128; 587 | return (b); 588 | } 589 | 590 | inline void write_data_bus(byte data) 591 | { 592 | digitalWrite(D0, data & 1); 593 | digitalWrite(D1, data & 2); 594 | digitalWrite(D2, data & 4); 595 | digitalWrite(D3, data & 8); 596 | digitalWrite(D4, data & 16); 597 | digitalWrite(D5, data & 32); 598 | digitalWrite(D6, data & 64); 599 | digitalWrite(D7, data & 128); 600 | } 601 | 602 | //############################################################### 603 | // FAST SWIFT functions 604 | //############################################################### 605 | inline void set_address_bus(unsigned int address) 606 | { 607 | byte hi, low; 608 | hi = (address >> 8); 609 | low = address & 0xff; 610 | //A14 become WE on 28C64 && 28C256, make sure dont use the output that were generally used for A14 611 | if (chipType == CHIP28C64 || chipType == CHIP28C256) bitSet(hi, 6); //set ouput 7 on hi byte 612 | else if (chipType == CHIP27C32) { 613 | bitClear(hi, 6); //set ouput 7 on hi byte 614 | bitSet(hi, 5); //set ouput 6 on hi byte, this is now VCC 615 | bitClear(hi, 4); //set ouput 5 on hi byte 616 | } 617 | 618 | ApplyShiftAt(hi, low); 619 | 620 | digitalWrite(A10, (address & 1024) ? HIGH : LOW ); 621 | if (chipType == CHIP28C64 || chipType == CHIP28C256) digitalWrite(A15VPP, (address & 16384) ? HIGH : LOW); //A15/VPP become A14 on 28C64 && 28C256 622 | else if (chipType == CHIP27SF512) digitalWrite(A15VPP, (address & 32768) ? HIGH : LOW); 623 | } 624 | 625 | inline void Set_Output_At(unsigned int Position, bool IsHigh) 626 | { 627 | byte hi, low; 628 | hi = (Last_Address >> 8); 629 | low = Last_Address & 0xff; 630 | if (Position >= 8) { 631 | if (IsHigh) bitSet(hi, Position - 8); 632 | else bitClear(hi, Position - 8); 633 | } 634 | else { 635 | if (IsHigh) bitSet(low, Position); 636 | else bitClear(low, Position); 637 | } 638 | ApplyShiftAt(hi, low); 639 | } 640 | 641 | void ApplyShiftAt(byte hi, byte low) 642 | { 643 | fastShiftOut(hi); 644 | fastShiftOut(low); 645 | //strobe latch line 646 | bitSet(STROBE_PORT, STROBE_LATCH); 647 | bitClear(STROBE_PORT, STROBE_LATCH); 648 | delayMicroseconds(1); 649 | } 650 | 651 | void fastShiftOut(byte data) { 652 | //clear 653 | bitClear(STROBE_PORT, STROBE_DS); 654 | 655 | //Loop for the 8x outputs 656 | for (int i = 7; i >= 0; i--) { 657 | //clear clock pin 658 | bitClear(STROBE_PORT, STROBE_CLOCK); 659 | 660 | //Enable/Disable pin Output 661 | if (bitRead(data, i) == 1) bitSet(STROBE_PORT, STROBE_DS); 662 | else bitClear(STROBE_PORT, STROBE_DS); 663 | 664 | //register shifts bits on upstroke of clock pin 665 | bitSet(STROBE_PORT, STROBE_CLOCK); 666 | //clear after shift to prevent bleed through 667 | bitClear(STROBE_PORT, STROBE_DS); 668 | } 669 | 670 | //stop shifting 671 | bitClear(STROBE_PORT, STROBE_CLOCK); 672 | } 673 | 674 | int GetAddress(unsigned int Position) 675 | { 676 | int Address = 0; 677 | if (Position == 1) Address = 1; 678 | if (Position == 2) Address = 2; 679 | if (Position == 3) Address = 4; 680 | if (Position == 4) Address = 8; 681 | if (Position == 5) Address = 16; 682 | if (Position == 6) Address = 32; 683 | if (Position == 7) Address = 64; 684 | if (Position == 8) Address = 128; 685 | if (Position == 9) Address = 256; 686 | if (Position == 10) Address = 512; 687 | if (Position == 11) Address = 1024; 688 | if (Position == 12) Address = 2048; 689 | if (Position == 13) Address = 4096; 690 | if (Position == 14) Address = 8192; 691 | if (Position == 15) Address = 16384; 692 | if (Position == 16) Address = 32768; 693 | return Address; 694 | } 695 | 696 | //############################################################### 697 | // PINS functions 698 | //############################################################### 699 | 700 | //**attention, this line is LOW - active** 701 | inline void set_oe (byte state) 702 | { 703 | digitalWrite(OE, state); 704 | } 705 | 706 | //**attention, this line is LOW - active** 707 | inline void set_ce (byte state) 708 | { 709 | digitalWrite(CE, state); 710 | } 711 | 712 | //**attention, this line is LOW - active** 713 | inline void set_we (byte state) 714 | { 715 | if (chipType == CHIP28C64 || chipType == CHIP28C256 || CHIP27C128) Set_Output_At(15, state); //output 15 become WE (since there are 8 outputs by 74HC595, its the #7 ouputs on the 2nd 74HC595) 716 | } 717 | 718 | //Boost VPP 12V 719 | void set_vpp (byte state) 720 | { 721 | switch (chipType) { 722 | case CHIP27SF512: 723 | digitalWrite(VPP, state); 724 | break; 725 | case CHIP27C256: // Vpp on pin 1 726 | digitalWrite(VPP_27C256, state); 727 | break; 728 | case CHIP27C128: // Vpp on pin 1 729 | digitalWrite(VPP_27C256, state); 730 | break; 731 | default: 732 | break; 733 | } 734 | } 735 | 736 | //Boost Erase 12V 737 | void set_vh (byte state) 738 | { 739 | switch (chipType) { 740 | case CHIP27SF512: 741 | digitalWrite(VH, state); 742 | break; 743 | default: 744 | break; 745 | } 746 | } 747 | 748 | //========================================================================== 749 | 750 | //Print HEX With leading zeros 751 | void printHex(int num, int precision) { 752 | 753 | char tmp[16]; 754 | char format[128]; 755 | 756 | sprintf(format, "%%.%dX", precision); 757 | sprintf(tmp, format, num); 758 | Serial.print(tmp); 759 | } 760 | 761 | void ReadSerial() { 762 | 763 | char rx_byte = Serial.read(); // get the character 764 | 765 | if ((rx_byte == 'V') || (rx_byte == 'v')) { 766 | Serial.println(""); Serial.print("Verify selected"); Serial.println(""); 767 | mode = "V"; 768 | selectChip(); 769 | } 770 | 771 | if ((rx_byte == 'R') || (rx_byte == 'r')) { 772 | Serial.println(""); Serial.print("Read selected"); Serial.println(""); 773 | mode = "R"; 774 | selectChip(); 775 | } 776 | 777 | if ((rx_byte == 'W') || (rx_byte == 'w')) { 778 | Serial.println(""); Serial.print("Write selected"); Serial.println(""); 779 | mode = "W"; 780 | selectChip(); 781 | } 782 | 783 | if ((rx_byte == 'E') || (rx_byte == 'e')) { 784 | Serial.println(""); Serial.print("Erase selected"); Serial.println(""); 785 | mode = "E"; 786 | //Can only erase W27C512 787 | chipType = CHIP27SF512; //W27C512; 788 | 789 | } 790 | 791 | if ((rx_byte == 'B') || (rx_byte == 'b')) { 792 | Serial.println(""); Serial.print("BlankCheck selected"); Serial.println(""); 793 | mode = "B"; 794 | selectChip(); 795 | } 796 | 797 | } 798 | 799 | void selectChip() { 800 | boolean selected = false; 801 | String rx_string; 802 | 803 | Serial.println(""); Serial.println("Enter chip: 27C128, 27C256, 27C512, W27C512"); Serial.println(""); 804 | 805 | while (selected == false) { 806 | if (Serial.available() > 0) { 807 | rx_string = Serial.readString(); 808 | rx_string.trim(); 809 | 810 | if (rx_string == "27C128" || rx_string == "27c128") { 811 | chipType = CHIP27C128; 812 | Serial.println("27C128 selected"); 813 | selected = true; 814 | mem_count = 64; 815 | } 816 | 817 | if (rx_string == "27C256" || rx_string == "27c256") { 818 | chipType = CHIP27C256; 819 | Serial.println("27C256 selected"); 820 | selected = true; 821 | mem_count = 128; 822 | } 823 | 824 | if (rx_string == "27C512" || rx_string == "27c512") { 825 | chipType = CHIP27SF512; 826 | Serial.println("27C512 selected"); 827 | selected = true; 828 | mem_count = 32; 829 | } 830 | 831 | if (rx_string == "W27C512" || rx_string == "w27c512") { 832 | chipType = CHIP27SF512; 833 | Serial.println("W27C512 selected"); 834 | selected = true; 835 | mem_count = 32; 836 | } 837 | } 838 | } 839 | 840 | } 841 | 842 | void getStartAddress() { 843 | 844 | boolean selected = false; 845 | int charsRead; 846 | char input[5]; 847 | 848 | Serial.println(""); Serial.print("Enter start address in hex "); 849 | if (chipType == 1) { 850 | Serial.println("(0000, 2000) :"); 851 | } 852 | 853 | if (chipType == 2) { 854 | Serial.println("(0000, 2000, 4000, 6000) :"); 855 | } 856 | 857 | if ((chipType == 5)) { 858 | Serial.println("(0000, 2000, 4000, 6000, 8000, a000, c000, e000): "); 859 | } 860 | 861 | Serial.println(""); 862 | 863 | while (selected == false) { 864 | 865 | if (Serial.available() > 0) { 866 | charsRead = Serial.readBytesUntil('\n', input, 5); // fetch the two characters 867 | input[charsRead] = '\0'; // Make it a string 868 | 869 | Start_Address = StrToHex(input); // Convert it 870 | 871 | if ( (Start_Address == 0x0000) || (Start_Address == 0x2000) || (Start_Address == 0x4000) || (Start_Address == 0x6000) 872 | || (Start_Address == 0x8000) || (Start_Address == 0xa000) || (Start_Address == 0xc000) || (Start_Address == 0xe000) ) { 873 | selected = true; 874 | } 875 | 876 | } 877 | 878 | } 879 | 880 | Serial.print("Start Address: "); 881 | if (Start_Address == 0) { 882 | Serial.println("0000"); 883 | } 884 | else { 885 | Serial.println(Start_Address, HEX); 886 | } 887 | Serial.println(""); 888 | 889 | } 890 | 891 | void getBlockSize() { 892 | 893 | boolean selected = false; 894 | int charsRead; 895 | char input[5]; 896 | 897 | Serial.print("Enter block size in hex "); 898 | if (chipType == 1) { 899 | Serial.println("(1000, 2000, 4000)"); 900 | } else { 901 | Serial.println("(1000, 2000, 4000, 6000)"); 902 | } 903 | 904 | while (selected == false) { 905 | 906 | if (Serial.available() > 0) { 907 | charsRead = Serial.readBytesUntil('\n', input, 5); // fetch the two characters 908 | input[charsRead] = '\0'; // Make it a string 909 | 910 | BlockSize = StrToHex(input); // Convert it 911 | 912 | if ( (BlockSize == 0x1000) || (BlockSize == 0x2000) || (BlockSize == 0x4000) || (BlockSize == 0x6000) ) { 913 | selected = true; 914 | } 915 | 916 | } 917 | 918 | } 919 | Serial.print("Block Size: "); Serial.println(BlockSize, HEX); 920 | 921 | } 922 | 923 | void resetVariables() { 924 | mode = ""; 925 | chipType = ""; 926 | Serial.println(""); 927 | Serial.println("Select Read, Write, Verify, Erase, BlankCheck [R/W/V/E/B]"); 928 | } 929 | 930 | long StrToHex(char str[]) 931 | { 932 | return (long) strtol(str, 0, 16); 933 | } 934 | 935 | void Error() { 936 | Serial.println("Error. Bin file is too big"); 937 | Serial.print("bin_file: "); Serial.println(arraySize); 938 | while (1); 939 | } 940 | --------------------------------------------------------------------------------