-
Notifications
You must be signed in to change notification settings - Fork 5
/
ROMCard.cpp
376 lines (346 loc) · 14 KB
/
ROMCard.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
#include "ROMCard.h"
int gCurrentPage = 0;
uint32_t gCurrentAddress = 0;
static bool sAddressPinsUndefined = true;
std::vector <Page> gPageList = {
{ 0x00000000, 0x00800000, "ROM page", "rom.bin" },
{ 0x00800000, 0x01000000, "ROM Extension 1", "rex1.bin" },
{ 0x02000000, 0x02800000, "ROM Extension 2", "rex2.bin" },
{ 0x02800000, 0x03000000, "ROM Extension 3", "rex3.bin" },
{ 0x00000000, 0x01000000, "ROM & ext1", "romrex1.bin" },
{ 0x02000000, 0x03000000, "ext2 & ext3", "rex23.bin" },
//{ 0x00000000, 0x02000000, "full card", "card.bin" },
};
void dataBus(bool active)
{
int mode = active ? OUTPUT : INPUT_PULLUP;
// int mode = active ? OUTPUT : INPUT;
pinMode(eggD0, mode);
pinMode(eggD1, mode);
pinMode(eggD2, mode);
pinMode(eggD3, mode);
pinMode(eggD4, mode);
pinMode(eggD5, mode);
pinMode(eggD6, mode);
pinMode(eggD7, mode);
pinMode(eggD8, mode);
pinMode(eggD9, mode);
pinMode(eggD10, mode);
pinMode(eggD11, mode);
pinMode(eggD12, mode);
pinMode(eggD13, mode);
pinMode(eggD14, mode);
pinMode(eggD15, mode);
pinMode(eggD16, mode);
pinMode(eggD17, mode);
pinMode(eggD18, mode);
pinMode(eggD19, mode);
pinMode(eggD20, mode);
pinMode(eggD21, mode);
pinMode(eggD22, mode);
pinMode(eggD23, mode);
pinMode(eggD24, mode);
pinMode(eggD25, mode);
pinMode(eggD26, mode);
pinMode(eggD27, mode);
pinMode(eggD28, mode);
pinMode(eggD29, mode);
pinMode(eggD30, mode);
pinMode(eggD31, mode);
}
void activateDataBusWrite() { dataBus(true); }
void activateDataBusRead() { dataBus(false); }
void deactivateDataBus() { dataBus(false); }
void addressBus(bool active)
{
int mode = active ? OUTPUT : INPUT_PULLUP;
pinMode(eggA2, mode); // 0x00000004
pinMode(eggA3, mode); // 0x00000008
pinMode(eggA4, mode); // 0x00000010
pinMode(eggA5, mode); // 0x00000020
pinMode(eggA6, mode); // 0x00000040
pinMode(eggA7, mode); // 0x00000080
pinMode(eggA8, mode); // 0x00000100
pinMode(eggA9, mode); // 0x00000200
pinMode(eggA10, mode); // 0x00000400
pinMode(eggA11, mode); // 0x00000800
pinMode(eggA12, mode); // 0x00001000
pinMode(eggA13, mode); // 0x00002000
pinMode(eggA14, mode); // 0x00004000
pinMode(eggA15, mode); // 0x00008000
pinMode(eggA16, mode); // 0x00010000
pinMode(eggA17, mode); // 0x00020000
pinMode(eggA18, mode); // 0x00040000
pinMode(eggA19, mode); // 0x00080000
pinMode(eggA20, mode); // 0x00100000
pinMode(eggA21, mode); // 0x00200000
pinMode(eggA22, mode); // 0x00400000
pinMode(eggA23, mode); // 0x00800000
pinMode(eggA24, mode); // 0x01000000
sAddressPinsUndefined = true;
}
void activateAddressBus() { addressBus(true); }
void deactivateAddressBus() { addressBus(false); }
/**
* Set an address on the address bus.
*
* \param[in] inAddress valid addresses are 0-32MB ind 4 byte steps
*/
void setAddress(uint32_t inAddress)
{
#if 1 // slower version
uint32_t a = inAddress;
a >>= 1;
a >>= 1;
digitalWrite(eggA2, a & 1); a >>= 1;
digitalWrite(eggA3, a & 1); a >>= 1;
digitalWrite(eggA4, a & 1); a >>= 1;
digitalWrite(eggA5, a & 1); a >>= 1;
digitalWrite(eggA6, a & 1); a >>= 1;
digitalWrite(eggA7, a & 1); a >>= 1;
digitalWrite(eggA8, a & 1); a >>= 1;
digitalWrite(eggA9, a & 1); a >>= 1;
digitalWrite(eggA10, a & 1); a >>= 1;
digitalWrite(eggA11, a & 1); a >>= 1;
digitalWrite(eggA12, a & 1); a >>= 1;
digitalWrite(eggA13, a & 1); a >>= 1;
digitalWrite(eggA14, a & 1); a >>= 1;
digitalWrite(eggA15, a & 1); a >>= 1;
digitalWrite(eggA16, a & 1); a >>= 1;
digitalWrite(eggA17, a & 1); a >>= 1;
digitalWrite(eggA18, a & 1); a >>= 1;
digitalWrite(eggA19, a & 1); a >>= 1;
digitalWrite(eggA20, a & 1); a >>= 1;
digitalWrite(eggA21, a & 1); a >>= 1;
digitalWrite(eggA22, a & 1); a >>= 1;
digitalWrite(eggA23, a & 1); a >>= 1;
digitalWrite(eggA24, a & 1); a >>= 1;
#elif 0 // faster version
if (sAddressPinsUndefined)
gCurrentAddress = ~inAddress;
uint32_t a = inAddress;
uint32_t m = inAddress ^ gCurrentAddress;
a >>= 1; m >>= 1;
a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA2, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA3, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA4, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA5, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA6, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA7, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA8, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA9, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA10, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA11, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA12, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA13, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA14, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA15, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA16, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA17, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA18, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA19, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA20, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA21, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA22, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA23, a & 1); a >>= 1; m >>= 1;
if (m&1) digitalWrite(eggA24, a & 1); a >>= 1; m >>= 1;
#else
// make sure that all address pins are refreshed
if (sAddressPinsUndefined)
gCurrentAddress = ~inAddress;
// update only the pins that changed
uint32_t a = inAddress;
uint32_t m = inAddress ^ gCurrentAddress;
a >>= 1; m >>= 1;
a >>= 1; m >>= 1;
for (int i=kAddrMin; i<=kAddrMax; i++) {
if (m&1) digitalWrite(gAdrressLut[i], a & 1);
a >>= 1; m >>= 1;
}
#endif
// set the global address, so we can optimize pin update
// also, gCurrentAddress is used to determine the corresponding CS
gCurrentAddress = inAddress;
}
void activateControlBus()
{
digitalWrite(eggRESET, 1);
pinMode(eggRESET, OUTPUT); // inv
digitalWrite(eggROM_CS_0, 1);
pinMode(eggROM_CS_0, OUTPUT); // inv
digitalWrite(eggROM_CS_1, 1);
pinMode(eggROM_CS_1, OUTPUT); // inv
digitalWrite(eggROM_IO_RD, 1);
pinMode(eggROM_IO_RD, OUTPUT);
digitalWrite(eggROM_IO_WR, 1);
pinMode(eggROM_IO_WR, OUTPUT);
pinMode(eggROM_IO_INT, INPUT);
pinMode(eggROM_IO_RDY, INPUT);
digitalWrite(eggPOWER_ENABLE, 1);
pinMode(eggPOWER_ENABLE, OUTPUT);
}
void deactivateControlBus()
{
pinMode(eggRESET, INPUT_PULLUP);
pinMode(eggROM_CS_0, INPUT_PULLUP);
pinMode(eggROM_CS_1, INPUT_PULLUP);
pinMode(eggROM_IO_RD, INPUT_PULLUP);
pinMode(eggROM_IO_WR, INPUT_PULLUP);
pinMode(eggROM_IO_INT, INPUT_PULLUP);
pinMode(eggROM_IO_RDY, INPUT_PULLUP);
pinMode(eggPOWER_ENABLE, INPUT_PULLUP);
}
void deactivateROMBus()
{
deactivateDataBus();
deactivateAddressBus();
deactivateControlBus();
}
void setupROMBus()
{
deactivateROMBus();
}
uint32_t readWord(uint32_t inAddr)
{
setAddress(inAddr);
return readWord();
}
uint32_t readWord()
{
register uint32_t w = 0;
if (gCurrentAddress & kAddrToCSMask)
digitalWrite(eggROM_CS_1, 0); // select the upper half of the Flash chips
else
digitalWrite(eggROM_CS_0, 0); // select the lower half of the Flash chips
#if 0 // universal
digitalWrite(eggROM_IO_RD, 0); // read operation
w = w << 1; if (digitalRead(eggD31)) w += 1;
w = w << 1; if (digitalRead(eggD30)) w += 1;
w = w << 1; if (digitalRead(eggD29)) w += 1;
w = w << 1; if (digitalRead(eggD28)) w += 1;
w = w << 1; if (digitalRead(eggD27)) w += 1;
w = w << 1; if (digitalRead(eggD26)) w += 1;
w = w << 1; if (digitalRead(eggD25)) w += 1;
w = w << 1; if (digitalRead(eggD24)) w += 1;
w = w << 1; if (digitalRead(eggD23)) w += 1;
w = w << 1; if (digitalRead(eggD22)) w += 1;
w = w << 1; if (digitalRead(eggD21)) w += 1;
w = w << 1; if (digitalRead(eggD20)) w += 1;
w = w << 1; if (digitalRead(eggD19)) w += 1;
w = w << 1; if (digitalRead(eggD18)) w += 1;
w = w << 1; if (digitalRead(eggD17)) w += 1;
w = w << 1; if (digitalRead(eggD16)) w += 1;
w = w << 1; if (digitalRead(eggD15)) w += 1;
w = w << 1; if (digitalRead(eggD14)) w += 1;
w = w << 1; if (digitalRead(eggD13)) w += 1;
w = w << 1; if (digitalRead(eggD12)) w += 1;
w = w << 1; if (digitalRead(eggD11)) w += 1;
w = w << 1; if (digitalRead(eggD10)) w += 1;
w = w << 1; if (digitalRead(eggD9)) w += 1;
w = w << 1; if (digitalRead(eggD8)) w += 1;
w = w << 1; if (digitalRead(eggD7)) w += 1;
w = w << 1; if (digitalRead(eggD6)) w += 1;
w = w << 1; if (digitalRead(eggD5)) w += 1;
w = w << 1; if (digitalRead(eggD4)) w += 1;
w = w << 1; if (digitalRead(eggD3)) w += 1;
w = w << 1; if (digitalRead(eggD2)) w += 1;
w = w << 1; if (digitalRead(eggD1)) w += 1;
w = w << 1; if (digitalRead(eggD0)) w += 1;
digitalWrite(eggROM_IO_RD, 1); // end of read operation
#else // Due specific (saving about 40% of time on "Verify")
PIOB->PIO_CODR = PIO_CODR_P15; // digitalWrite(eggROM_IO_RD, 0); // read operation
asm(" nop\n nop\n nop\n"); // I don't know why I need a delay here, but it will read faulty data without it
asm(" nop\n nop\n nop\n");
uint32_t portA = PIOA->PIO_PDSR;
uint32_t portB = PIOB->PIO_PDSR;
uint32_t portC = PIOC->PIO_PDSR;
uint32_t portD = PIOD->PIO_PDSR;
PIOB->PIO_SODR = PIO_SODR_P15; // digitalWrite(eggROM_IO_RD, 1); // PB15, end of read operation
if (portA & PIO_PDSR_P0) w |= PIO_PDSR_P18; // const int eggD18 = 69; // PA0 A15;
if (portA & PIO_PDSR_P2) w |= PIO_PDSR_P10; // const int eggD10 = A7; // PA2
if (portA & PIO_PDSR_P4) w |= PIO_PDSR_P9; // const int eggD9 = A5; // PA4
if (portA & PIO_PDSR_P6) w |= PIO_PDSR_P8; // const int eggD8 = A4; // PA6
if (portA & PIO_PDSR_P7) w |= PIO_PDSR_P23; // const int eggD23 = 31; // PA7
if (portA & PIO_PDSR_P10) w |= PIO_PDSR_P13; // const int eggD13 = 19; // PA10
if (portA & PIO_PDSR_P12) w |= PIO_PDSR_P12; // const int eggD12 = 17; // PA12
if (portA & PIO_PDSR_P14) w |= PIO_PDSR_P19; // const int eggD19 = 23; // PA14
if (portA & PIO_PDSR_P20) w |= PIO_PDSR_P31; // const int eggD31 = 43; // PA20
if (portA & PIO_PDSR_P22) w |= PIO_PDSR_P7; // const int eggD7 = A3; // PA22
if (portA & PIO_PDSR_P24) w |= PIO_PDSR_P6; // const int eggD6 = A1; // PA24
if (portB & PIO_PDSR_P13) w |= PIO_PDSR_P14; // const int eggD14 = 21; // PB13
if (portB & PIO_PDSR_P16) w |= PIO_PDSR_P17; // const int eggD17 = 67; // PB16 A13;
if (portB & PIO_PDSR_P18) w |= PIO_PDSR_P15; // const int eggD15 = A9; // PB18
if (portB & PIO_PDSR_P20) w |= PIO_PDSR_P16; // const int eggD16 = A11; // PB20
if (portB & PIO_PDSR_P25) w |= PIO_PDSR_P5; // const int eggD5 = 2; // PB25
if (portC & PIO_PDSR_P1) w |= PIO_PDSR_P24; // const int eggD24 = 33; // PC1
if (portC & PIO_PDSR_P3) w |= PIO_PDSR_P25; // const int eggD25 = 35; // PC3
if (portC & PIO_PDSR_P5) w |= PIO_PDSR_P26; // const int eggD26 = 37; // PC5
if (portC & PIO_PDSR_P7) w |= PIO_PDSR_P27; // const int eggD27 = 39; // PC7
if (portC & PIO_PDSR_P14) w |= PIO_PDSR_P28; // const int eggD28 = 49; // PC14
if (portC & PIO_PDSR_P16) w |= PIO_PDSR_P29; // const int eggD29 = 47; // PC16
if (portC & PIO_PDSR_P18) w |= PIO_PDSR_P30; // const int eggD30 = 45; // PC18
if (portC & PIO_PDSR_P22) w |= PIO_PDSR_P2; // const int eggD2 = 8; // PC22
if (portC & PIO_PDSR_P24) w |= PIO_PDSR_P3; // const int eggD3 = 6; // PC24
if (portC & PIO_PDSR_P26) w |= PIO_PDSR_P4; // const int eggD4 = 4; // PC26
if (portC & PIO_PDSR_P29) w |= PIO_PDSR_P1; // const int eggD1 = 10; // PC29
if (portD & PIO_PDSR_P0) w |= PIO_PDSR_P20; // const int eggD20 = 25; // PD0
if (portD & PIO_PDSR_P2) w |= PIO_PDSR_P21; // const int eggD21 = 27; // PD2
if (portD & PIO_PDSR_P5) w |= PIO_PDSR_P11; // const int eggD11 = 15; // PD5
if (portD & PIO_PDSR_P6) w |= PIO_PDSR_P22; // const int eggD22 = 29; // PD6
if (portD & PIO_PDSR_P8) w |= PIO_PDSR_P0; // const int eggD0 = 12; // PD8
#endif
if (gCurrentAddress & kAddrToCSMask)
digitalWrite(eggROM_CS_1, 1); // deselect the upper half of the Flash chips
else
digitalWrite(eggROM_CS_0, 1); // deselect the lower half of the Flash chips
return w;
}
void writeWord(uint32_t a, uint32_t w)
{
setAddress(a);
activateDataBusWrite();
digitalWrite(eggD0, w & 1); w = w >> 1;
digitalWrite(eggD1, w & 1); w = w >> 1;
digitalWrite(eggD2, w & 1); w = w >> 1;
digitalWrite(eggD3, w & 1); w = w >> 1;
digitalWrite(eggD4, w & 1); w = w >> 1;
digitalWrite(eggD5, w & 1); w = w >> 1;
digitalWrite(eggD6, w & 1); w = w >> 1;
digitalWrite(eggD7, w & 1); w = w >> 1;
digitalWrite(eggD8, w & 1); w = w >> 1;
digitalWrite(eggD9, w & 1); w = w >> 1;
digitalWrite(eggD10, w & 1); w = w >> 1;
digitalWrite(eggD11, w & 1); w = w >> 1;
digitalWrite(eggD12, w & 1); w = w >> 1;
digitalWrite(eggD13, w & 1); w = w >> 1;
digitalWrite(eggD14, w & 1); w = w >> 1;
digitalWrite(eggD15, w & 1); w = w >> 1;
digitalWrite(eggD16, w & 1); w = w >> 1;
digitalWrite(eggD17, w & 1); w = w >> 1;
digitalWrite(eggD18, w & 1); w = w >> 1;
digitalWrite(eggD19, w & 1); w = w >> 1;
digitalWrite(eggD20, w & 1); w = w >> 1;
digitalWrite(eggD21, w & 1); w = w >> 1;
digitalWrite(eggD22, w & 1); w = w >> 1;
digitalWrite(eggD23, w & 1); w = w >> 1;
digitalWrite(eggD24, w & 1); w = w >> 1;
digitalWrite(eggD25, w & 1); w = w >> 1;
digitalWrite(eggD26, w & 1); w = w >> 1;
digitalWrite(eggD27, w & 1); w = w >> 1;
digitalWrite(eggD28, w & 1); w = w >> 1;
digitalWrite(eggD29, w & 1); w = w >> 1;
digitalWrite(eggD30, w & 1); w = w >> 1;
digitalWrite(eggD31, w & 1); w = w >> 1;
if (gCurrentAddress & kAddrToCSMask)
digitalWrite(eggROM_CS_1, 0); // select the upper half of the Flash chips
else
digitalWrite(eggROM_CS_0, 0); // select the lower half of the Flash chips
digitalWrite(eggROM_IO_WR, 0); // read operation
digitalWrite(eggROM_IO_WR, 1); // end of read operation
if (gCurrentAddress & kAddrToCSMask)
digitalWrite(eggROM_CS_1, 1); // deselect the upper half of the Flash chips
else
digitalWrite(eggROM_CS_0, 1); // deselect the lower half of the Flash chips
activateDataBusRead();
}