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