1 /* 2 Interfacing the Arduino Duemilanove to Am29F010 devices. 3 4 Copyright (C) 2015, 2016 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 #ifdef CIRCUIT_74HC273 21 CS1 = 2, CS2 = 3, /* using 74HC273 */ 22 #endif 23 #ifdef CIRCUIT_74HC595 24 SHIFT_SCK = 2, SHIFT_RCK = 3, /* using 74HC595 */ 25 SHIFT_SI = 12, 26 #endif 27 DQ0 = 7, DQ1 = 6, DQ2 = 5, DQ3 = 4, 28 DQ4 = 8, DQ5 = 9, DQ6 = 10, DQ7 = 11; 29 30 const int datapins[8] = {DQ7, DQ6, DQ5, DQ4, DQ3, DQ2, DQ1, DQ0}; 31 const int BUFSIZE = 9; 32 char inbuffer[BUFSIZE]; 33 int nread = 0; 34 35 const char RESET[][9] = { 36 "W05555AA", "W02AAA55", "W05555F0" 37 }; 38 const char ERASE[][9] = { 39 "W05555AA", "W02AAA55", "W0555580", "W05555AA", "W02AAA55" 40 }; 41 const char PROGRAM[][9] = { 42 "W05555AA", "W02AAA55", "W05555A0" 43 }; 44 45 int fromHex(char c) 46 { 47 if ((c >= 48) && (c <= 57)) 48 return c - 48; 49 if ((c >= 65) && (c <= 70)) 50 return c - 65 + 10; 51 if ((c >= 97) && (c <= 102)) 52 return c - 97 + 10; 53 return 0; 54 } 55 56 void setDataOut() 57 { 58 pinMode(DQ0, OUTPUT); 59 pinMode(DQ1, OUTPUT); 60 pinMode(DQ2, OUTPUT); 61 pinMode(DQ3, OUTPUT); 62 pinMode(DQ4, OUTPUT); 63 pinMode(DQ5, OUTPUT); 64 pinMode(DQ6, OUTPUT); 65 pinMode(DQ7, OUTPUT); 66 } 67 68 void setDataIn() 69 { 70 pinMode(DQ0, INPUT); 71 pinMode(DQ1, INPUT); 72 pinMode(DQ2, INPUT); 73 pinMode(DQ3, INPUT); 74 pinMode(DQ4, INPUT); 75 pinMode(DQ5, INPUT); 76 pinMode(DQ6, INPUT); 77 pinMode(DQ7, INPUT); 78 } 79 80 int sampleData() 81 { 82 int i = 0; /* start at DQ7 */ 83 int data = 0; 84 85 while (i < 8) 86 { 87 data <<= 1; 88 data += digitalRead(datapins[i]); 89 i++; 90 } 91 92 return data; 93 } 94 95 int readData() 96 { 97 int data = 0; 98 99 setDataIn(); 100 delayMicroseconds(1); 101 data = sampleData(); 102 setDataOut(); 103 return data; 104 } 105 106 void writeData(int data) 107 { 108 int i = 8; /* start at DQ0 */ 109 110 while (i > 0) 111 { 112 i--; 113 digitalWrite(datapins[i], data % 2); 114 data >>= 1; 115 } 116 } 117 118 #ifdef CIRCUIT_74HC273 119 void setAddress(int high, int low) 120 { 121 /* The top bit is sent directly. */ 122 123 if (high & 0x100) 124 digitalWrite(A16, HIGH); 125 else 126 digitalWrite(A16, LOW); 127 128 /* The lower 16 bits are sent via the latches. */ 129 130 writeData(high); 131 delayMicroseconds(1); 132 digitalWrite(CS2, HIGH); 133 delayMicroseconds(1); 134 digitalWrite(CS2, LOW); 135 writeData(low); 136 delayMicroseconds(1); 137 digitalWrite(CS1, HIGH); 138 delayMicroseconds(1); 139 digitalWrite(CS1, LOW); 140 } 141 #endif 142 143 #ifdef CIRCUIT_74HC595 144 void writeAddress(int v) 145 { 146 int mask; 147 148 for (mask = 0x80; mask; mask >>= 1) 149 { 150 if (v & mask) 151 { 152 digitalWrite(SHIFT_SI, HIGH); 153 } 154 else 155 { 156 digitalWrite(SHIFT_SI, LOW); 157 } 158 159 delayMicroseconds(1); 160 digitalWrite(SHIFT_SCK, HIGH); 161 delayMicroseconds(1); 162 digitalWrite(SHIFT_SCK, LOW); 163 } 164 165 delayMicroseconds(1); 166 digitalWrite(SHIFT_RCK, HIGH); 167 delayMicroseconds(1); 168 digitalWrite(SHIFT_RCK, LOW); 169 } 170 171 void setAddress(int high, int low) 172 { 173 /* The top bit is sent directly. */ 174 175 if (high & 0x100) 176 digitalWrite(A16, HIGH); 177 else 178 digitalWrite(A16, LOW); 179 180 /* The lower 16 bits are sent via the shift registers. */ 181 182 writeAddress(high); 183 writeAddress(low); 184 } 185 #endif 186 187 int readOp(int high, int low) 188 { 189 int data; 190 191 digitalWrite(CE, LOW); 192 setAddress(high, low); 193 delayMicroseconds(1); 194 digitalWrite(OE, LOW); 195 data = readData(); 196 delayMicroseconds(1); 197 digitalWrite(OE, HIGH); 198 digitalWrite(CE, HIGH); 199 200 return data; 201 } 202 203 void writeOp(int high, int low, int data) 204 { 205 digitalWrite(CE, LOW); 206 setAddress(high, low); 207 delayMicroseconds(1); 208 digitalWrite(WE, LOW); 209 writeData(data); 210 delayMicroseconds(1); 211 digitalWrite(WE, HIGH); 212 digitalWrite(CE, HIGH); 213 } 214 215 int readCommand(const char buffer[], int nread) 216 { 217 int high, low; 218 219 high = (fromHex(buffer[1]) << 8) + (fromHex(buffer[2]) << 4) + (fromHex(buffer[3])); 220 low = (fromHex(buffer[4]) << 4) + (fromHex(buffer[5])); 221 222 return readOp(high, low); 223 } 224 225 bool writeCommand(const char buffer[], int nread) 226 { 227 int high, low, data; 228 229 high = (fromHex(buffer[1]) << 8) + (fromHex(buffer[2]) << 4) + (fromHex(buffer[3])); 230 low = (fromHex(buffer[4]) << 4) + (fromHex(buffer[5])); 231 data = (fromHex(buffer[6]) << 4) + (fromHex(buffer[7])); 232 233 writeOp(high, low, data); 234 235 return true; 236 } 237 238 bool haveCompletion(int data, int written) 239 { 240 return ((data & 0x80) == (written & 0x80)); 241 } 242 243 bool haveFault(int data) 244 { 245 return ((data & 0x20) != 0); 246 } 247 248 bool waitForCompletion(int high, int low, int written) 249 { 250 int data; 251 bool match; 252 253 setDataIn(); 254 digitalWrite(CE, LOW); 255 digitalWrite(OE, LOW); 256 257 do 258 { 259 data = readOp(high, low); 260 match = haveCompletion(data, written); 261 } while (!match && !haveFault(data)); 262 263 if (!match) 264 { 265 data = readOp(high, low); 266 match = haveCompletion(data, written); 267 } 268 269 setDataOut(); 270 digitalWrite(OE, HIGH); 271 digitalWrite(CE, HIGH); 272 return match; 273 } 274 275 bool reset() 276 { 277 for (int i = 0; i < 3; i++) 278 { 279 writeCommand(RESET[i], 7); 280 } 281 } 282 283 bool chipErase() 284 { 285 for (int i = 0; i < 5; i++) 286 { 287 writeCommand(ERASE[i], 7); 288 } 289 writeOp(0x55, 0x55, 0x30); 290 return waitForCompletion(0, 0, 0xff); 291 } 292 293 bool sectorErase(const char buffer[]) 294 { 295 int high; 296 297 // 3-bit number shifted to A16...A14. 298 // Thus, only sectors from 0 to 7 are supported. 299 300 high = (fromHex(buffer[1]) << 6) & 0x1ff; 301 302 for (int i = 0; i < 5; i++) 303 { 304 writeCommand(ERASE[i], 7); 305 } 306 writeOp(high, 0, 0x30); 307 308 // Result of erase if 0xff written to all locations. 309 310 return waitForCompletion(high, 0, 0xff); 311 } 312 313 bool program(const char buffer[], int nread) 314 { 315 int high, low, data; 316 317 high = (fromHex(buffer[1]) << 8) + (fromHex(buffer[2]) << 4) + (fromHex(buffer[3])); 318 low = (fromHex(buffer[4]) << 4) + (fromHex(buffer[5])); 319 data = (fromHex(buffer[6]) << 4) + (fromHex(buffer[7])); 320 321 for (int i = 0; i < 3; i++) 322 { 323 writeCommand(PROGRAM[i], 7); 324 } 325 writeOp(high, low, data); 326 327 return waitForCompletion(high, low, data); 328 } 329 330 void setup() 331 { 332 Serial.begin(115200); 333 pinMode(CE, OUTPUT); 334 pinMode(OE, OUTPUT); 335 pinMode(WE, OUTPUT); 336 pinMode(A16, OUTPUT); 337 338 #ifdef CIRCUIT_74HC273 339 pinMode(CS1, OUTPUT); 340 pinMode(CS2, OUTPUT); 341 #endif 342 343 #ifdef CIRCUIT_74HC595 344 pinMode(SHIFT_SCK, OUTPUT); 345 pinMode(SHIFT_RCK, OUTPUT); 346 pinMode(SHIFT_SI, OUTPUT); 347 #endif 348 349 setDataOut(); 350 351 // Initial state for the flash device. 352 353 digitalWrite(CE, HIGH); 354 digitalWrite(OE, HIGH); 355 digitalWrite(WE, HIGH); 356 digitalWrite(A16, LOW); 357 358 // Initial state for the latches. 359 360 #ifdef CIRCUIT_74HC273 361 digitalWrite(CS1, LOW); 362 digitalWrite(CS2, LOW); 363 #endif 364 365 #ifdef CIRCUIT_74HC595 366 digitalWrite(SHIFT_SCK, LOW); 367 digitalWrite(SHIFT_RCK, LOW); 368 #endif 369 370 // Interface loop. 371 372 Serial.println("?"); 373 } 374 375 void loop() 376 { 377 /* Read bytes, obtaining the number read excluding any newline terminator. */ 378 379 if (nread += Serial.readBytesUntil('\n', inbuffer + nread, BUFSIZE - nread)) 380 { 381 /* Handle each command, waiting for the newline. */ 382 383 switch (inbuffer[0]) 384 { 385 case 'r': 386 reset(); 387 Serial.println("r"); 388 nread = 0; 389 break; 390 391 case 'R': 392 if (nread >= 6) 393 { 394 Serial.println(readCommand(inbuffer, nread), HEX); 395 nread = 0; 396 } 397 break; 398 399 case 'W': 400 if (nread >= 8) 401 { 402 if (writeCommand(inbuffer, nread)) 403 Serial.println("W"); 404 else 405 Serial.println("C"); 406 nread = 0; 407 } 408 break; 409 410 case 'E': 411 if (chipErase()) 412 Serial.println("E"); 413 else 414 Serial.println("C"); 415 nread = 0; 416 break; 417 418 case 'S': 419 if (nread >= 2) 420 { 421 if (sectorErase(inbuffer)) 422 Serial.println("S"); 423 else 424 Serial.println("C"); 425 nread = 0; 426 } 427 break; 428 429 case 'P': 430 if (nread >= 8) 431 { 432 if (program(inbuffer, nread)) 433 Serial.println("P"); 434 else 435 Serial.println("C"); 436 nread = 0; 437 } 438 break; 439 440 default: 441 Serial.println(inbuffer[0]); 442 nread = 0; 443 break; 444 } 445 446 Serial.flush(); 447 } 448 } 449 450 extern "C" void __cxa_pure_virtual(void) { 451 while(1); 452 } 453 454 // tabstop=4 expandtab shiftwidth=4