ArduinoAm29F010

ArduinoAm29F010.cpp

28:deaef57647e7
2015-08-09 Paul Boddie Added support for controlling A16 when programming. Fixed the read examples.
     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         i = 1;   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[])   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         i = 1;   192    193     high |= (fromHex(buffer[i]) << 4) + (fromHex(buffer[i+1]));   194     low = (fromHex(buffer[i+2]) << 4) + (fromHex(buffer[i+3]));   195     data = (fromHex(buffer[i+4]) << 4) + (fromHex(buffer[i+5]));   196    197     writeOp(high, low, data);   198    199     return true;   200 }   201    202 bool waitForCompletion(int high, int low, int written)   203 {   204     int data, then = millis();   205    206     setDataIn();   207     digitalWrite(CE, LOW);   208     digitalWrite(OE, LOW);   209    210     do   211     {   212         delay(10);   213         data = sampleData();   214     } while (   215         ((data & 0x80) != (written & 0x80)) &&   216         ((data & 0x20) == 0) &&   217         (millis() - then < 2000)   218         );   219    220     digitalWrite(OE, HIGH);   221     digitalWrite(CE, HIGH);   222     setDataOut();   223     delay(10);   224     return readOp(high, low) == written;   225 }   226    227 bool chipErase()   228 {   229     for (int i = 0; i < 5; i++)   230     {   231         writeCommand(ERASE[i]);   232     }   233     writeOp(0x55, 0x55, 0x30);   234     return waitForCompletion(0, 0, 0xff);   235 }   236    237 bool sectorErase(const char buffer[])   238 {   239     int high;   240    241     // 3-bit number shifted to A16...A14 with A16 discarded.   242     // Thus, only sectors from 0 to 3 are supported.   243    244     high = (fromHex(buffer[1]) << 6) & 0xff;   245    246     for (int i = 0; i < 5; i++)   247     {   248         writeCommand(ERASE[i]);   249     }   250     writeOp(high, 0, 0x30);   251    252     // Result of erase if 0xff written to all locations.   253    254     return waitForCompletion(high, 0, 0xff);   255 }   256    257 bool program(const char buffer[])   258 {   259     int high, low, data;   260    261     high = (fromHex(buffer[1]) << 4) + (fromHex(buffer[2]));   262     low = (fromHex(buffer[3]) << 4) + (fromHex(buffer[4]));   263     data = (fromHex(buffer[5]) << 4) + (fromHex(buffer[6]));   264    265     for (int i = 0; i < 3; i++)   266     {   267         writeCommand(PROGRAM[i]);   268     }   269     writeOp(high, low, data);   270    271     return waitForCompletion(high, low, data);   272 }   273    274 void setup()   275 {   276     Serial.begin(115200);   277     pinMode(CE, OUTPUT);   278     pinMode(OE, OUTPUT);   279     pinMode(WE, OUTPUT);   280     pinMode(A16, OUTPUT);   281     pinMode(CS1, OUTPUT);   282     pinMode(CS2, OUTPUT);   283     setDataOut();   284    285     // Initial state for the flash device.   286    287     digitalWrite(CE, HIGH);   288     digitalWrite(OE, HIGH);   289     digitalWrite(WE, HIGH);   290     digitalWrite(A16, LOW);   291    292     // Initial state for the latches.   293    294     digitalWrite(CS1, LOW);   295     digitalWrite(CS2, LOW);   296    297     // Interface loop.   298    299     Serial.println("?");   300 }   301    302 void loop()   303 {   304     if (nread += Serial.readBytesUntil('\n', inbuffer + nread, BUFSIZE - nread))   305     {   306         switch (inbuffer[0])   307         {   308             case 'R':   309             if (nread >= 5)   310             {   311                 Serial.println(readCommand(inbuffer), HEX);   312                 nread = 0;   313             }   314             break;   315    316             case 'W':   317             if (nread >= 7)   318             {   319                 if (writeCommand(inbuffer))   320                     Serial.println("W");   321                 else   322                     Serial.println("C");   323                 nread = 0;   324             }   325             break;   326    327             case 'E':   328             if (chipErase())   329                 Serial.println("E");   330             else   331                 Serial.println("C");   332             nread = 0;   333             break;   334    335             case 'S':   336             if (nread >= 2)   337             {   338                 if (sectorErase(inbuffer))   339                     Serial.println("S");   340                 else   341                     Serial.println("C");   342                 nread = 0;   343             }   344             break;   345    346             case 'P':   347             if (nread >= 7)   348             {   349                 if (program(inbuffer))   350                     Serial.println("P");   351                 else   352                     Serial.println("C");   353                 nread = 0;   354             }   355             break;   356    357             default:   358             Serial.println(inbuffer[0]);   359             nread = 0;   360             break;   361         }   362    363         Serial.flush();   364     }   365 }   366    367 extern "C" void __cxa_pure_virtual(void) {   368     while(1);   369 }   370    371 // tabstop=4 expandtab shiftwidth=4