1
1
/*
2
2
MemCARDuino - Arduino PlayStation 1 Memory Card reader
3
- Shendo 2013. - 2016 .
4
-
5
- Compatible with Arduino/Genuino Uno, Duemilanove, Diecimila, Nano, Mini,
6
- basically any board with ATmega168/P or ATmega328/P.
7
-
8
-
9
- THIS IS THE FIXED COMMIT FOR 328/P variants of arduino (Like Uno, Nano v3)
10
- The latest commit made by krzys-h broke the compatibility with the 328/P mcu
3
+ Shendo 2013. - 2023 .
4
+
5
+ Compatible with:
6
+ * Arduino Uno, Duemilanove, Diecimila, Nano, Mini, Fio ( ATmega168/P or ATmega328/P) .
7
+ * Arduino Leonardo, Micro (ATmega32U4)
8
+ * Arduino Mega 2560
9
+ * Espressif ESP8266, ESP32
10
+ * Raspberry Pi Pico
11
11
*/
12
12
13
-
14
13
#include " Arduino.h"
14
+ #include < SPI.h>
15
15
16
16
// Device Firmware identifier
17
- #define IDENTIFIER " MCDINO" // MemCARDuino
18
- #define VERSION 0x05 // Firmware version byte (Major.Minor). Same as the 0x04 version made by Shendo
17
+ #define IDENTIFIER " MCDINO" // MemCARDuino
18
+ #define VERSION 0x06 // Firmware version byte (Major.Minor).
19
19
20
20
// Commands
21
- #define GETID 0xA0 // Get identifier
22
- #define GETVER 0xA1 // Get firmware version
23
- #define MCREAD 0xA2 // Memory Card Read (frame)
24
- #define MCWRITE 0xA3 // Memory Card Write (frame)
21
+ #define GETID 0xA0 // Get identifier
22
+ #define GETVER 0xA1 // Get firmware version
23
+ #define MCREAD 0xA2 // Memory Card Read (frame)
24
+ #define MCWRITE 0xA3 // Memory Card Write (frame)
25
25
26
26
// Responses
27
- #define ERROR 0xE0 // Invalid command received (error)
27
+ #define ERROR 0xE0 // Invalid command received (error)
28
28
29
29
// Memory Card Responses
30
30
// 0x47 - Good
31
31
// 0x4E - BadChecksum
32
32
// 0xFF - BadSector
33
33
34
- // Define pins
35
- #define DataPin 12 // Data
36
- #define CmdPin 11 // Command
37
- #define AttPin 10 // Attention (Select)
38
- #define ClockPin 13 // Clock
39
- #define AckPin 2 // Acknowledge
34
+ #ifndef ICACHE_RAM_ATTR
35
+ #define ICACHE_RAM_ATTR
36
+ #endif
37
+
38
+ // Define pins for each known platform
39
+ #ifdef ESP8266
40
+ #define DataPin 12 // MISO aka Data
41
+ #define AttPin 15 // Attention (SS)
42
+ #define AckPin 2 // Acknowledge
43
+ #elif defined (ESP32)
44
+ #define DataPin 19
45
+ #define CmndPin 23
46
+ #define AttPin 5
47
+ #define ClockPin 18
48
+ #define AckPin 22
49
+ #elif defined (ARDUINO_ARCH_MBED_RP2040)
50
+ #define DataPin 16
51
+ #define CmndPin 19
52
+ #define AttPin 17
53
+ #define ClockPin 18
54
+ #define AckPin 20
55
+ #elif defined (ARDUINO_AVR_MEGA2560)
56
+ #define DataPin 50
57
+ #define AttPin 53
58
+ #define AckPin 2
59
+ #else
60
+ #define DataPin 12
61
+ #define AttPin 10
62
+ #define AckPin 2
63
+ #endif
40
64
41
- byte ReadByte = 0 ;
42
65
volatile int state = HIGH;
43
66
bool CompatibleMode = false ;
67
+ byte ReadData[128 ];
44
68
45
69
// Set up pins for communication
46
70
void PinSetup ()
47
71
{
48
- byte clr = 0 ;
49
-
50
- pinMode (DataPin, INPUT);
51
- pinMode (CmdPin, OUTPUT);
52
72
pinMode (AttPin, OUTPUT);
53
- pinMode (ClockPin, OUTPUT);
54
- pinMode (AckPin, INPUT);
73
+ pinMode (AckPin, INPUT_PULLUP);
55
74
56
- // Set up SPI on Arduino (250 kHz, clock active when low, reading on falling edge of the clock)
57
- SPCR = 0x7F ;
58
- clr=SPSR;
59
- clr=SPDR;
60
-
61
- digitalWrite (DataPin, HIGH); // Activate pullup resistor
62
- digitalWrite (CmdPin, LOW);
63
75
digitalWrite (AttPin, HIGH);
64
- digitalWrite (ClockPin, HIGH);
65
- digitalWrite (AckPin, HIGH); // Activate pullup resistor
66
76
67
- // Set up interrupt on pin 2 (INT.0) for Acknowledge signal
68
- attachInterrupt (0 , ACK, FALLING);
77
+ #ifdef ARDUINO_ARCH_MBED_RP2040
78
+ pinMode (ClockPin, OUTPUT);
79
+ pinMode (CmndPin, OUTPUT);
80
+
81
+ digitalWrite (ClockPin, HIGH);
82
+ digitalWrite (CmndPin, HIGH);
83
+ #else
84
+
85
+ #if ESP32
86
+ SPI.begin (ClockPin, DataPin, CmndPin, -1 );
87
+ #else
88
+ SPI.begin ();
89
+ #endif
90
+ /* Memory Cards on PS1 are accessed at 250Khz but for the compatibility sake
91
+ * we will use 125Khz. For higher speeds external pull-ups are recommended.*/
92
+ SPI.beginTransaction (SPISettings (125000 , LSBFIRST, SPI_MODE3));
93
+ #endif
94
+
95
+ // Enable pullup on MISO Data line
96
+ #if defined(__AVR_ATmega32U4__)
97
+ /* Arduino Leonardo and Micro do not have exposed ICSP pins
98
+ * so we have to enable pullup by referencing the port*/
99
+ PORTB = (1 <<PB3);
100
+ #elif defined(ESP8266)
101
+ /* ESP8266 needs to have each pin reconfigured for a specific purpose.
102
+ * If we just write pin as INPUT_PULLUP it will lose it's function as MISO line
103
+ * Therefore we need to adjust it as MISO with pullup...*/
104
+ PIN_PULLUP_EN (PERIPHS_IO_MUX_MTDI_U);
105
+ #else
106
+ pinMode (DataPin, INPUT_PULLUP);
107
+ #endif
108
+
109
+ /* Set up interrupt for ACK signal from the Memory Card.
110
+ *
111
+ * Should be FALLING because signal goes LOW for ~5uS during ACK
112
+ * but ESP8266 for some reason doesn't register it.
113
+ * So since it goes HIGH anyway after that we will use RISING */
114
+ attachInterrupt (digitalPinToInterrupt (AckPin), ACK, RISING);
69
115
}
70
116
71
117
// Acknowledge routine
72
- void ACK ()
118
+ ICACHE_RAM_ATTR void ACK ()
73
119
{
74
120
state = !state;
75
121
}
76
122
123
+ // Software SPI bit bang, for devices without SPI or with SPI issues
124
+ #ifdef ARDUINO_ARCH_MBED_RP2040
125
+ byte SoftTransfer (byte data)
126
+ {
127
+ byte outData = 0 ;
128
+
129
+ for (int i = 0 ; i < 8 ; i++) {
130
+ digitalWrite (CmndPin, !!(data & (1 << i)));
131
+
132
+ // Clock
133
+ digitalWrite (ClockPin, LOW);
134
+ delayMicroseconds (2 );
135
+
136
+ // Sample input data
137
+ outData |= digitalRead (DataPin) << i;
138
+ digitalWrite (ClockPin, HIGH);
139
+ delayMicroseconds (2 );
140
+ }
141
+
142
+ return outData;
143
+ }
144
+ #endif
145
+
77
146
// Send a command to PlayStation port using SPI
78
- byte SendCommand (byte CommandByte, int Delay)
147
+ byte SendCommand (byte CommandByte, int Timeout, int Delay)
79
148
{
80
- if (!CompatibleMode) Delay = 3000 ; // Timeout
81
- state = HIGH; // Set high state for ACK signal
149
+ if (!CompatibleMode) Timeout = 3000 ;
150
+ state = HIGH; // Set high state for ACK signal
151
+
152
+ // Delay for a bit (values simulating delays between real PS1 and Memory Card)
153
+ delayMicroseconds (Delay );
82
154
83
- SPDR = CommandByte; // Start the transmission
84
- while (!(SPSR & (1 <<SPIF))); // Wait for the end of the transmission
155
+ // Send data on the SPI bus
156
+ #ifdef ARDUINO_ARCH_MBED_RP2040
157
+ /* Raspberry Pi Pico currently has some issues with SPI data corruption.
158
+ * So for now we are gonna do some bit banging, Pico has plenty of power to do it in software.*/
159
+ byte data = SoftTransfer (CommandByte);
160
+ #else
161
+ byte data = SPI.transfer (CommandByte);
162
+ #endif
85
163
86
164
// Wait for the ACK signal from the Memory Card
87
165
while (state == HIGH)
88
166
{
89
- Delay --;
167
+ Timeout --;
90
168
delayMicroseconds (1 );
91
- if (Delay == 0 ){
169
+ if (Timeout == 0 ){
92
170
// Timeout reached, card doesn't report ACK properly
93
171
CompatibleMode = true ;
94
172
break ;
95
173
}
96
174
}
97
175
98
- return SPDR ; // Return the received byte
176
+ return data ; // Return the received byte
99
177
}
100
178
101
179
// Read a frame from Memory Card and send it to serial port
@@ -108,52 +186,53 @@ void ReadFrame(unsigned int Address)
108
186
CompatibleMode = false ;
109
187
110
188
// Activate device
111
- PORTB &= 0xFB ; // Set pin 10 (AttPin, LOW)
112
-
113
- SendCommand (0x81 , 500 ); // Access Memory Card
114
- SendCommand (0x52 , 500 ); // Send read command
115
- SendCommand (0x00 , 500 ); // Memory Card ID1
116
- SendCommand (0x00 , 500 ); // Memory Card ID2
117
- SendCommand (AddressMSB, 500 ); // Address MSB
118
- SendCommand (AddressLSB, 500 ); // Address LSB
119
- SendCommand (0x00 , 2800 ); // Memory Card ACK1
120
- SendCommand (0x00 , 2800 ); // Memory Card ACK2
121
- SendCommand (0x00 , 2800 ); // Confirm MSB
122
- SendCommand (0x00 , 2800 ); // Confirm LSB
189
+ digitalWrite (AttPin, LOW);
190
+ delayMicroseconds (20 );
191
+
192
+ SendCommand (0x81 , 500 , 70 ); // Access Memory Card
193
+ SendCommand (0x52 , 500 , 45 ); // Send read command
194
+ SendCommand (0x00 , 500 , 45 ); // Memory Card ID1
195
+ SendCommand (0x00 , 500 , 45 ); // Memory Card ID2
196
+ SendCommand (AddressMSB, 500 , 45 ); // Address MSB
197
+ SendCommand (AddressLSB, 500 , 45 ); // Address LSB
198
+ SendCommand (0x00 , 2800 , 45 ); // Memory Card ACK1
199
+ SendCommand (0x00 , 2800 , 0 ); // Memory Card ACK2
200
+ SendCommand (0x00 , 2800 , 0 ); // Confirm MSB
201
+ SendCommand (0x00 , 2800 , 0 ); // Confirm LSB
123
202
124
203
// Get 128 byte data from the frame
125
204
for (int i = 0 ; i < 128 ; i++)
126
205
{
127
- Serial.write (SendCommand (0x00 , 150 ));
206
+ Serial.write (SendCommand (0x00 , 150 , 0 ));
128
207
}
129
208
130
- Serial.write (SendCommand (0x00 , 500 )); // Checksum (MSB xor LSB xor Data)
131
- Serial.write (SendCommand (0x00 , 500 )); // Memory Card status byte
209
+ Serial.write (SendCommand (0x00 , 500 , 0 )); // Checksum (MSB xor LSB xor Data)
210
+ Serial.write (SendCommand (0x00 , 0 , 0 )); // Memory Card status byte
132
211
133
212
// Deactivate device
134
- PORTB |= 4 ; // Set pin 10 (AttPin, HIGH)
213
+ digitalWrite (AttPin, HIGH);
135
214
}
136
215
137
216
// Write a frame from the serial port to the Memory Card
138
217
void WriteFrame (unsigned int Address)
139
218
{
140
219
byte AddressMSB = Address & 0xFF ;
141
220
byte AddressLSB = (Address >> 8 ) & 0xFF ;
142
- byte ReadData[128 ];
143
221
int DelayCounter = 30 ;
144
222
145
223
// Use ACK detection mode by default
146
224
CompatibleMode = false ;
147
225
148
226
// Activate device
149
- PORTB &= 0xFB ; // Set pin 10 (AttPin, LOW)
227
+ digitalWrite (AttPin, LOW);
228
+ delayMicroseconds (20 );
150
229
151
- SendCommand (0x81 , 300 ); // Access Memory Card
152
- SendCommand (0x57 , 300 ); // Send write command
153
- SendCommand (0x00 , 300 ); // Memory Card ID1
154
- SendCommand (0x00 , 300 ); // Memory Card ID2
155
- SendCommand (AddressMSB, 300 ); // Address MSB
156
- SendCommand (AddressLSB, 300 ); // Address LSB
230
+ SendCommand (0x81 , 300 , 45 ); // Access Memory Card
231
+ SendCommand (0x57 , 300 , 45 ); // Send write command
232
+ SendCommand (0x00 , 300 , 45 ); // Memory Card ID1
233
+ SendCommand (0x00 , 300 , 45 ); // Memory Card ID2
234
+ SendCommand (AddressMSB, 300 , 45 ); // Address MSB
235
+ SendCommand (AddressLSB, 300 , 45 ); // Address LSB
157
236
158
237
// Copy 128 bytes from the serial input
159
238
for (int i = 0 ; i < 128 ; i++)
@@ -171,22 +250,22 @@ void WriteFrame(unsigned int Address)
171
250
// Write 128 byte data to the frame
172
251
for (int i = 0 ; i < 128 ; i++)
173
252
{
174
- SendCommand (ReadData[i], 150 );
253
+ SendCommand (ReadData[i], 150 , 0 );
175
254
}
176
255
177
- SendCommand (Serial.read (), 200 ); // Checksum (MSB xor LSB xor Data)
178
- SendCommand (0x00 , 200 ); // Memory Card ACK1
179
- SendCommand (0x00 , 200 ); // Memory Card ACK2
180
- Serial.write (SendCommand (0x00 , 200 )); // Memory Card status byte
256
+ SendCommand (Serial.read (), 200 , 0 ); // Checksum (MSB xor LSB xor Data)
257
+ SendCommand (0x00 , 200 , 0 ); // Memory Card ACK1
258
+ SendCommand (0x00 , 200 , 0 ); // Memory Card ACK2
259
+ Serial.write (SendCommand (0x00 , 0 , 0 )); // Memory Card status byte
181
260
182
261
// Deactivate device
183
- PORTB |= 4 ; // Set pin 10 (AttPin, HIGH)
262
+ digitalWrite (AttPin, HIGH);
184
263
}
185
264
186
265
void setup ()
187
266
{
188
267
// Set up serial communication
189
- Serial.begin (38400 );
268
+ Serial.begin (115200 );
190
269
191
270
// Set up pins
192
271
PinSetup ();
@@ -197,9 +276,7 @@ void loop()
197
276
// Listen for commands
198
277
if (Serial.available () > 0 )
199
278
{
200
- ReadByte = Serial.read ();
201
-
202
- switch (ReadByte)
279
+ switch (Serial.read ())
203
280
{
204
281
default :
205
282
Serial.write (ERROR);
@@ -214,13 +291,13 @@ void loop()
214
291
break ;
215
292
216
293
case MCREAD:
217
- delay (5 );
218
- ReadFrame (Serial.read () | Serial.read () << 8 );
294
+ delay (5 );
295
+ ReadFrame (Serial.read () | Serial.read () << 8 );
219
296
break ;
220
297
221
298
case MCWRITE:
222
- delay (5 );
223
- WriteFrame (Serial.read () | Serial.read () << 8 );
299
+ delay (5 );
300
+ WriteFrame (Serial.read () | Serial.read () << 8 );
224
301
break ;
225
302
}
226
303
}
0 commit comments