Advertisement
UnaClocker

EEProm Programmer

Jul 2nd, 2013
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.84 KB | None | 0 0
  1. /**
  2.  * ** project Arduino EEPROM programmer **
  3.  *
  4.  * This sketch can be used to read and write data to a
  5.  * AT28C64 or AT28C256 parallel EEPROM
  6.  *
  7.  * $Author: mario $
  8.  * $Date: 2013/05/05 11:01:54 $
  9.  * $Revision: 1.3 $
  10.  *
  11.  * This software is freeware and can be modified, reused or thrown away without any restrictions.
  12.  *
  13.  * Use this code at your own risk. I'm not responsible for any bad effect or damages caused by this software!!!
  14.  *
  15.  **/
  16.  
  17. #define VERSIONSTRING "MEEPROMMER $Revision: 1.3 $ $Date: June 25th, 2013 9:15am $, CMD:B,b,w,W,V"
  18.  
  19. // shiftOut part
  20. #define DS      A0
  21. #define LATCH   A1
  22. #define CLOCK   A2
  23.  
  24. #define PORTC_DS      0
  25. #define PORTC_LATCH   1
  26. #define PORTC_CLOCK   2
  27.  
  28.  
  29. // eeprom stuff
  30. // define the IO lines for the data - bus
  31. #define D0 2
  32. #define D1 3
  33. #define D2 4
  34. #define D3 5
  35. #define D4 6
  36. #define D5 7
  37. #define D6 8
  38. #define D7 9
  39.  
  40. // define the IO lines for the eeprom control
  41. #define CE A3
  42. #define OE A4
  43. #define WE A5
  44. #define PORTC_CE   3
  45. #define PORTC_OE   4
  46. #define PORTC_WE   5
  47.  
  48. //a buffer for bytes to burn
  49. #define BUFFERSIZE 1024
  50. byte buffer[BUFFERSIZE];
  51. //command buffer for parsing commands
  52. #define COMMANDSIZE 32
  53. char cmdbuf[COMMANDSIZE];
  54.  
  55. unsigned int startAddress,endAddress;
  56. unsigned int lineLength,dataLength;
  57.  
  58. //define COMMANDS
  59. #define NOCOMMAND    0
  60. #define VERSION      1
  61.  
  62. #define READ_HEX    10
  63. #define READ_BIN    11
  64. #define READ_ITL    12
  65.  
  66. #define WRITE_HEX   20
  67. #define WRITE_BIN   21
  68. #define WRITE_ITL   22
  69.  
  70.  
  71. /*****************************************************************
  72.  *
  73.  *  CONTROL and DATA functions
  74.  *
  75.  ****************************************************************/
  76.  
  77. // switch IO lines of databus to INPUT state
  78. void        data_bus_input() {
  79.   pinMode(D0, INPUT);
  80.   pinMode(D1, INPUT);
  81.   pinMode(D2, INPUT);
  82.   pinMode(D3, INPUT);
  83.   pinMode(D4, INPUT);
  84.   pinMode(D5, INPUT);
  85.   pinMode(D6, INPUT);
  86.   pinMode(D7, INPUT);
  87. }
  88.  
  89. //switch IO lines of databus to OUTPUT state
  90. void data_bus_output() {
  91.   pinMode(D0, OUTPUT);
  92.   pinMode(D1, OUTPUT);
  93.   pinMode(D2, OUTPUT);
  94.   pinMode(D3, OUTPUT);
  95.   pinMode(D4, OUTPUT);
  96.   pinMode(D5, OUTPUT);
  97.   pinMode(D6, OUTPUT);
  98.   pinMode(D7, OUTPUT);
  99. }
  100.  
  101. //set databus to input and read a complete byte from the bus
  102. //be sure to set data_bus to input before
  103. byte read_data_bus()
  104. {
  105.   return ((digitalRead(D7) << 7) +
  106.     (digitalRead(D6) << 6) +
  107.     (digitalRead(D5) << 5) +
  108.     (digitalRead(D4) << 4) +
  109.     (digitalRead(D3) << 3) +
  110.     (digitalRead(D2) << 2) +
  111.     (digitalRead(D1) << 1) +
  112.     digitalRead(D0));
  113.  
  114. }
  115.  
  116.  
  117. //write a byte to the data bus
  118. //be sure to set data_bus to output before
  119. void write_data_bus(byte data)
  120. {
  121.   //2 bits belong to PORTB and have to be set separtely
  122.   digitalWrite(D6, (data >> 6) & 0x01);
  123.   digitalWrite(D7, (data >> 7) & 0x01);
  124.   //bit 0 to 6 belong to bit 2 to 8 of PORTD
  125.   PORTD = PIND | ( data << 2 );
  126. }
  127.  
  128. //shift out the given address to the 74hc595 registers
  129. void set_address_bus(unsigned int address)
  130. {
  131.  
  132.   //get high - byte of 16 bit address
  133.   byte hi = address >> 8;
  134.   //get low - byte of 16 bit address
  135.   byte low = address & 0xff;
  136.  
  137.   //disable latch line
  138.   bitClear(PORTC,PORTC_LATCH);
  139.  
  140.   //shift out highbyte
  141.   fastShiftOut(hi);
  142.   //shift out lowbyte
  143.   fastShiftOut(low);
  144.  
  145.   //enable latch and set address
  146.   bitSet(PORTC,PORTC_LATCH);
  147.  
  148. }
  149.  
  150. //faster shiftOut function then normal IDE function (about 4 times)
  151. void fastShiftOut(byte data) {
  152.   //clear data pin
  153.   bitClear(PORTC,PORTC_DS);
  154.   //Send each bit of the myDataOut byte MSBFIRST
  155.   for (int i=7; i>=0; i--)  {
  156.     bitClear(PORTC,PORTC_CLOCK);
  157.     //--- Turn data on or off based on value of bit
  158.     if ( bitRead(data,i) == 1) {
  159.       bitSet(PORTC,PORTC_DS);
  160.     }
  161.     else {      
  162.       bitClear(PORTC,PORTC_DS);
  163.     }
  164.     //register shifts bits on upstroke of clock pin  
  165.     bitSet(PORTC,PORTC_CLOCK);
  166.     //zero the data pin after shift to prevent bleed through
  167.     bitClear(PORTC,PORTC_DS);
  168.   }
  169.   //stop shifting
  170.   bitClear(PORTC,PORTC_CLOCK);
  171. }
  172.  
  173. //short function to set the OE(output enable line of the eeprom)
  174. // attention, this line is LOW - active
  175. void set_oe (byte state)
  176. {
  177.   digitalWrite(OE, state);
  178. }
  179.  
  180. //short function to set the CE(chip enable line of the eeprom)
  181. // attention, this line is LOW - active
  182. void set_ce (byte state)
  183. {
  184.   digitalWrite(CE, state);
  185. }
  186.  
  187. //short function to set the WE(write enable line of the eeprom)
  188. // attention, this line is LOW - active
  189. void set_we (byte state)
  190. {
  191.   digitalWrite(WE, state);
  192. }
  193.  
  194. //highlevel function to read a byte from a given address
  195. byte read_byte(unsigned int address)
  196. {
  197.   byte      data = 0;
  198.   //set databus for reading
  199.   data_bus_input();
  200.   //first disbale output
  201.   set_oe(HIGH);
  202.   //enable chip select
  203.   set_ce(LOW);
  204.   //disable write
  205.   set_we(HIGH);
  206.   //set address bus
  207.   set_address_bus(address);
  208.   //enable output
  209.   set_oe(LOW);
  210.   data = read_data_bus();
  211.  
  212.   //disable output
  213.   set_oe(HIGH);
  214.  
  215.   return data;
  216.  
  217. }
  218.  
  219.  
  220. //highlevel function to write a byte to a given address
  221. //this function uses /DATA polling to get the end of the
  222. //write cycle. This is much faster then waiting 10ms
  223. void fast_write(unsigned int address, byte data)
  224. {
  225.   byte cyclecount=0;
  226.  
  227.   //first disbale output
  228.   set_oe(HIGH);
  229.  
  230.   //disable write
  231.   set_we(HIGH);
  232.  
  233.   //set address bus
  234.   set_address_bus(address);
  235.  
  236.   //set databus to output
  237.   data_bus_output();
  238.  
  239.   //set data bus
  240.   write_data_bus(data);
  241.  
  242.   //enable chip select
  243.   set_ce(LOW);
  244.  
  245.   //wait some time to finish writing
  246.   delayMicroseconds(1);
  247.  
  248.   //enable write
  249.   set_we(LOW);
  250.  
  251.   //wait some time to finish writing
  252.   delayMicroseconds(1);
  253.  
  254.   //disable write
  255.   set_we(HIGH);
  256.  
  257.   data_bus_input();
  258.  
  259.   set_oe(LOW);
  260.  
  261.   while(data != read_data_bus()) {
  262.     cyclecount++;
  263.   };
  264.  
  265.   set_oe(HIGH);
  266.   set_ce(HIGH);
  267.  
  268. }
  269.  
  270.  
  271.  
  272. /************************************************
  273.  *
  274.  * COMMAND and PARSING functions
  275.  *
  276.  *************************************************/
  277.  
  278. //waits for a string submitted via serial connection
  279. //returns only if linebreak is sent or the buffer is filled
  280. void readCommand() {
  281.   //first clear command buffer
  282.   for(int i=0; i< COMMANDSIZE;i++) cmdbuf[i] = 0;
  283.   //initialize variables
  284.   char c = ' ';
  285.   int idx = 0;
  286.   //now read serial data until linebreak or buffer is full
  287.   do {
  288.     if(Serial.available()) {
  289.       c = Serial.read();
  290.       cmdbuf[idx++] = c;
  291.     }
  292.   }
  293.   while (c != '\n' && idx < (COMMANDSIZE)); //save the last '\0' for string end
  294.   //change last newline to '\0' termination
  295.   cmdbuf[idx - 1] = 0;
  296. }
  297.  
  298. //parse the given command by separating command character and parameters
  299. //at the moment only 5 commands are supported
  300. byte parseCommand() {
  301.   //set ',' to '\0' terminator (command string has a fixed strucure)
  302.   //first string is the command character
  303.   cmdbuf[1]  = 0;
  304.   //second string is startaddress (4 bytes)
  305.   cmdbuf[6]  = 0;
  306.   //third string is endaddress (4 bytes)
  307.   cmdbuf[11] = 0;
  308.   //fourth string is length (2 bytes)
  309.   cmdbuf[14] = 0;
  310.   startAddress=hexWord((cmdbuf+2));
  311.   dataLength=hexWord((cmdbuf+7));
  312.   lineLength=hexByte(cmdbuf+12);
  313.   byte retval = 0;
  314.   switch(cmdbuf[0]) {
  315.   case 'R':
  316.     retval = READ_HEX;
  317.     break;
  318.   case 'r':
  319.     retval = READ_BIN;
  320.     break;
  321.   case 'W':
  322.     retval = WRITE_HEX;
  323.     break;
  324.   case 'w':
  325.     retval = WRITE_BIN;
  326.     break;
  327.   case 'V':
  328.     retval = VERSION;
  329.     break;
  330.   default:
  331.     retval = NOCOMMAND;
  332.     break;
  333.   }
  334.  
  335.   return retval;
  336. }
  337.  
  338. /************************************************************
  339.  * convert a single hex digit (0-9,a-f) to byte
  340.  * @param char c single character (digit)
  341.  * @return byte represented by the digit
  342.  ************************************************************/
  343. byte hexDigit(char c)
  344. {
  345.   if (c >= '0' && c <= '9') {
  346.     return c - '0';
  347.   }
  348.   else if (c >= 'a' && c <= 'f') {
  349.     return c - 'a' + 10;
  350.   }
  351.   else if (c >= 'A' && c <= 'F') {
  352.     return c - 'A' + 10;
  353.   }
  354.   else {
  355.     return 0;   // getting here is bad: it means the character was invalid
  356.   }
  357. }
  358.  
  359. /************************************************************
  360.  * convert a hex byte (00 - ff) to byte
  361.  * @param c-string with the hex value of the byte
  362.  * @return byte represented by the digits
  363.  ************************************************************/
  364. byte hexByte(char* a)
  365. {
  366.   return ((hexDigit(a[0])*16) + hexDigit(a[1]));
  367. }
  368.  
  369. /************************************************************
  370.  * convert a hex word (0000 - ffff) to unsigned int
  371.  * @param c-string with the hex value of the word
  372.  * @return unsigned int represented by the digits
  373.  ************************************************************/
  374. unsigned int hexWord(char* data) {
  375.   return ((hexDigit(data[0])*4096)+
  376.     (hexDigit(data[1])*256)+
  377.     (hexDigit(data[2])*16)+
  378.     (hexDigit(data[3])));
  379. }
  380.  
  381.  
  382. /************************************************
  383.  *
  384.  * INPUT / OUTPUT Functions
  385.  *
  386.  *************************************************/
  387.  
  388.  
  389. /**
  390.  * read a data block from eeprom and write out a hex dump
  391.  * of the data to serial connection
  392.  * @param from       start address to read fromm
  393.  * @param to         last address to read from
  394.  * @param linelength how many hex values are written in one line
  395.  **/
  396. void read_block(unsigned int from, unsigned int to, int linelength)
  397. {
  398.   //count the number fo values that are already printed out on the
  399.   //current line
  400.   int           outcount = 0;
  401.   //loop from "from address" to "to address" (included)
  402.   for (unsigned int address = from; address <= to; address++) {
  403.     if (outcount == 0) {
  404.       //print out the address at the beginning of the line
  405.       Serial.println();
  406.       Serial.print("0x");
  407.       printAddress(address);
  408.       Serial.print(" : ");
  409.     }
  410.     //print data, separated by a space
  411.     byte data = read_byte(address);
  412.     printByte(data);
  413.     Serial.print(" ");
  414.     outcount = (++outcount % linelength);
  415.  
  416.   }
  417.   //print a newline after the last data line
  418.   Serial.println();
  419.  
  420. }
  421.  
  422. /**
  423.  * read a data block from eeprom and write out the binary data
  424.  * to the serial connection
  425.  * @param from       start address to read fromm
  426.  * @param to         last address to read from
  427.  **/
  428. void read_binblock(unsigned int from, unsigned int to) {
  429.   for (unsigned int address = from; address <= to; address++) {
  430.     Serial.write(read_byte(address));
  431.   }
  432.   //print out an additional 0-byte as success return code
  433.   Serial.print('\0');
  434.  
  435. }  
  436.  
  437. /**
  438.  * write a data block to the eeprom
  439.  * @param address  startaddress to write on eeprom
  440.  * @param buffer   data buffer to get the data from
  441.  * @param len      number of bytes to be written
  442.  **/
  443. void write_block(unsigned int address, byte* buffer, int len) {
  444.   for (unsigned int i = 0; i < len; i++) {
  445.     fast_write(address+i,buffer[i]);
  446.   }  
  447. }
  448.  
  449.  
  450. /**
  451.  * print out a 16 bit word as 4 character hex value
  452.  **/
  453. void printAddress(unsigned int address) {
  454.   if(address < 0x0010) Serial.print("0");
  455.   if(address < 0x0100) Serial.print("0");
  456.   if(address < 0x1000) Serial.print("0");
  457.   Serial.print(address, HEX);
  458.  
  459. }
  460.  
  461. /**
  462.  * print out a byte as 2 character hex value
  463.  **/
  464. void printByte(byte data) {
  465.   if(data < 0x10) Serial.print("0");
  466.   Serial.print(data, HEX);  
  467. }
  468.  
  469.  
  470.  
  471.  
  472.  
  473. /************************************************
  474.  *
  475.  * MAIN
  476.  *
  477.  *************************************************/
  478. void setup() {
  479.   //define the shiuftOut Pins as output
  480.   pinMode(DS, OUTPUT);
  481.   pinMode(LATCH, OUTPUT);
  482.   pinMode(CLOCK, OUTPUT);
  483.  
  484.   //define the EEPROM Pins as output
  485.   // take care that they are HIGH
  486.   digitalWrite(OE, HIGH);
  487.   pinMode(OE, OUTPUT);
  488.   digitalWrite(CE, HIGH);
  489.   pinMode(CE, OUTPUT);
  490.   digitalWrite(WE, HIGH);
  491.   pinMode(WE, OUTPUT);
  492.  
  493.   //set speed of serial connection
  494.   Serial.begin(57600);
  495. }
  496.  
  497. /**
  498.  * main loop, that runs invinite times, parsing a given command and
  499.  * executing the given read or write requestes.
  500.  **/
  501. void loop() {
  502.   readCommand();
  503.   byte cmd = parseCommand();
  504.   int bytes = 0;
  505.   switch(cmd) {
  506.   case READ_HEX:
  507.     //set a default if needed to prevent infinite loop
  508.     if(lineLength==0) lineLength=32;
  509.     endAddress = startAddress + dataLength -1;
  510.     read_block(startAddress,endAddress,lineLength);
  511.     Serial.println('%');
  512.     break;
  513.   case READ_BIN:
  514.     endAddress = startAddress + dataLength -1;
  515.     read_binblock(startAddress,endAddress);
  516.     break;
  517.   case READ_ITL:
  518.     break;
  519.   case WRITE_BIN:
  520.     //take care for max buffer size
  521.     if(dataLength > 1024) dataLength = 1024;
  522.     endAddress = startAddress + dataLength -1;
  523.     while(bytes < dataLength) {
  524.       if(Serial.available()) buffer[bytes++] = Serial.read();
  525.     }    
  526.     write_block(startAddress,buffer,dataLength);
  527.     Serial.println('%');
  528.    
  529.     break;
  530.   case WRITE_HEX:
  531.     break;
  532.   case WRITE_ITL:
  533.     break;
  534.   case VERSION:
  535.     Serial.println(VERSIONSTRING);
  536.     break;
  537.   default:
  538.     break;    
  539.   }
  540.  
  541.  
  542. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement