diff --git a/README.md b/README.md index 6e8a80d..8f37432 100644 --- a/README.md +++ b/README.md @@ -171,7 +171,7 @@ You can update these values at any time without creating a new instance: You can also change these compile-time constants: - `LINK_WIRELESS_QUEUE_SIZE`: to set a custom buffer size (how many incoming and outgoing messages the queues can store at max). The default value is `30`, which seems fine for most games. - `LINK_WIRELESS_MAX_SERVER_TRANSFER_LENGTH` and `LINK_WIRELESS_MAX_CLIENT_TRANSFER_LENGTH`: to set the biggest allowed transfer per timer tick. Transfers contain retransmission headers and multiple user messages. These values must be in the range `[6;20]` for servers and `[2;4]` for clients. The default values are `20` and `4`, but you might want to set them a bit lower to reduce CPU usage. -- `LINK_WIRELESS_PUT_ISR_IN_IWRAM`: to put critical functions (~3.5KB) in IWRAM, which can significantly improve performance due to its faster access. This is disabled by default to conserve IWRAM space, which is limited, but it's enabled in demos to showcase its performance benefits. +- `LINK_WIRELESS_PUT_ISR_IN_IWRAM`: to put critical functions in IWRAM, which can significantly improve performance due to its faster access. This is disabled by default to conserve IWRAM space, which is limited, but it's enabled in demos to showcase its performance benefits. - If you enable this, make sure that `LinkWireless.cpp` gets compiled! For example, in a Makefile-based project, verify that the file is in your `SRCDIRS` list. - `LINK_WIRELESS_USE_SEND_RECEIVE_LATCH`: to alternate between sends and receives on each timer tick (instead of doing both things). This is disabled by default. Enabling it will introduce some latency but reduce overall CPU usage. diff --git a/examples/LinkWireless_demo/src/main.cpp b/examples/LinkWireless_demo/src/main.cpp index 275d5c5..3971e44 100644 --- a/examples/LinkWireless_demo/src/main.cpp +++ b/examples/LinkWireless_demo/src/main.cpp @@ -1,12 +1,12 @@ +// (0) Include the header +#include "../../../lib/LinkWireless.hpp" + #include #include #include #include #include "../../_lib/interrupt.h" -// (0) Include the header -#include "../../../lib/LinkWireless.hpp" - #ifdef PROFILING_ENABLED #include #endif diff --git a/lib/LinkCable.hpp b/lib/LinkCable.hpp index 8e65d73..2329df2 100644 --- a/lib/LinkCable.hpp +++ b/lib/LinkCable.hpp @@ -77,7 +77,7 @@ class LinkCable { using vs32 = volatile signed int; using vu32 = volatile unsigned int; - static constexpr int BASE_FREQUENCY = Link::_TM_FREQ_1024; + static constexpr auto BASE_FREQUENCY = Link::_TM_FREQ_1024; static constexpr int REMOTE_TIMEOUT_OFFLINE = -1; static constexpr int BIT_SLAVE = 2; static constexpr int BIT_READY = 3; diff --git a/lib/LinkWireless.hpp b/lib/LinkWireless.hpp index fc3351b..abfc759 100644 --- a/lib/LinkWireless.hpp +++ b/lib/LinkWireless.hpp @@ -54,8 +54,8 @@ // - 0xFFFF is a reserved value, so don't use it! // -------------------------------------------------------------------------- -#include -#include +#include "_link_common.hpp" + #include #include "LinkGPIO.hpp" #include "LinkSPI.hpp" @@ -78,55 +78,24 @@ // Use send/receive latch (uncomment to enable) // #define LINK_WIRELESS_USE_SEND_RECEIVE_LATCH +static volatile char LINK_WIRELESS_VERSION[] = "LinkWireless/v7.0.0"; + #define LINK_WIRELESS_MAX_PLAYERS 5 #define LINK_WIRELESS_MIN_PLAYERS 2 +#define LINK_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH 22 +#define LINK_WIRELESS_MAX_COMMAND_RESPONSE_LENGTH 30 +#define LINK_WIRELESS_BROADCAST_LENGTH 6 +#define LINK_WIRELESS_BROADCAST_RESPONSE_LENGTH \ + (1 + LINK_WIRELESS_BROADCAST_LENGTH) +#define LINK_WIRELESS_MAX_SERVERS \ + (LINK_WIRELESS_MAX_COMMAND_RESPONSE_LENGTH / \ + LINK_WIRELESS_BROADCAST_RESPONSE_LENGTH) #define LINK_WIRELESS_END 0 #define LINK_WIRELESS_DEFAULT_TIMEOUT 10 #define LINK_WIRELESS_DEFAULT_REMOTE_TIMEOUT 10 #define LINK_WIRELESS_DEFAULT_INTERVAL 50 #define LINK_WIRELESS_DEFAULT_SEND_TIMER_ID 3 #define LINK_WIRELESS_DEFAULT_ASYNC_ACK_TIMER_ID -1 -#define LINK_WIRELESS_BASE_FREQUENCY TM_FREQ_1024 -#define LINK_WIRELESS_PACKET_ID_BITS 6 -#define LINK_WIRELESS_MAX_PACKET_IDS (1 << LINK_WIRELESS_PACKET_ID_BITS) -#define LINK_WIRELESS_PACKET_ID_MASK (LINK_WIRELESS_MAX_PACKET_IDS - 1) -#define LINK_WIRELESS_MSG_PING 0xffff -#define LINK_WIRELESS_PING_WAIT 50 -#define LINK_WIRELESS_TRANSFER_WAIT 15 -#define LINK_WIRELESS_BROADCAST_SEARCH_WAIT_FRAMES 60 -#define LINK_WIRELESS_CMD_TIMEOUT 100 -#define LINK_WIRELESS_MAX_COMMAND_RESPONSE_LENGTH 30 -#define LINK_WIRELESS_MAX_GAME_ID 0x7fff -#define LINK_WIRELESS_MAX_GAME_NAME_LENGTH 14 -#define LINK_WIRELESS_MAX_USER_NAME_LENGTH 8 -#define LINK_WIRELESS_LOGIN_STEPS 9 -#define LINK_WIRELESS_COMMAND_HEADER 0x9966 -#define LINK_WIRELESS_RESPONSE_ACK 0x80 -#define LINK_WIRELESS_DATA_REQUEST 0x80000000 -#define LINK_WIRELESS_SETUP_MAGIC 0x003c0420 -#define LINK_WIRELESS_SETUP_MAX_PLAYERS_BIT 16 -#define LINK_WIRELESS_STILL_CONNECTING 0x01000000 -#define LINK_WIRELESS_BROADCAST_LENGTH 6 -#define LINK_WIRELESS_BROADCAST_RESPONSE_LENGTH \ - (1 + LINK_WIRELESS_BROADCAST_LENGTH) -#define LINK_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH 22 -#define LINK_WIRELESS_MAX_SERVERS \ - (LINK_WIRELESS_MAX_COMMAND_RESPONSE_LENGTH / \ - LINK_WIRELESS_BROADCAST_RESPONSE_LENGTH) -#define LINK_WIRELESS_COMMAND_HELLO 0x10 -#define LINK_WIRELESS_COMMAND_SETUP 0x17 -#define LINK_WIRELESS_COMMAND_BROADCAST 0x16 -#define LINK_WIRELESS_COMMAND_START_HOST 0x19 -#define LINK_WIRELESS_COMMAND_ACCEPT_CONNECTIONS 0x1a -#define LINK_WIRELESS_COMMAND_BROADCAST_READ_START 0x1c -#define LINK_WIRELESS_COMMAND_BROADCAST_READ_POLL 0x1d -#define LINK_WIRELESS_COMMAND_BROADCAST_READ_END 0x1e -#define LINK_WIRELESS_COMMAND_CONNECT 0x1f -#define LINK_WIRELESS_COMMAND_IS_FINISHED_CONNECT 0x20 -#define LINK_WIRELESS_COMMAND_FINISH_CONNECTION 0x21 -#define LINK_WIRELESS_COMMAND_SEND_DATA 0x24 -#define LINK_WIRELESS_COMMAND_RECEIVE_DATA 0x26 -#define LINK_WIRELESS_COMMAND_BYE 0x3d #define LINK_WIRELESS_BARRIER asm volatile("" ::: "memory") #define LINK_WIRELESS_CODE_IWRAM \ __attribute__((section(".iwram"), target("arm"), noinline)) @@ -139,17 +108,51 @@ if (!reset()) \ return false; -static volatile char LINK_WIRELESS_VERSION[] = "LinkWireless/v7.0.0"; - -void LINK_WIRELESS_ISR_VBLANK(); -void LINK_WIRELESS_ISR_SERIAL(); -void LINK_WIRELESS_ISR_TIMER(); -const u16 LINK_WIRELESS_LOGIN_PARTS[] = {0x494e, 0x494e, 0x544e, 0x544e, 0x4e45, - 0x4e45, 0x4f44, 0x4f44, 0x8001}; -const u16 LINK_WIRELESS_TIMER_IRQ_IDS[] = {IRQ_TIMER0, IRQ_TIMER1, IRQ_TIMER2, - IRQ_TIMER3}; - class LinkWireless { + private: + using u32 = unsigned int; + using u16 = unsigned short; + using u8 = unsigned char; + using vs32 = volatile signed int; + using vu32 = volatile unsigned int; + using s8 = signed char; + + static constexpr auto BASE_FREQUENCY = Link::_TM_FREQ_1024; + static constexpr int PACKET_ID_BITS = 6; + static constexpr int MAX_PACKET_IDS = (1 << PACKET_ID_BITS); + static constexpr int PACKET_ID_MASK = (MAX_PACKET_IDS - 1); + static constexpr int MSG_PING = 0xffff; + static constexpr int PING_WAIT = 50; + static constexpr int TRANSFER_WAIT = 15; + static constexpr int BROADCAST_SEARCH_WAIT_FRAMES = 60; + static constexpr int CMD_TIMEOUT = 100; + static constexpr int MAX_GAME_ID = 0x7fff; + static constexpr int MAX_GAME_NAME_LENGTH = 14; + static constexpr int MAX_USER_NAME_LENGTH = 8; + static constexpr int LOGIN_STEPS = 9; + static constexpr int COMMAND_HEADER_VALUE = 0x9966; + static constexpr int RESPONSE_ACK_VALUE = 0x80; + static constexpr u32 DATA_REQUEST_VALUE = 0x80000000; + static constexpr int SETUP_MAGIC = 0x003c0420; + static constexpr int SETUP_MAX_PLAYERS_BIT = 16; + static constexpr int WAIT_STILL_CONNECTING = 0x01000000; + static constexpr int COMMAND_HELLO = 0x10; + static constexpr int COMMAND_SETUP = 0x17; + static constexpr int COMMAND_BROADCAST = 0x16; + static constexpr int COMMAND_START_HOST = 0x19; + static constexpr int COMMAND_ACCEPT_CONNECTIONS = 0x1a; + static constexpr int COMMAND_BROADCAST_READ_START = 0x1c; + static constexpr int COMMAND_BROADCAST_READ_POLL = 0x1d; + static constexpr int COMMAND_BROADCAST_READ_END = 0x1e; + static constexpr int COMMAND_CONNECT = 0x1f; + static constexpr int COMMAND_IS_FINISHED_CONNECT = 0x20; + static constexpr int COMMAND_FINISH_CONNECTION = 0x21; + static constexpr int COMMAND_SEND_DATA = 0x24; + static constexpr int COMMAND_RECEIVE_DATA = 0x26; + static constexpr int COMMAND_BYE = 0x3d; + static constexpr u16 LOGIN_PARTS[] = {0x494e, 0x494e, 0x544e, 0x544e, 0x4e45, + 0x4e45, 0x4f44, 0x4f44, 0x8001}; + public: // std::function debug; // #define PROFILING_ENABLED @@ -203,8 +206,8 @@ class LinkWireless { struct Server { u16 id = 0; u16 gameId; - char gameName[LINK_WIRELESS_MAX_GAME_NAME_LENGTH + 1]; - char userName[LINK_WIRELESS_MAX_USER_NAME_LENGTH + 1]; + char gameName[MAX_GAME_NAME_LENGTH + 1]; + char userName[MAX_USER_NAME_LENGTH + 1]; u8 currentPlayerCount; bool isFull() { return currentPlayerCount == 0; } @@ -229,7 +232,7 @@ class LinkWireless { this->config.asyncACKTimerId = asyncACKTimerId; } - bool isActive() { return isEnabled; } + [[nodiscard]] bool isActive() { return isEnabled; } bool activate() { lastError = NONE; @@ -245,7 +248,7 @@ class LinkWireless { bool deactivate() { activate(); - bool success = sendCommand(LINK_WIRELESS_COMMAND_BYE).success; + bool success = sendCommand(COMMAND_BYE).success; lastError = NONE; isEnabled = false; @@ -257,7 +260,7 @@ class LinkWireless { bool serve(const char* gameName = "", const char* userName = "", - u16 gameId = LINK_WIRELESS_MAX_GAME_ID) { + u16 gameId = MAX_GAME_ID) { LINK_WIRELESS_RESET_IF_NEEDED if (state != AUTHENTICATED && state != SERVING) { lastError = WRONG_STATE; @@ -267,25 +270,25 @@ class LinkWireless { lastError = BUSY_TRY_AGAIN; return false; } - if (std::strlen(gameName) > LINK_WIRELESS_MAX_GAME_NAME_LENGTH) { + if (std::strlen(gameName) > MAX_GAME_NAME_LENGTH) { lastError = GAME_NAME_TOO_LONG; return false; } - if (std::strlen(userName) > LINK_WIRELESS_MAX_GAME_NAME_LENGTH) { + if (std::strlen(userName) > MAX_GAME_NAME_LENGTH) { lastError = USER_NAME_TOO_LONG; return false; } - char finalGameName[LINK_WIRELESS_MAX_GAME_NAME_LENGTH + 1]; - char finalUserName[LINK_WIRELESS_MAX_USER_NAME_LENGTH + 1]; - copyName(finalGameName, gameName, LINK_WIRELESS_MAX_GAME_NAME_LENGTH); - copyName(finalUserName, userName, LINK_WIRELESS_MAX_USER_NAME_LENGTH); + char finalGameName[MAX_GAME_NAME_LENGTH + 1]; + char finalUserName[MAX_USER_NAME_LENGTH + 1]; + copyName(finalGameName, gameName, MAX_GAME_NAME_LENGTH); + copyName(finalUserName, userName, MAX_USER_NAME_LENGTH); if (state != SERVING) setup(config.maxPlayers); addData(buildU32(buildU16(finalGameName[1], finalGameName[0]), - gameId & LINK_WIRELESS_MAX_GAME_ID), + gameId & MAX_GAME_ID), true); addData(buildU32(buildU16(finalGameName[5], finalGameName[4]), buildU16(finalGameName[3], finalGameName[2]))); @@ -298,11 +301,10 @@ class LinkWireless { addData(buildU32(buildU16(finalUserName[7], finalUserName[6]), buildU16(finalUserName[5], finalUserName[4]))); - bool success = sendCommand(LINK_WIRELESS_COMMAND_BROADCAST, true).success; + bool success = sendCommand(COMMAND_BROADCAST, true).success; if (state != SERVING) { - success = - success && sendCommand(LINK_WIRELESS_COMMAND_START_HOST).success; + success = success && sendCommand(COMMAND_START_HOST).success; } if (!success) { @@ -311,7 +313,7 @@ class LinkWireless { return false; } - wait(LINK_WIRELESS_TRANSFER_WAIT); + wait(TRANSFER_WAIT); state = SERVING; return true; @@ -326,7 +328,7 @@ class LinkWireless { if (!getServersAsyncStart()) return false; - waitVBlanks(LINK_WIRELESS_BROADCAST_SEARCH_WAIT_FRAMES, onWait); + waitVBlanks(BROADCAST_SEARCH_WAIT_FRAMES, onWait); if (!getServersAsyncEnd(servers)) return false; @@ -341,8 +343,7 @@ class LinkWireless { return false; } - bool success = - sendCommand(LINK_WIRELESS_COMMAND_BROADCAST_READ_START).success; + bool success = sendCommand(COMMAND_BROADCAST_READ_START).success; if (!success) { reset(); @@ -362,7 +363,7 @@ class LinkWireless { return false; } - auto result = sendCommand(LINK_WIRELESS_COMMAND_BROADCAST_READ_POLL); + auto result = sendCommand(COMMAND_BROADCAST_READ_POLL); bool success1 = result.success && result.responsesSize % LINK_WIRELESS_BROADCAST_RESPONSE_LENGTH == 0; @@ -373,8 +374,7 @@ class LinkWireless { return false; } - bool success2 = - sendCommand(LINK_WIRELESS_COMMAND_BROADCAST_READ_END).success; + bool success2 = sendCommand(COMMAND_BROADCAST_READ_END).success; if (!success2) { reset(); @@ -390,7 +390,7 @@ class LinkWireless { Server server; server.id = (u16)result.responses[start]; - server.gameId = result.responses[start + 1] & LINK_WIRELESS_MAX_GAME_ID; + server.gameId = result.responses[start + 1] & MAX_GAME_ID; u32 gameI = 0, userI = 0; recoverName(server.gameName, gameI, result.responses[start + 1], false); recoverName(server.gameName, gameI, result.responses[start + 2]); @@ -420,7 +420,7 @@ class LinkWireless { } addData(serverId, true); - bool success = sendCommand(LINK_WIRELESS_COMMAND_CONNECT, true).success; + bool success = sendCommand(COMMAND_CONNECT, true).success; if (!success) { reset(); @@ -440,14 +440,14 @@ class LinkWireless { return false; } - auto result1 = sendCommand(LINK_WIRELESS_COMMAND_IS_FINISHED_CONNECT); + auto result1 = sendCommand(COMMAND_IS_FINISHED_CONNECT); if (!result1.success || result1.responsesSize == 0) { reset(); lastError = COMMAND_FAILED; return false; } - if (result1.responses[0] == LINK_WIRELESS_STILL_CONNECTING) + if (result1.responses[0] == WAIT_STILL_CONNECTING) return true; u8 assignedPlayerId = 1 + (u8)msB32(result1.responses[0]); @@ -457,7 +457,7 @@ class LinkWireless { return false; } - auto result2 = sendCommand(LINK_WIRELESS_COMMAND_FINISH_CONNECTION); + auto result2 = sendCommand(COMMAND_FINISH_CONNECTION); if (!result2.success) { reset(); lastError = COMMAND_FAILED; @@ -528,12 +528,14 @@ class LinkWireless { return true; } - State getState() { return state; } - bool isConnected() { return sessionState.playerCount > 1; } - bool isSessionActive() { return state == SERVING || state == CONNECTED; } - u8 playerCount() { return sessionState.playerCount; } - u8 currentPlayerId() { return sessionState.currentPlayerId; } - Error getLastError(bool clear = true) { + [[nodiscard]] State getState() { return state; } + [[nodiscard]] bool isConnected() { return sessionState.playerCount > 1; } + [[nodiscard]] bool isSessionActive() { + return state == SERVING || state == CONNECTED; + } + [[nodiscard]] u8 playerCount() { return sessionState.playerCount; } + [[nodiscard]] u8 currentPlayerId() { return sessionState.currentPlayerId; } + [[nodiscard]] Error getLastError(bool clear = true) { Error error = lastError; if (clear) lastError = NONE; @@ -545,21 +547,27 @@ class LinkWireless { delete linkGPIO; } - bool _hasActiveAsyncCommand() { return asyncCommand.isActive; } - bool _canSend() { return !sessionState.outgoingMessages.isFull(); } - u32 _getPendingCount() { return sessionState.outgoingMessages.size(); } - u32 _lastPacketId() { return sessionState.lastPacketId; } - u32 _lastConfirmationFromClient1() { + [[nodiscard]] bool _hasActiveAsyncCommand() { return asyncCommand.isActive; } + [[nodiscard]] bool _canSend() { + return !sessionState.outgoingMessages.isFull(); + } + [[nodiscard]] u32 _getPendingCount() { + return sessionState.outgoingMessages.size(); + } + [[nodiscard]] u32 _lastPacketId() { return sessionState.lastPacketId; } + [[nodiscard]] u32 _lastConfirmationFromClient1() { return sessionState.lastConfirmationFromClients[1]; } - u32 _lastPacketIdFromClient1() { + [[nodiscard]] u32 _lastPacketIdFromClient1() { return sessionState.lastPacketIdFromClients[1]; } - u32 _lastConfirmationFromServer() { + [[nodiscard]] u32 _lastConfirmationFromServer() { return sessionState.lastConfirmationFromServer; } - u32 _lastPacketIdFromServer() { return sessionState.lastPacketIdFromServer; } - u32 _nextPendingPacketId() { + [[nodiscard]] u32 _lastPacketIdFromServer() { + return sessionState.lastPacketIdFromServer; + } + [[nodiscard]] u32 _nextPendingPacketId() { return sessionState.outgoingMessages.isEmpty() ? 0 : sessionState.outgoingMessages.peek().packetId; @@ -824,7 +832,7 @@ class LinkWireless { }; struct MessageHeader { - unsigned int partialPacketId : LINK_WIRELESS_PACKET_ID_BITS; + unsigned int partialPacketId : PACKET_ID_BITS; unsigned int isConfirmation : 1; unsigned int playerId : 3; unsigned int clientCount : 2; @@ -893,9 +901,9 @@ class LinkWireless { void processAsyncCommand() { // (irq only) if (!asyncCommand.result.success) { - if (asyncCommand.type == LINK_WIRELESS_COMMAND_SEND_DATA) + if (asyncCommand.type == COMMAND_SEND_DATA) lastError = SEND_DATA_FAILED; - else if (asyncCommand.type == LINK_WIRELESS_COMMAND_RECEIVE_DATA) + else if (asyncCommand.type == COMMAND_RECEIVE_DATA) lastError = RECEIVE_DATA_FAILED; else lastError = COMMAND_FAILED; @@ -907,14 +915,14 @@ class LinkWireless { asyncCommand.isActive = false; switch (asyncCommand.type) { - case LINK_WIRELESS_COMMAND_ACCEPT_CONNECTIONS: { + case COMMAND_ACCEPT_CONNECTIONS: { // AcceptConnections (end) - sessionState.playerCount = - min(1 + asyncCommand.result.responsesSize, config.maxPlayers); + sessionState.playerCount = Link::_min( + 1 + asyncCommand.result.responsesSize, config.maxPlayers); break; } - case LINK_WIRELESS_COMMAND_SEND_DATA: { + case COMMAND_SEND_DATA: { // SendData (end) #ifdef LINK_WIRELESS_USE_SEND_RECEIVE_LATCH @@ -925,13 +933,13 @@ class LinkWireless { #ifndef LINK_WIRELESS_USE_SEND_RECEIVE_LATCH if (state == SERVING) { // ReceiveData (start) - sendCommandAsync(LINK_WIRELESS_COMMAND_RECEIVE_DATA); + sendCommandAsync(COMMAND_RECEIVE_DATA); } #endif break; } - case LINK_WIRELESS_COMMAND_RECEIVE_DATA: { + case COMMAND_RECEIVE_DATA: { // ReceiveData (end) #ifdef LINK_WIRELESS_USE_SEND_RECEIVE_LATCH @@ -970,7 +978,7 @@ class LinkWireless { if (state == SERVING && !sessionState.acceptCalled && sessionState.playerCount < config.maxPlayers) { // AcceptConnections (start) - if (sendCommandAsync(LINK_WIRELESS_COMMAND_ACCEPT_CONNECTIONS)) + if (sendCommandAsync(COMMAND_ACCEPT_CONNECTIONS)) sessionState.acceptCalled = true; } else if (state == CONNECTED || isConnected()) { #ifdef LINK_WIRELESS_USE_SEND_RECEIVE_LATCH @@ -983,7 +991,7 @@ class LinkWireless { if (shouldReceive) { // ReceiveData (start) - sendCommandAsync(LINK_WIRELESS_COMMAND_RECEIVE_DATA); + sendCommandAsync(COMMAND_RECEIVE_DATA); } else { // SendData (start) sendPendingData(); @@ -994,7 +1002,7 @@ class LinkWireless { void sendPendingData() { // (irq only) copyOutgoingState(); int lastPacketId = setDataFromOutgoingMessages(); - if (sendCommandAsync(LINK_WIRELESS_COMMAND_SEND_DATA, true)) + if (sendCommandAsync(COMMAND_SEND_DATA, true)) clearOutgoingMessagesIfNeeded(lastPacketId); } @@ -1047,10 +1055,10 @@ class LinkWireless { MessageHeader header = serializer.asStruct; u32 partialPacketId = header.partialPacketId; bool isConfirmation = header.isConfirmation; - u8 remotePlayerId = min(header.playerId, config.maxPlayers - 1); + u8 remotePlayerId = Link::_min(header.playerId, config.maxPlayers - 1); u8 remotePlayerCount = LINK_WIRELESS_MIN_PLAYERS + header.clientCount; u32 checksum = header.dataChecksum; - bool isPing = data == LINK_WIRELESS_MSG_PING; + bool isPing = data == MSG_PING; sessionState.timeouts[0] = 0; sessionState.timeouts[remotePlayerId] = 0; @@ -1082,7 +1090,7 @@ class LinkWireless { if (state == SERVING) { u32 expectedPacketId = (sessionState.lastPacketIdFromClients[message.playerId] + 1) % - LINK_WIRELESS_MAX_PACKET_IDS; + MAX_PACKET_IDS; if (config.retransmission && !isConfirmation && message.packetId != expectedPacketId) @@ -1092,8 +1100,8 @@ class LinkWireless { message.packetId = ++sessionState.lastPacketIdFromClients[message.playerId]; } else { - u32 expectedPacketId = (sessionState.lastPacketIdFromServer + 1) % - LINK_WIRELESS_MAX_PACKET_IDS; + u32 expectedPacketId = + (sessionState.lastPacketIdFromServer + 1) % MAX_PACKET_IDS; if (config.retransmission && !isConfirmation && message.packetId != expectedPacketId) @@ -1121,7 +1129,7 @@ class LinkWireless { Message pingMessage; pingMessage.packetId = newPacketId(); pingMessage.playerId = sessionState.currentPlayerId; - pingMessage.data = LINK_WIRELESS_MSG_PING; + pingMessage.data = MSG_PING; sessionState.outgoingMessages.push(pingMessage); sessionState.pingSent = true; } @@ -1205,7 +1213,7 @@ class LinkWireless { // confirmation messages "repurpose" some message header fields: // packetId => high 6 bits of confirmation // data => low 16 bits of confirmation - u8 highPart = (confirmationData >> 16) & LINK_WIRELESS_PACKET_ID_MASK; + u8 highPart = (confirmationData >> 16) & PACKET_ID_MASK; u16 lowPart = confirmationData & 0xffff; return buildMessageHeader(playerId, highPart, buildChecksum(lowPart), true); } @@ -1215,7 +1223,7 @@ class LinkWireless { u8 dataChecksum, bool isConfirmation = false) { // (irq only) MessageHeader header; - header.partialPacketId = packetId % LINK_WIRELESS_MAX_PACKET_IDS; + header.partialPacketId = packetId % MAX_PACKET_IDS; header.isConfirmation = isConfirmation; header.playerId = playerId; header.clientCount = sessionState.playerCount - LINK_WIRELESS_MIN_PLAYERS; @@ -1288,14 +1296,14 @@ class LinkWireless { } void startACKTimer() { - REG_TM[config.asyncACKTimerId].start = -1; - REG_TM[config.asyncACKTimerId].cnt = - TM_ENABLE | TM_IRQ | LINK_WIRELESS_BASE_FREQUENCY; + Link::_REG_TM[config.asyncACKTimerId].start = -1; + Link::_REG_TM[config.asyncACKTimerId].cnt = + Link::_TM_ENABLE | Link::_TM_IRQ | BASE_FREQUENCY; } void stopACKTimer() { - REG_TM[config.asyncACKTimerId].cnt = - REG_TM[config.asyncACKTimerId].cnt & (~TM_ENABLE); + Link::_REG_TM[config.asyncACKTimerId].cnt = + Link::_REG_TM[config.asyncACKTimerId].cnt & (~Link::_TM_ENABLE); } void copyName(char* target, const char* source, u32 length) { @@ -1389,9 +1397,9 @@ class LinkWireless { if (!login()) return false; - wait(LINK_WIRELESS_TRANSFER_WAIT); + wait(TRANSFER_WAIT); - if (!sendCommand(LINK_WIRELESS_COMMAND_HELLO).success) + if (!sendCommand(COMMAND_HELLO).success) return false; if (!setup()) @@ -1404,33 +1412,32 @@ class LinkWireless { } void stopTimer() { - REG_TM[config.sendTimerId].cnt = - REG_TM[config.sendTimerId].cnt & (~TM_ENABLE); + Link::_REG_TM[config.sendTimerId].cnt = + Link::_REG_TM[config.sendTimerId].cnt & (~Link::_TM_ENABLE); } void startTimer() { - REG_TM[config.sendTimerId].start = -config.interval; - REG_TM[config.sendTimerId].cnt = - TM_ENABLE | TM_IRQ | LINK_WIRELESS_BASE_FREQUENCY; + Link::_REG_TM[config.sendTimerId].start = -config.interval; + Link::_REG_TM[config.sendTimerId].cnt = + Link::_TM_ENABLE | Link::_TM_IRQ | BASE_FREQUENCY; } void pingAdapter() { linkGPIO->setMode(LinkGPIO::Pin::SO, LinkGPIO::Direction::OUTPUT); linkGPIO->setMode(LinkGPIO::Pin::SD, LinkGPIO::Direction::OUTPUT); linkGPIO->writePin(LinkGPIO::SD, true); - wait(LINK_WIRELESS_PING_WAIT); + wait(PING_WAIT); linkGPIO->writePin(LinkGPIO::SD, false); } bool login() { LoginMemory memory; - if (!exchangeLoginPacket(LINK_WIRELESS_LOGIN_PARTS[0], 0, memory)) + if (!exchangeLoginPacket(LOGIN_PARTS[0], 0, memory)) return false; - for (u32 i = 0; i < LINK_WIRELESS_LOGIN_STEPS; i++) { - if (!exchangeLoginPacket(LINK_WIRELESS_LOGIN_PARTS[i], - LINK_WIRELESS_LOGIN_PARTS[i], memory)) + for (u32 i = 0; i < LOGIN_STEPS; i++) { + if (!exchangeLoginPacket(LOGIN_PARTS[i], LOGIN_PARTS[i], memory)) return false; } @@ -1454,11 +1461,10 @@ class LinkWireless { } bool setup(u8 maxPlayers = LINK_WIRELESS_MAX_PLAYERS) { - addData(LINK_WIRELESS_SETUP_MAGIC | - (((LINK_WIRELESS_MAX_PLAYERS - maxPlayers) & 0b11) - << LINK_WIRELESS_SETUP_MAX_PLAYERS_BIT), + addData(SETUP_MAGIC | (((LINK_WIRELESS_MAX_PLAYERS - maxPlayers) & 0b11) + << SETUP_MAX_PLAYERS_BIT), true); - return sendCommand(LINK_WIRELESS_COMMAND_SETUP, true).success; + return sendCommand(COMMAND_SETUP, true).success; } CommandResult sendCommand(u8 type, bool withData = false) { @@ -1469,35 +1475,34 @@ class LinkWireless { isSendingSyncCommand = true; LINK_WIRELESS_BARRIER; - if (transfer(command) != LINK_WIRELESS_DATA_REQUEST) { + if (transfer(command) != DATA_REQUEST_VALUE) { isSendingSyncCommand = false; return result; } if (withData) { for (u32 i = 0; i < nextCommandDataSize; i++) { - if (transfer(nextCommandData[i]) != LINK_WIRELESS_DATA_REQUEST) { + if (transfer(nextCommandData[i]) != DATA_REQUEST_VALUE) { isSendingSyncCommand = false; return result; } } } - u32 response = transfer(LINK_WIRELESS_DATA_REQUEST); + u32 response = transfer(DATA_REQUEST_VALUE); u16 header = msB32(response); u16 data = lsB32(response); u8 responses = msB16(data); u8 ack = lsB16(data); - if (header != LINK_WIRELESS_COMMAND_HEADER || - ack != type + LINK_WIRELESS_RESPONSE_ACK || + if (header != COMMAND_HEADER_VALUE || ack != type + RESPONSE_ACK_VALUE || responses > LINK_WIRELESS_MAX_COMMAND_RESPONSE_LENGTH) { isSendingSyncCommand = false; return result; } for (u32 i = 0; i < responses; i++) - result.responses[i] = transfer(LINK_WIRELESS_DATA_REQUEST); + result.responses[i] = transfer(DATA_REQUEST_VALUE); result.responsesSize = responses; result.success = true; @@ -1538,7 +1543,7 @@ class LinkWireless { void updateAsyncCommand(u32 newData) { // (irq only) switch (asyncCommand.step) { case AsyncCommand::Step::COMMAND_HEADER: { - if (newData != LINK_WIRELESS_DATA_REQUEST) { + if (newData != DATA_REQUEST_VALUE) { asyncCommand.state = AsyncCommand::State::COMPLETED; return; } @@ -1547,7 +1552,7 @@ class LinkWireless { break; } case AsyncCommand::Step::COMMAND_PARAMETERS: { - if (newData != LINK_WIRELESS_DATA_REQUEST) { + if (newData != DATA_REQUEST_VALUE) { asyncCommand.state = AsyncCommand::State::COMPLETED; return; } @@ -1561,8 +1566,8 @@ class LinkWireless { u8 responses = msB16(data); u8 ack = lsB16(data); - if (header != LINK_WIRELESS_COMMAND_HEADER || - ack != asyncCommand.type + LINK_WIRELESS_RESPONSE_ACK || + if (header != COMMAND_HEADER_VALUE || + ack != asyncCommand.type + RESPONSE_ACK_VALUE || responses > LINK_WIRELESS_MAX_COMMAND_RESPONSE_LENGTH) { asyncCommand.state = AsyncCommand::State::COMPLETED; return; @@ -1591,14 +1596,14 @@ class LinkWireless { asyncCommand.sentParameters++; } else { asyncCommand.step = AsyncCommand::Step::RESPONSE_REQUEST; - transferAsync(LINK_WIRELESS_DATA_REQUEST); + transferAsync(DATA_REQUEST_VALUE); } } void receiveAsyncCommandResponseOrFinish() { // (irq only) if (asyncCommand.receivedResponses < asyncCommand.totalResponses) { asyncCommand.step = AsyncCommand::Step::DATA_REQUEST; - transferAsync(LINK_WIRELESS_DATA_REQUEST); + transferAsync(DATA_REQUEST_VALUE); } else { asyncCommand.result.success = true; asyncCommand.state = AsyncCommand::State::COMPLETED; @@ -1606,7 +1611,7 @@ class LinkWireless { } u32 buildCommand(u8 type, u8 length = 0) { - return buildU32(LINK_WIRELESS_COMMAND_HEADER, buildU16(length, type)); + return buildU32(COMMAND_HEADER_VALUE, buildU16(length, type)); } void transferAsync(u32 data) { @@ -1615,10 +1620,10 @@ class LinkWireless { u32 transfer(u32 data, bool customAck = true) { if (!customAck) - wait(LINK_WIRELESS_TRANSFER_WAIT); + wait(TRANSFER_WAIT); u32 lines = 0; - u32 vCount = REG_VCOUNT; + u32 vCount = Link::_REG_VCOUNT; u32 receivedData = linkSPI->transfer( data, [this, &lines, &vCount]() { return cmdTimeout(lines, vCount); }, false, customAck); @@ -1631,7 +1636,7 @@ class LinkWireless { bool acknowledge() { u32 lines = 0; - u32 vCount = REG_VCOUNT; + u32 vCount = Link::_REG_VCOUNT; linkSPI->_setSOLow(); while (!linkSPI->_isSIHigh()) @@ -1649,13 +1654,13 @@ class LinkWireless { bool usesAsyncACK() { return config.asyncACKTimerId > -1; } bool cmdTimeout(u32& lines, u32& vCount) { - return timeout(LINK_WIRELESS_CMD_TIMEOUT, lines, vCount); + return timeout(CMD_TIMEOUT, lines, vCount); } bool timeout(u32 limit, u32& lines, u32& vCount) { - if (REG_VCOUNT != vCount) { - lines += max((int)REG_VCOUNT - (int)vCount, 0); - vCount = REG_VCOUNT; + if (Link::_REG_VCOUNT != vCount) { + lines += Link::_max((int)Link::_REG_VCOUNT - (int)vCount, 0); + vCount = Link::_REG_VCOUNT; } return lines > limit; @@ -1663,12 +1668,12 @@ class LinkWireless { void wait(u32 verticalLines) { u32 count = 0; - u32 vCount = REG_VCOUNT; + u32 vCount = Link::_REG_VCOUNT; while (count < verticalLines) { - if (REG_VCOUNT != vCount) { + if (Link::_REG_VCOUNT != vCount) { count++; - vCount = REG_VCOUNT; + vCount = Link::_REG_VCOUNT; } }; } @@ -1676,11 +1681,11 @@ class LinkWireless { template void waitVBlanks(u32 vBlanks, F onVBlank) { u32 count = 0; - u32 vCount = REG_VCOUNT; + u32 vCount = Link::_REG_VCOUNT; while (count < vBlanks) { - if (REG_VCOUNT != vCount) { - vCount = REG_VCOUNT; + if (Link::_REG_VCOUNT != vCount) { + vCount = Link::_REG_VCOUNT; if (vCount == 160) { onVBlank(); @@ -1699,21 +1704,21 @@ class LinkWireless { #ifdef PROFILING_ENABLED void profileStart() { - REG_TM1CNT_L = 0; - REG_TM2CNT_L = 0; + Link::_REG_TM1CNT_L = 0; + Link::_REG_TM2CNT_L = 0; - REG_TM1CNT_H = 0; - REG_TM2CNT_H = 0; + Link::_REG_TM1CNT_H = 0; + Link::_REG_TM2CNT_H = 0; - REG_TM2CNT_H = TM_ENABLE | TM_CASCADE; - REG_TM1CNT_H = TM_ENABLE | TM_FREQ_1; + Link::_REG_TM2CNT_H = Link::_TM_ENABLE | Link::_TM_CASCADE; + Link::_REG_TM1CNT_H = Link::_TM_ENABLE | Link::_TM_FREQ_1; } u32 profileStop() { - REG_TM1CNT_H = 0; - REG_TM2CNT_H = 0; + Link::_REG_TM1CNT_H = 0; + Link::_REG_TM2CNT_H = 0; - return (REG_TM1CNT_L | (REG_TM2CNT_L << 16)); + return (Link::_REG_TM1CNT_L | (Link::_REG_TM2CNT_L << 16)); } public: diff --git a/lib/_link_common.hpp b/lib/_link_common.hpp index e22b0a2..680b745 100644 --- a/lib/_link_common.hpp +++ b/lib/_link_common.hpp @@ -15,6 +15,7 @@ using u8 = unsigned char; using vs32 = volatile signed int; using vu32 = volatile unsigned int; using s16 = signed short; +using s8 = signed char; // Structs