ArduinoAm29F010

ArduinoAm29F010.cpp

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