From c8e639ff8f87f5719fa81a259bdc73a157898c8d Mon Sep 17 00:00:00 2001 From: Rodrigo Alfonso Date: Sun, 29 Jan 2023 05:25:25 -0300 Subject: [PATCH] Refactoring and trying out multiple clients --- examples/LinkWireless_demo/src/main.cpp | 312 +++++++++++++----------- lib/LinkWireless.h | 71 +++--- 2 files changed, 219 insertions(+), 164 deletions(-) diff --git a/examples/LinkWireless_demo/src/main.cpp b/examples/LinkWireless_demo/src/main.cpp index 67a9c83..9f56754 100644 --- a/examples/LinkWireless_demo/src/main.cpp +++ b/examples/LinkWireless_demo/src/main.cpp @@ -4,7 +4,14 @@ // (0) Include the header #include "../../_lib/LinkWireless.h" +void activate(); +void host(); +void connect(); +void messageLoop(bool acceptNewClients); void log(std::string text); +void waitFor(u16 key); +void vBlankWait(); +void hang(); // (1) Create a LinkWireless instance LinkWireless* linkWireless = new LinkWireless(); @@ -14,9 +21,6 @@ void init() { REG_DISPCNT = DCNT_MODE0 | DCNT_BG0; tte_init_se_default(0, BG_CBB(0) | BG_SBB(31)); - - // (2) Initialize the library - // linkWireless->activate(); // TODO: RECOVER } int main() { @@ -27,164 +31,200 @@ int main() { bool connecting = false; while (true) { - // std::string output = ""; u16 keys = ~REG_KEYS & KEY_ANY; - if ((keys & KEY_START) && !activating) { - log("Trying..."); - activating = true; - if (linkWireless->activate()) - log("Activated! :)"); - else - log("Activation failed! :("); - } + log("START = Activate\nL = Host\nR = Connect"); + // START = Activate + if ((keys & KEY_START) && !activating) { + activating = true; + activate(); + } if (activating && !(keys & KEY_START)) activating = false; + // L = Host if ((keys & KEY_L) && !hosting) { - log("Hosting..."); hosting = true; - if (linkWireless->host(std::vector{0x0c020002, 0x00005ce1, - 0x00000000, 0x09000040, - 0xc1cfc8cd, 0x00ffccbb})) { - log("Hosting ok. Listening..."); - u16 newId = 0; - do { - newId = linkWireless->getNewConnectionId(); - log("Hosting ok. " + std::to_string(newId) + " Listening... "); - } while (newId == 0 || newId == 1); - log("CONNECTED! " + std::to_string(newId)); - - u32 i = 50; - bool sending = false; - - // TODO: DEDUP - while (true) { - keys = ~REG_KEYS & KEY_ANY; - - if (!sending && (keys & KEY_A)) { - sending = true; - linkWireless->sendData(std::vector{i}); - i++; - } - - if (sending && !(keys & KEY_A)) - sending = false; - - std::vector receivedData = std::vector{}; - if (!linkWireless->receiveData(receivedData)) { - log("ERROR RECEIVING!"); - while (true) - ; - } - if (receivedData.size() > 0) - log("RECEIVED: " + std::to_string(receivedData[0])); - - while (REG_VCOUNT >= 160) - ; // wait till VDraw - while (REG_VCOUNT < 160) - ; // wait till VBlank - } - } else { - log("Hosting error"); - while (true) - ; - } + host(); } - if (hosting && !(keys & KEY_L)) hosting = false; + // R = Connect if (!connecting && (keys & KEY_R)) { - log("Searching..."); connecting = true; - std::vector data; - if (linkWireless->getBroadcasts(data)) { - std::string str = - "Press select to conn " + std::to_string(data.size()) + "\n"; - for (u32& dat : data) - str += std::to_string(dat) + "\n"; - log(str); - - if (data.size() > 0) { - do { - keys = ~REG_KEYS & KEY_ANY; - } while (!(keys & KEY_SELECT)); - - if (!linkWireless->connect((u16)data[0])) { - log("CONNECT FAILED!"); - while (true) - ; - } - - u16 idid = 0; - do { - idid = linkWireless->isFinishedConnect(); - } while (idid <= 1); - - log("HAVE ID! PRESS SEL! " + std::to_string(idid)); - - do { - keys = ~REG_KEYS & KEY_ANY; - } while (!(keys & KEY_SELECT)); - - u16 asd = linkWireless->finishConnection(); - if (asd == 0) { - log("FINISH CONNECT FAILED!"); - while (true) - ; - } - - u32 i = 50; - bool sending = false; - log("CONNECTED! " + std::to_string(asd)); - // TODO: DEDUP - while (true) { - keys = ~REG_KEYS & KEY_ANY; - - if (!sending && (keys & KEY_A)) { - sending = true; - linkWireless->sendData(std::vector{i}); - i++; - } - - if (sending && !(keys & KEY_A)) - sending = false; - - std::vector receivedData = std::vector{}; - if (!linkWireless->receiveData(receivedData)) { - log("ERROR RECEIVING!"); - while (true) - ; - } - if (receivedData.size() > 0) - log("RECEIVED: " + std::to_string(receivedData[0])); - - while (REG_VCOUNT >= 160) - ; // wait till VDraw - while (REG_VCOUNT < 160) - ; // wait till VBlank - } - } - } else - log("Search failed :("); + connect(); } - if (connecting && !(keys & KEY_R)) connecting = false; - while (REG_VCOUNT >= 160) - ; // wait till VDraw - while (REG_VCOUNT < 160) - ; // wait till VBlank + vBlankWait(); } return 0; } +void activate() { + log("Trying..."); + + if (linkWireless->activate()) + log("Activated!"); + else + log("Activation failed! :("); + + hang(); +} + +void host() { + log("Hosting..."); + + if (!linkWireless->host(std::vector{0x0c020002, 0x00005ce1, 0x00000000, + 0x09000040, 0xc1cfc8cd, + 0x00ffccbb})) { + log("Hosting failed :("); + hang(); + return; + } + + log("Listening..."); + + LinkWireless::ClientIdResponses response; + do { + response = linkWireless->acceptConnection(); + if (!response.success) { + log("Accept failed :("); + hang(); + return; + } + } while (response.clientIds[0] == 0); + + log("Connected! " + std::to_string(response.clientIds[0])); + + messageLoop(true); +} + +void connect() { + log("Searching..."); + + std::vector broadcastData; + if (!linkWireless->getBroadcasts(broadcastData)) { + log("Search failed :("); + hang(); + return; + } + + std::string str = "Press SELECT to connect\n"; + for (u32& number : broadcastData) + str += std::to_string(number) + "\n"; + log(str); + + if (broadcastData.size() == 0) { + log("Nothing found :("); + hang(); + return; + } + + waitFor(KEY_SELECT); + + if (!linkWireless->connect((u16)broadcastData[0])) { + log("Connect failed :("); + hang(); + return; + } + + LinkWireless::ClientIdResponse response1; + do { + response1 = linkWireless->checkConnection(); + if (!response1.success) { + log("Check connection failed :("); + hang(); + return; + } + + log("Checking: " + std::to_string(response1.clientId)); + } while (response1.clientId == 0); + + log("Assigned id (press SELECT):\n" + std::to_string(response1.clientId)); + + waitFor(KEY_SELECT); + + auto response2 = linkWireless->finishConnection(); + if (!response2.success) { + log("Finish connection failed :("); + hang(); + return; + } + if (response2.clientId != response1.clientId) { + log("Assigned IDs don't match :("); + hang(); + return; + } + + log("Connected! " + std::to_string(response2.clientId)); + + messageLoop(false); +} + +void messageLoop(bool acceptNewClients) { + u32 i = 50; + bool sending = false; + + while (true) { + u16 keys = ~REG_KEYS & KEY_ANY; + + if (!sending && (keys & KEY_A)) { + sending = true; + linkWireless->sendData(std::vector{1, i}); + i++; + } + if (sending && !(keys & KEY_A)) + sending = false; + + if (acceptNewClients) { + auto newConnection = linkWireless->acceptConnection(); + if (!newConnection.success) { + log("Accept failed :("); + hang(); + return; + } + if (newConnection.clientIds.size() > 1) + log("New connection: " + std::to_string(newConnection.clientIds[1])); + } + + std::vector receivedData = std::vector{}; + if (!linkWireless->receiveData(receivedData)) { + log("Receive failed :("); + hang(); + return; + } + if (receivedData.size() > 1) + log("<<< " + std::to_string(receivedData[1])); + + vBlankWait(); + } +} + void log(std::string text) { tte_erase_screen(); tte_write("#{P:0,0}"); tte_write(text.c_str()); +} + +void waitFor(u16 key) { + u16 keys; + do { + keys = ~REG_KEYS & KEY_ANY; + } while (!(keys & key)); +} + +void vBlankWait() { + while (REG_VCOUNT >= 160) + ; // wait till VDraw + while (REG_VCOUNT < 160) + ; // wait till VBlank +} + +void hang() { + waitFor(KEY_DOWN); } \ No newline at end of file diff --git a/lib/LinkWireless.h b/lib/LinkWireless.h index 02f3e4a..9cfd415 100644 --- a/lib/LinkWireless.h +++ b/lib/LinkWireless.h @@ -30,10 +30,9 @@ #include "LinkGPIO.h" #include "LinkSPI.h" -// TODO: AVOID response.responses, use result - #define LINK_WIRELESS_PING_WAIT 50 #define LINK_WIRELESS_TRANSFER_WAIT 15 +#define LINK_WIRELESS_BROADCAST_SEARCH_WAIT ((160 + 68) * 60) #define LINK_WIRELESS_TIMEOUT 100 #define LINK_WIRELESS_LOGIN_STEPS 9 #define LINK_WIRELESS_BROADCAST_SIZE 6 @@ -59,6 +58,14 @@ const u16 LINK_WIRELESS_LOGIN_PARTS[] = {0x494e, 0x494e, 0x544e, 0x544e, 0x4e45, class LinkWireless { public: + struct ClientIdResponse { + bool success = false; + u16 clientId = 0; + }; + struct ClientIdResponses { + bool success = false; + std::vector clientIds = std::vector{0}; // TODO: IMPROVE + }; std::function debug; // TODO: REMOVE bool isActive() { return isEnabled; } @@ -87,13 +94,18 @@ class LinkWireless { sendCommand(LINK_WIRELESS_COMMAND_START_HOST).success; } - u16 getNewConnectionId() { - auto response = sendCommand(0x1a); - if (!response.success) - return 0; // TODO: PROPER RETURN TYPE + ClientIdResponses acceptConnection() { + auto result = sendCommand(LINK_WIRELESS_COMMAND_IS_CONNECT_ATTEMPT); - return response.responses.size() > 0 ? (u16)response.responses[0] - : 1; // TODO: FIGURE OUT MULTIPLE IDS + ClientIdResponses response; + if (!result.success) + return response; + response.success = true; + if (result.responses.size() == 0) + return response; + response.clientIds = result.responses; + + return response; } bool connect(u16 remoteId) { @@ -102,26 +114,35 @@ class LinkWireless { .success; } - u16 isFinishedConnect() { - auto response = sendCommand(LINK_WIRELESS_COMMAND_IS_FINISHED_CONNECT); - if (!response.success || response.responses.size() == 0) - return 0; // TODO: PROPER RETURN TYPE + ClientIdResponse checkConnection() { + auto result = sendCommand(LINK_WIRELESS_COMMAND_IS_FINISHED_CONNECT); - if (msB32(response.responses[0]) > 0) - return 1; + ClientIdResponse response; + if (!result.success) + return response; + response.success = true; + if (result.responses.size() == 0 || msB32(result.responses[0]) > 0) + return response; + response.clientId = (u16)result.responses[0]; - return (u16)response.responses[0]; + return response; } - u16 finishConnection() { - auto response = sendCommand(LINK_WIRELESS_COMMAND_FINISH_CONNECTION); - if (!response.success || response.responses.size() == 0) - return 0; // TODO: PROPER RETURN TYPE + ClientIdResponse finishConnection() { + auto result = sendCommand(LINK_WIRELESS_COMMAND_FINISH_CONNECTION); - return (u16)response.responses[0]; + ClientIdResponse response; + if (!result.success) + return response; + response.success = true; + if (result.responses.size() == 0) + return response; + response.clientId = (u16)result.responses[0]; + + return response; } - // TODO: 0 IS NOT A VALID VALUE + // TODO: CHECK RANGES bool sendData(std::vector data) { return sendCommand(LINK_WIRELESS_COMMAND_SEND_DATA, data).success; } @@ -142,19 +163,13 @@ class LinkWireless { if (!sendCommand(LINK_WIRELESS_COMMAND_BROADCAST_READ_START).success) return false; - wait(228 * 60); // TODO: NEEDED INDEED! + wait(LINK_WIRELESS_BROADCAST_SEARCH_WAIT); auto result = sendCommand(LINK_WIRELESS_COMMAND_BROADCAST_READ_END); data = result.responses; return result.success; } - // bool read(std::vector& data) { - // auto result = sendCommand(LINK_WIRELESS_COMMAND_BROADCAST_READ); - // data = result.responses; - // return result.success; - // } - ~LinkWireless() { delete linkSPI; delete linkGPIO;