ArduinoAm29F010

ArduinoAm29F010.cpp

31:cb9fe339c6ed
2015-08-23 Paul Boddie Fixed data pin I/O which made assumptions about pin ordering.
     1 /*     2 Interfacing the Arduino Duemilanove to Am29F010 devices.     3      4 Copyright (C) 2015 Paul Boddie <paul@boddie.org.uk>     5      6 This program is free software; you can redistribute it and/or modify it under     7 the terms of the GNU General Public License as published by the Free Software     8 Foundation; either version 3 of the License, or (at your option) any later     9 version.    10     11 This program is distributed in the hope that it will be useful, but WITHOUT ANY    12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A    13 PARTICULAR PURPOSE.  See the GNU General Public License for more details.    14     15 You should have received a copy of the GNU General Public License along    16 with this program.  If not, see <http://www.gnu.org/licenses/>.    17 */    18     19 const int CE = A5, OE = A4, WE = A3, A16 = A2,    20           CS1 = 2, CS2 = 3,    21           DQ0 = 7, DQ1 = 6, DQ2 = 5, DQ3 = 4,    22           DQ4 = 8, DQ5 = 9, DQ6 = 10, DQ7 = 11;    23     24 const int datapins[8] = {DQ7, DQ6, DQ5, DQ4, DQ3, DQ2, DQ1, DQ0};    25 const int BUFSIZE = 9;    26 char inbuffer[BUFSIZE];    27 int nread = 0;    28     29 const char ERASE[][8] = {    30     "W5555AA", "W2AAA55", "W555580", "W5555AA", "W2AAA55"    31     };    32 const char PROGRAM[][8] = {    33     "W5555AA", "W2AAA55", "W5555A0"    34     };    35     36 int fromHex(char c)    37 {    38     if ((c >= 48) && (c <= 57))    39         return c - 48;    40     if ((c >= 65) && (c <= 70))    41         return c - 65 + 10;    42     if ((c >= 97) && (c <= 102))    43         return c - 97 + 10;    44     return 0;    45 }    46     47 void setDataOut()    48 {    49     pinMode(DQ0, OUTPUT);    50     pinMode(DQ1, OUTPUT);    51     pinMode(DQ2, OUTPUT);    52     pinMode(DQ3, OUTPUT);    53     pinMode(DQ4, OUTPUT);    54     pinMode(DQ5, OUTPUT);    55     pinMode(DQ6, OUTPUT);    56     pinMode(DQ7, OUTPUT);    57 }    58     59 void setDataIn()    60 {    61     pinMode(DQ0, INPUT);    62     pinMode(DQ1, INPUT);    63     pinMode(DQ2, INPUT);    64     pinMode(DQ3, INPUT);    65     pinMode(DQ4, INPUT);    66     pinMode(DQ5, INPUT);    67     pinMode(DQ6, INPUT);    68     pinMode(DQ7, INPUT);    69 }    70     71 int sampleData()    72 {    73     int i = 0; /* start at DQ7 */    74     int data = 0;    75     76     while (i < 8)    77     {    78         data <<= 1;    79         data += digitalRead(datapins[i]);    80         i++;    81     }    82     83     return data;    84 }    85     86 int readData()    87 {    88     int data = 0;    89     90     setDataIn();    91     delay(1);    92     data = sampleData();    93     setDataOut();    94     return data;    95 }    96     97 void writeData(int data)    98 {    99     int i = 8; /* start at DQ0 */   100    101     while (i > 0)   102     {   103 	i--;   104         digitalWrite(datapins[i], data % 2);   105         data >>= 1;   106     }   107 }   108    109 void setAddress(int high, int low)   110 {   111     /* The top bit is sent directly. */   112    113     if (high & 0x100)   114         digitalWrite(A16, HIGH);   115     else   116         digitalWrite(A16, LOW);   117    118     /* The lower 16 bits are sent via the latches. */   119    120     writeData(high);   121     delayMicroseconds(1);   122     digitalWrite(CS2, HIGH);   123     delayMicroseconds(1);   124     digitalWrite(CS2, LOW);   125     writeData(low);   126     delayMicroseconds(1);   127     digitalWrite(CS1, HIGH);   128     delayMicroseconds(1);   129     digitalWrite(CS1, LOW);   130 }   131    132 int readOp(int high, int low)   133 {   134     int data;   135    136     digitalWrite(CE, LOW);   137     setAddress(high, low);   138     delay(1);   139     digitalWrite(OE, LOW);   140     data = readData();   141     delay(1);   142     digitalWrite(OE, HIGH);   143     digitalWrite(CE, HIGH);   144    145     return data;   146 }   147    148 void writeOp(int high, int low, int data)   149 {   150     digitalWrite(CE, LOW);   151     setAddress(high, low);   152     delay(1);   153     digitalWrite(WE, LOW);   154     writeData(data);   155     delay(1);   156     digitalWrite(WE, HIGH);   157     digitalWrite(CE, HIGH);   158 }   159    160 int readCommand(const char buffer[], int nread)   161 {   162     int high, low, i;   163    164     if (nread > 5)   165     {   166         high = fromHex(buffer[1]) << 8;   167         i = 2;   168     }   169     else   170     {   171         high = 0;   172         i = 1;   173     }   174    175     high |= (fromHex(buffer[i]) << 4) + (fromHex(buffer[i+1]));   176     low = (fromHex(buffer[i+2]) << 4) + (fromHex(buffer[i+3]));   177    178     return readOp(high, low);   179 }   180    181 bool writeCommand(const char buffer[], int nread)   182 {   183     int high, low, data, i;   184    185     if (nread > 7)   186     {   187         high = fromHex(buffer[1]) << 8;   188         i = 2;   189     }   190     else   191     {   192         high = 0;   193         i = 1;   194     }   195    196     high |= (fromHex(buffer[i]) << 4) + (fromHex(buffer[i+1]));   197     low = (fromHex(buffer[i+2]) << 4) + (fromHex(buffer[i+3]));   198     data = (fromHex(buffer[i+4]) << 4) + (fromHex(buffer[i+5]));   199    200     writeOp(high, low, data);   201    202     return true;   203 }   204    205 bool waitForCompletion(int high, int low, int written)   206 {   207     int data, then = millis();   208    209     setDataIn();   210     digitalWrite(CE, LOW);   211     digitalWrite(OE, LOW);   212    213     do   214     {   215         delay(10);   216         data = sampleData();   217     } while (   218         ((data & 0x80) != (written & 0x80)) &&   219         ((data & 0x20) == 0) &&   220         (millis() - then < 2000)   221         );   222    223     digitalWrite(OE, HIGH);   224     digitalWrite(CE, HIGH);   225     setDataOut();   226     delay(10);   227     return readOp(high, low) == written;   228 }   229    230 bool chipErase()   231 {   232     for (int i = 0; i < 5; i++)   233     {   234         writeCommand(ERASE[i], 7);   235     }   236     writeOp(0x55, 0x55, 0x30);   237     return waitForCompletion(0, 0, 0xff);   238 }   239    240 bool sectorErase(const char buffer[])   241 {   242     int high;   243    244     // 3-bit number shifted to A16...A14.   245     // Thus, only sectors from 0 to 7 are supported.   246    247     high = (fromHex(buffer[1]) << 6) & 0x1ff;   248    249     for (int i = 0; i < 5; i++)   250     {   251         writeCommand(ERASE[i], 7);   252     }   253     writeOp(high, 0, 0x30);   254    255     // Result of erase if 0xff written to all locations.   256    257     return waitForCompletion(high, 0, 0xff);   258 }   259    260 bool program(const char buffer[], int nread)   261 {   262     int high, low, data, i;   263    264     if (nread > 7)   265     {   266         high = fromHex(buffer[1]) << 8;   267         i = 2;   268     }   269     else   270     {   271         high = 0;   272         i = 1;   273     }   274    275     high |= (fromHex(buffer[i]) << 4) + (fromHex(buffer[i+1]));   276     low = (fromHex(buffer[i+2]) << 4) + (fromHex(buffer[i+3]));   277     data = (fromHex(buffer[i+4]) << 4) + (fromHex(buffer[i+5]));   278    279     for (int i = 0; i < 3; i++)   280     {   281         writeCommand(PROGRAM[i], 7);   282     }   283     writeOp(high, low, data);   284    285     return waitForCompletion(high, low, data);   286 }   287    288 void setup()   289 {   290     Serial.begin(115200);   291     pinMode(CE, OUTPUT);   292     pinMode(OE, OUTPUT);   293     pinMode(WE, OUTPUT);   294     pinMode(A16, OUTPUT);   295     pinMode(CS1, OUTPUT);   296     pinMode(CS2, OUTPUT);   297     setDataOut();   298    299     // Initial state for the flash device.   300    301     digitalWrite(CE, HIGH);   302     digitalWrite(OE, HIGH);   303     digitalWrite(WE, HIGH);   304     digitalWrite(A16, LOW);   305    306     // Initial state for the latches.   307    308     digitalWrite(CS1, LOW);   309     digitalWrite(CS2, LOW);   310    311     // Interface loop.   312    313     Serial.println("?");   314 }   315    316 void loop()   317 {   318     if (nread += Serial.readBytesUntil('\n', inbuffer + nread, BUFSIZE - nread))   319     {   320         switch (inbuffer[0])   321         {   322             case 'R':   323             if (nread >= 5)   324             {   325                 Serial.println(readCommand(inbuffer, nread), HEX);   326                 nread = 0;   327             }   328             break;   329    330             case 'W':   331             if (nread >= 7)   332             {   333                 if (writeCommand(inbuffer, nread))   334                     Serial.println("W");   335                 else   336                     Serial.println("C");   337                 nread = 0;   338             }   339             break;   340    341             case 'E':   342             if (chipErase())   343                 Serial.println("E");   344             else   345                 Serial.println("C");   346             nread = 0;   347             break;   348    349             case 'S':   350             if (nread >= 2)   351             {   352                 if (sectorErase(inbuffer))   353                     Serial.println("S");   354                 else   355                     Serial.println("C");   356                 nread = 0;   357             }   358             break;   359    360             case 'P':   361             if (nread >= 7)   362             {   363                 if (program(inbuffer, nread))   364                     Serial.println("P");   365                 else   366                     Serial.println("C");   367                 nread = 0;   368             }   369             break;   370    371             default:   372             Serial.println(inbuffer[0]);   373             nread = 0;   374             break;   375         }   376    377         Serial.flush();   378     }   379 }   380    381 extern "C" void __cxa_pure_virtual(void) {   382     while(1);   383 }   384    385 // tabstop=4 expandtab shiftwidth=4