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, 20 CS1 = 2, CS2 = 3, 21 DQ0 = 4, DQ1 = 5, DQ2 = 6, DQ3 = 7, 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 writeData(high); 115 delayMicroseconds(1); 116 digitalWrite(CS2, HIGH); 117 delayMicroseconds(1); 118 digitalWrite(CS2, LOW); 119 writeData(low); 120 delayMicroseconds(1); 121 digitalWrite(CS1, HIGH); 122 delayMicroseconds(1); 123 digitalWrite(CS1, LOW); 124 } 125 126 int readOp(int high, int low) 127 { 128 int data; 129 130 digitalWrite(CE, LOW); 131 setAddress(high, low); 132 delay(1); 133 digitalWrite(OE, LOW); 134 data = readData(); 135 delay(1); 136 digitalWrite(OE, HIGH); 137 digitalWrite(CE, HIGH); 138 139 return data; 140 } 141 142 void writeOp(int high, int low, int data) 143 { 144 digitalWrite(CE, LOW); 145 setAddress(high, low); 146 delay(1); 147 digitalWrite(WE, LOW); 148 writeData(data); 149 delay(1); 150 digitalWrite(WE, HIGH); 151 digitalWrite(CE, HIGH); 152 } 153 154 int readCommand(const char buffer[]) 155 { 156 int high, low; 157 158 high = (fromHex(buffer[1]) << 4) + (fromHex(buffer[2])); 159 low = (fromHex(buffer[3]) << 4) + (fromHex(buffer[4])); 160 161 return readOp(high, low); 162 } 163 164 bool writeCommand(const char buffer[]) 165 { 166 int high, low, data; 167 168 high = (fromHex(buffer[1]) << 4) + (fromHex(buffer[2])); 169 low = (fromHex(buffer[3]) << 4) + (fromHex(buffer[4])); 170 data = (fromHex(buffer[5]) << 4) + (fromHex(buffer[6])); 171 172 writeOp(high, low, data); 173 174 return true; 175 } 176 177 bool waitForCompletion(int high, int low, int written) 178 { 179 int data, then = millis(); 180 181 setDataIn(); 182 digitalWrite(CE, LOW); 183 digitalWrite(OE, LOW); 184 185 do 186 { 187 delay(10); 188 data = sampleData(); 189 } while ( 190 ((data & 0x80) != (written & 0x80)) && 191 ((data & 0x20) == 0) && 192 (millis() - then < 2000) 193 ); 194 195 digitalWrite(OE, HIGH); 196 digitalWrite(CE, HIGH); 197 setDataOut(); 198 delay(10); 199 return readOp(high, low) == written; 200 } 201 202 bool chipErase() 203 { 204 for (int i = 0; i < 5; i++) 205 { 206 writeCommand(ERASE[i]); 207 } 208 writeOp(0x55, 0x55, 0x30); 209 return waitForCompletion(0, 0, 0xff); 210 } 211 212 bool sectorErase(const char buffer[]) 213 { 214 int high; 215 216 // 3-bit number shifted to A16...A14 with A16 discarded. 217 // Thus, only sectors from 0 to 3 are supported. 218 219 high = (fromHex(buffer[1]) << 6) & 0xff; 220 221 for (int i = 0; i < 5; i++) 222 { 223 writeCommand(ERASE[i]); 224 } 225 writeOp(high, 0, 0x30); 226 227 // Result of erase if 0xff written to all locations. 228 229 return waitForCompletion(high, 0, 0xff); 230 } 231 232 bool program(const char buffer[]) 233 { 234 int high, low, data; 235 236 high = (fromHex(buffer[1]) << 4) + (fromHex(buffer[2])); 237 low = (fromHex(buffer[3]) << 4) + (fromHex(buffer[4])); 238 data = (fromHex(buffer[5]) << 4) + (fromHex(buffer[6])); 239 240 for (int i = 0; i < 3; i++) 241 { 242 writeCommand(PROGRAM[i]); 243 } 244 writeOp(high, low, data); 245 246 return waitForCompletion(high, low, data); 247 } 248 249 void setup() 250 { 251 Serial.begin(115200); 252 pinMode(CE, OUTPUT); 253 pinMode(OE, OUTPUT); 254 pinMode(WE, OUTPUT); 255 pinMode(CS1, OUTPUT); 256 pinMode(CS2, OUTPUT); 257 setDataOut(); 258 259 // Initial state for the flash device. 260 261 digitalWrite(CE, HIGH); 262 digitalWrite(OE, HIGH); 263 digitalWrite(WE, HIGH); 264 265 // Initial state for the latches. 266 267 digitalWrite(CS1, LOW); 268 digitalWrite(CS2, LOW); 269 270 // Interface loop. 271 272 Serial.println("?"); 273 } 274 275 void loop() 276 { 277 if (nread += Serial.readBytesUntil('\n', inbuffer + nread, BUFSIZE - nread)) 278 { 279 switch (inbuffer[0]) 280 { 281 case 'R': 282 if (nread >= 5) 283 { 284 Serial.println(readCommand(inbuffer), HEX); 285 nread = 0; 286 } 287 break; 288 289 case 'W': 290 if (nread >= 7) 291 { 292 if (writeCommand(inbuffer)) 293 Serial.println("W"); 294 else 295 Serial.println("C"); 296 nread = 0; 297 } 298 break; 299 300 case 'E': 301 if (chipErase()) 302 Serial.println("E"); 303 else 304 Serial.println("C"); 305 nread = 0; 306 break; 307 308 case 'S': 309 if (nread >= 2) 310 { 311 if (sectorErase(inbuffer)) 312 Serial.println("S"); 313 else 314 Serial.println("C"); 315 nread = 0; 316 } 317 break; 318 319 case 'P': 320 if (nread >= 7) 321 { 322 if (program(inbuffer)) 323 Serial.println("P"); 324 else 325 Serial.println("C"); 326 nread = 0; 327 } 328 break; 329 330 default: 331 Serial.println(inbuffer[0]); 332 nread = 0; 333 break; 334 } 335 336 Serial.flush(); 337 } 338 } 339 340 extern "C" void __cxa_pure_virtual(void) { 341 while(1); 342 } 343 344 // tabstop=4 expandtab shiftwidth=4