Skip to content

Commit a8ab944

Browse files
committed
Improving reliability of card transfers
1 parent 3d4b5f9 commit a8ab944

File tree

6 files changed

+130
-29
lines changed

6 files changed

+130
-29
lines changed

examples/LinkCard_demo/#loader/localize.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ const data = {
1616
"MSG_TRANSFERRING": "TRANSFERRING",
1717
"MSG_CARD_SENT": "CARD SENT",
1818
"MSG_ERROR": "ERROR",
19-
"MSG_PRESS_B_CANCEL": "PRESS B TO CANCEL"
19+
"MSG_PRESS_B_CANCEL": "PRESS B TO CANCEL",
20+
"MSG_NUMBERS": "0123456789"
2021
};
2122
*/
2223

examples/LinkCard_demo/#loader/src/link.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,14 @@ bool send(u16 data, CancelCallback cancel) {
8484
bool sendAndExpect(u16 data, u16 expect, CancelCallback cancel) {
8585
u16 received;
8686
do {
87-
if (!send(data, cancel))
87+
bool sent = false;
88+
for (u32 attempt = 0; attempt < 3; attempt++) {
89+
if (send(data, cancel)) {
90+
sent = true;
91+
break;
92+
}
93+
}
94+
if (!sent)
8895
return false;
8996

9097
received = getDataFromPlayer0();

examples/LinkCard_demo/#loader/src/main.c

Lines changed: 118 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,21 @@
33
#include "link.h"
44
#include "protocol.h"
55

6-
#ifdef REGION_JAP
6+
// Enable this to simulate failed scans with ⮜ and successful scans with ➤
7+
#define DEBUG_MODE 0
8+
9+
// Enable this to display error codes
10+
#define DISPLAY_ERROR_CODES 1
11+
712
// Japanese strings are encoded as Shift-JIS byte arrays.
13+
#ifdef REGION_JAP
14+
#if DISPLAY_ERROR_CODES == 1
15+
/* "0123456789" */
16+
const u8 MSG_NUMBERS[] = {0x82, 0x4f, 0x82, 0x50, 0x82, 0x51, 0x82,
17+
0x52, 0x82, 0x53, 0x82, 0x54, 0x82, 0x55,
18+
0x82, 0x56, 0x82, 0x57, 0x82, 0x58, 0x00};
19+
#endif
20+
821
#ifdef LANGUAGE_ENG
922
const u8 MSG_WAITING_GAME[] = {
1023
0x82, 0x76, 0x82, 0x60, 0x82, 0x68, 0x82, 0x73, 0x82, 0x68, 0x82,
@@ -62,8 +75,42 @@ extern int __end[];
6275
ERAPI_HANDLE_REGION region;
6376
u8 card[CARD_BUFFER_SIZE];
6477
const u16 palette[] = {0x0000, 0xFFFF};
78+
u32 previousKeys = 0;
79+
80+
#if DISPLAY_ERROR_CODES == 1
81+
void codeToString(char* buf, int num) {
82+
#ifdef REGION_JAP
83+
const u8* digits = MSG_NUMBERS;
84+
int temp[5];
85+
int len = 0;
86+
do {
87+
temp[len++] = num % 10;
88+
num /= 10;
89+
} while (num && len < 5);
90+
91+
u8* p = (u8*)buf;
92+
for (int i = len - 1; i >= 0; --i) {
93+
int idx = temp[i] * 2;
94+
*p++ = digits[idx];
95+
*p++ = digits[idx + 1];
96+
}
97+
*p = 0;
98+
#else
99+
char temp[6];
100+
int pos = 0;
101+
do {
102+
temp[pos++] = '0' + (num % 10);
103+
num /= 10;
104+
} while (num && pos < 5);
105+
int j = 0;
106+
while (pos)
107+
buf[j++] = temp[--pos];
108+
buf[j] = '\0';
109+
#endif
110+
}
111+
#endif
65112

66-
void print(const char* text);
113+
void print(const char* text, bool canCancel);
67114
bool cancel();
68115
void reset();
69116

@@ -85,14 +132,13 @@ int main() {
85132

86133
// loop
87134
while (1) {
88-
if (cancel())
89-
break;
135+
u32 errorCode = 0;
90136

91137
// init loader
92138
reset();
93139

94140
// "Waiting for game..."
95-
print(MSG_WAITING_GAME);
141+
print(MSG_WAITING_GAME, false);
96142

97143
// handshake with game
98144
if (!sendAndExpect(HANDSHAKE_1, HANDSHAKE_1, cancel))
@@ -104,54 +150,91 @@ int main() {
104150

105151
// wait for card request
106152
u16 cardRequest = sendAndReceiveExcept(HANDSHAKE_3, HANDSHAKE_3, cancel);
107-
if (cardRequest != GAME_REQUEST)
153+
if (cardRequest != GAME_REQUEST) {
154+
errorCode = 1;
108155
goto error;
156+
}
109157

110158
// confirm card request
111159
if (!sendAndExpect(GAME_ANIMATING, EREADER_ANIMATING, cancel))
112160
continue;
113161
if (!send(EREADER_ANIMATING, cancel))
114162
continue;
115163

116-
// "Scan a card!"
117-
print(MSG_SCAN_CARD);
118-
119164
// scan card
120-
if (cancel())
121-
goto abort;
122-
if (!sendAndExpect(EREADER_READY, GAME_READY, cancel))
123-
goto abort;
165+
if (!sendAndExpect(EREADER_READY, GAME_READY, cancel)) {
166+
errorCode = 2;
167+
goto error;
168+
}
124169

170+
// "Scan a card!"
171+
print(MSG_SCAN_CARD, false);
172+
173+
#if DEBUG_MODE == 1
174+
u32 resultCode = 0;
175+
while (true) {
176+
u32 debugKeys = ERAPI_GetKeyStateRaw();
177+
if ((debugKeys & ERAPI_KEY_LEFT) != 0) {
178+
resultCode = SCAN_SUCCESS - 1;
179+
break;
180+
}
181+
if ((debugKeys & ERAPI_KEY_RIGHT) != 0) {
182+
resultCode = SCAN_SUCCESS;
183+
const char msg[] = "HelloWorld";
184+
const u32 msgLen = sizeof(msg) - 1;
185+
const u32 byteCount = CARD_BUFFER_SIZE - CARD_OFFSET;
186+
for (u32 i = 0; i < byteCount; i++)
187+
card[CARD_OFFSET + i] = i == byteCount - 1 ? '!' : msg[i % msgLen];
188+
break;
189+
}
190+
}
191+
#else
125192
u32 resultCode = ERAPI_ScanDotCode((u32)card);
126-
if (resultCode != SCAN_SUCCESS)
193+
#endif
194+
195+
if (resultCode != SCAN_SUCCESS) {
196+
errorCode = 3;
127197
goto error;
198+
}
128199

129200
// "Transferring..."
130-
print(MSG_TRANSFERRING);
201+
print(MSG_TRANSFERRING, true);
131202

132203
// transfer start
133-
if (!sendAndExpect(EREADER_SEND_READY, GAME_RECEIVE_READY, cancel))
204+
if (!sendAndExpect(EREADER_SEND_READY, GAME_RECEIVE_READY, cancel)) {
205+
errorCode = 4;
134206
goto error;
135-
if (!send(EREADER_SEND_START, cancel))
207+
}
208+
if (!send(EREADER_SEND_START, cancel)) {
209+
errorCode = 5;
136210
goto error;
211+
}
137212

138213
// transfer
139214
u32 checksum = 0;
140215
for (u32 o = CARD_OFFSET; o < CARD_SIZE; o += 2) {
141216
u16 block = *(u16*)(card + o);
142-
if (!send(block, cancel))
217+
if (!send(block, cancel)) {
218+
errorCode = 6;
143219
goto error;
220+
}
144221
checksum += block;
145222
}
146-
if (!send(checksum & 0xffff, cancel))
223+
if (!send(checksum & 0xffff, cancel)) {
224+
errorCode = 7;
147225
goto error;
148-
if (!send(checksum >> 16, cancel))
226+
}
227+
if (!send(checksum >> 16, cancel)) {
228+
errorCode = 8;
149229
goto error;
150-
if (!send(EREADER_SEND_END, cancel))
230+
}
231+
if (!send(EREADER_SEND_END, cancel)) {
232+
errorCode = 9;
151233
goto error;
234+
}
152235

153236
// "Card sent!"
154-
print(MSG_CARD_SENT);
237+
print(MSG_CARD_SENT, false);
155238
for (u32 i = 0; i < POST_TRANSFER_WAIT; i++)
156239
ERAPI_RenderFrame(1);
157240

@@ -168,7 +251,13 @@ int main() {
168251
// "Error!"
169252
ERAPI_ClearRegion(region);
170253
ERAPI_DrawText(region, 0, 0, MSG_ERROR);
254+
#if DISPLAY_ERROR_CODES == 1
255+
char errorCodeStr[11];
256+
codeToString(errorCodeStr, errorCode);
257+
ERAPI_DrawText(region, 0, 16, errorCodeStr);
258+
#else
171259
ERAPI_DrawText(region, 0, 16, MSG_WAITING_GAME);
260+
#endif
172261
ERAPI_RenderFrame(1);
173262

174263
send(EREADER_CANCEL, cancel);
@@ -183,16 +272,20 @@ int main() {
183272
return ERAPI_EXIT_TO_MENU;
184273
}
185274

186-
void print(const char* text) {
275+
void print(const char* text, bool canCancel) {
187276
ERAPI_ClearRegion(region);
188277
ERAPI_DrawText(region, 0, 0, text);
189-
ERAPI_DrawText(region, 0, 16, MSG_PRESS_B_CANCEL);
278+
if (canCancel)
279+
ERAPI_DrawText(region, 0, 16, MSG_PRESS_B_CANCEL);
190280
ERAPI_RenderFrame(1);
191281
}
192282

193283
bool cancel() {
194284
u32 keys = ERAPI_GetKeyStateRaw();
195-
return (keys & ERAPI_KEY_B) != 0;
285+
bool isPressed =
286+
(previousKeys & ERAPI_KEY_B) == 0 && (keys & ERAPI_KEY_B) != 0;
287+
previousKeys = keys;
288+
return isPressed;
196289
}
197290

198291
void reset() {
1.31 KB
Binary file not shown.

examples/LinkCard_demo/src/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ int main() {
5151
u32 initialVCount = REG_VCOUNT;
5252
auto device = linkCard->getConnectedDevice([&initialVCount]() {
5353
u32 elapsed = (REG_VCOUNT - initialVCount + 228) % 228;
54-
return elapsed > 30;
54+
return elapsed > 150;
5555
});
5656

5757
switch (device) {

lib/LinkCard.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class LinkCard {
8181
static constexpr int CMD_LINKCARD_RESET = 0;
8282
static constexpr int MODE_SWITCH_WAIT = 228;
8383
static constexpr int DEACTIVATION_WAIT = 50;
84-
static constexpr int PRE_TRANSFER_WAIT = 2 + 1;
84+
static constexpr int PRE_TRANSFER_WAIT = 4;
8585

8686
public:
8787
enum class ConnectedDevice {

0 commit comments

Comments
 (0)