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 RESET[][9] = { 30 "W05555AA", "W02AAA55", "W05555F0" 31 }; 32 const char ERASE[][9] = { 33 "W05555AA", "W02AAA55", "W0555580", "W05555AA", "W02AAA55" 34 }; 35 const char PROGRAM[][9] = { 36 "W05555AA", "W02AAA55", "W05555A0" 37 }; 38 39 int fromHex(char c) 40 { 41 if ((c >= 48) && (c <= 57)) 42 return c - 48; 43 if ((c >= 65) && (c <= 70)) 44 return c - 65 + 10; 45 if ((c >= 97) && (c <= 102)) 46 return c - 97 + 10; 47 return 0; 48 } 49 50 void setDataOut() 51 { 52 pinMode(DQ0, OUTPUT); 53 pinMode(DQ1, OUTPUT); 54 pinMode(DQ2, OUTPUT); 55 pinMode(DQ3, OUTPUT); 56 pinMode(DQ4, OUTPUT); 57 pinMode(DQ5, OUTPUT); 58 pinMode(DQ6, OUTPUT); 59 pinMode(DQ7, OUTPUT); 60 } 61 62 void setDataIn() 63 { 64 pinMode(DQ0, INPUT); 65 pinMode(DQ1, INPUT); 66 pinMode(DQ2, INPUT); 67 pinMode(DQ3, INPUT); 68 pinMode(DQ4, INPUT); 69 pinMode(DQ5, INPUT); 70 pinMode(DQ6, INPUT); 71 pinMode(DQ7, INPUT); 72 } 73 74 int sampleData() 75 { 76 int i = 0; /* start at DQ7 */ 77 int data = 0; 78 79 while (i < 8) 80 { 81 data <<= 1; 82 data += digitalRead(datapins[i]); 83 i++; 84 } 85 86 return data; 87 } 88 89 int readData() 90 { 91 int data = 0; 92 93 setDataIn(); 94 delayMicroseconds(1); 95 data = sampleData(); 96 setDataOut(); 97 return data; 98 } 99 100 void writeData(int data) 101 { 102 int i = 8; /* start at DQ0 */ 103 104 while (i > 0) 105 { 106 i--; 107 digitalWrite(datapins[i], data % 2); 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 delayMicroseconds(1); 142 digitalWrite(OE, LOW); 143 data = readData(); 144 delayMicroseconds(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 delayMicroseconds(1); 156 digitalWrite(WE, LOW); 157 writeData(data); 158 delayMicroseconds(1); 159 digitalWrite(WE, HIGH); 160 digitalWrite(CE, HIGH); 161 } 162 163 int readCommand(const char buffer[], int nread) 164 { 165 int high, low; 166 167 high = (fromHex(buffer[1]) << 8) + (fromHex(buffer[2]) << 4) + (fromHex(buffer[3])); 168 low = (fromHex(buffer[4]) << 4) + (fromHex(buffer[5])); 169 170 return readOp(high, low); 171 } 172 173 bool writeCommand(const char buffer[], int nread) 174 { 175 int high, low, data; 176 177 high = (fromHex(buffer[1]) << 8) + (fromHex(buffer[2]) << 4) + (fromHex(buffer[3])); 178 low = (fromHex(buffer[4]) << 4) + (fromHex(buffer[5])); 179 data = (fromHex(buffer[6]) << 4) + (fromHex(buffer[7])); 180 181 writeOp(high, low, data); 182 183 return true; 184 } 185 186 bool haveCompletion(int data, int written) 187 { 188 return ((data & 0x80) == (written & 0x80)); 189 } 190 191 bool haveFault(int data) 192 { 193 return ((data & 0x20) != 0); 194 } 195 196 bool waitForCompletion(int high, int low, int written) 197 { 198 int data; 199 bool match; 200 201 setDataIn(); 202 digitalWrite(CE, LOW); 203 digitalWrite(OE, LOW); 204 205 do 206 { 207 data = readOp(high, low); 208 match = haveCompletion(data, written); 209 } while (!match && !haveFault(data)); 210 211 if (!match) 212 { 213 data = readOp(high, low); 214 match = haveCompletion(data, written); 215 } 216 217 setDataOut(); 218 digitalWrite(OE, HIGH); 219 digitalWrite(CE, HIGH); 220 return match; 221 } 222 223 bool reset() 224 { 225 for (int i = 0; i < 3; i++) 226 { 227 writeCommand(RESET[i], 7); 228 } 229 } 230 231 bool chipErase() 232 { 233 for (int i = 0; i < 5; i++) 234 { 235 writeCommand(ERASE[i], 7); 236 } 237 writeOp(0x55, 0x55, 0x30); 238 return waitForCompletion(0, 0, 0xff); 239 } 240 241 bool sectorErase(const char buffer[]) 242 { 243 int high; 244 245 // 3-bit number shifted to A16...A14. 246 // Thus, only sectors from 0 to 7 are supported. 247 248 high = (fromHex(buffer[1]) << 6) & 0x1ff; 249 250 for (int i = 0; i < 5; i++) 251 { 252 writeCommand(ERASE[i], 7); 253 } 254 writeOp(high, 0, 0x30); 255 256 // Result of erase if 0xff written to all locations. 257 258 return waitForCompletion(high, 0, 0xff); 259 } 260 261 bool program(const char buffer[], int nread) 262 { 263 int high, low, data; 264 265 high = (fromHex(buffer[1]) << 8) + (fromHex(buffer[2]) << 4) + (fromHex(buffer[3])); 266 low = (fromHex(buffer[4]) << 4) + (fromHex(buffer[5])); 267 data = (fromHex(buffer[6]) << 4) + (fromHex(buffer[7])); 268 269 for (int i = 0; i < 3; i++) 270 { 271 writeCommand(PROGRAM[i], 7); 272 } 273 writeOp(high, low, data); 274 275 return waitForCompletion(high, low, data); 276 } 277 278 void setup() 279 { 280 Serial.begin(115200); 281 pinMode(CE, OUTPUT); 282 pinMode(OE, OUTPUT); 283 pinMode(WE, OUTPUT); 284 pinMode(A16, OUTPUT); 285 pinMode(CS1, OUTPUT); 286 pinMode(CS2, OUTPUT); 287 setDataOut(); 288 289 // Initial state for the flash device. 290 291 digitalWrite(CE, HIGH); 292 digitalWrite(OE, HIGH); 293 digitalWrite(WE, HIGH); 294 digitalWrite(A16, LOW); 295 296 // Initial state for the latches. 297 298 digitalWrite(CS1, LOW); 299 digitalWrite(CS2, LOW); 300 301 // Interface loop. 302 303 Serial.println("?"); 304 } 305 306 void loop() 307 { 308 /* Read bytes, obtaining the number read excluding any newline terminator. */ 309 310 if (nread += Serial.readBytesUntil('\n', inbuffer + nread, BUFSIZE - nread)) 311 { 312 /* Handle each command, waiting for the newline. */ 313 314 switch (inbuffer[0]) 315 { 316 case 'r': 317 reset(); 318 Serial.println("r"); 319 nread = 0; 320 break; 321 322 case 'R': 323 if (nread >= 6) 324 { 325 Serial.println(readCommand(inbuffer, nread), HEX); 326 nread = 0; 327 } 328 break; 329 330 case 'W': 331 if (nread >= 8) 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 >= 8) 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