diff --git a/README.md b/README.md index df165bb..06998fd 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ Name | Return type | Description `deactivate()` | - | Deactivates the library. `isConnected()` | **bool** | Returns `true` if there are at least 2 connected players. `playerCount()` | **u8** *(0~4)* | Returns the number of connected players. -`currentPlayerId()` | **u8** *(0~3)* | Returns the current player id. +`currentPlayerId()` | **u8** *(0~3)* | Returns the current player ID. `sync()` | - | Call this method every time you need to fetch new data. `waitFor(playerId)` | **bool** | Waits for data from player #`playerId`. Returns `true` on success, or `false` on disconnection. `waitFor(playerId, cancel)` | **bool** | Like `waitFor(playerId)` but accepts a `cancel()` function. The library will continuously invoke it, and abort the wait if it returns `true`. @@ -125,7 +125,7 @@ Name | Return type | Description `isActive()` | **bool** | Returns whether the library is active or not. `activate(baudRate = BAUD_RATE_1)` | - | Activates the library in a specific `baudRate` (`LinkRawCable::BaudRate`). `deactivate()` | - | Deactivates the library. -`transfer(data)` | **LinkRawCable::Response** | Exchanges `data` with the connected consoles. Returns the received data, including the assigned player id. +`transfer(data)` | **LinkRawCable::Response** | Exchanges `data` with the connected consoles. Returns the received data, including the assigned player ID. `transfer(data, cancel)` | **LinkRawCable::Response** | Like `transfer(data)` but accepts a `cancel()` function. The library will continuously invoke it, and abort the transfer if it returns `true`. `transferAsync(data)` | - | Schedules a `data` transfer and returns. After this, call `getAsyncState()` and `getAsyncData()`. Note that until you retrieve the async data, normal `transfer(...)`s won't do anything! `getAsyncState()` | **LinkRawCable::AsyncState** | Returns the state of the last async transfer (one of `LinkRawCable::AsyncState::IDLE`, `LinkRawCable::AsyncState::WAITING`, or `LinkRawCable::AsyncState::READY`). @@ -191,14 +191,14 @@ Name | Return type | Description `getServersAsyncStart()` | **bool** | Starts looking for broadcasting servers and changes the state to `SEARCHING`. After this, call `getServersAsyncEnd(...)` 1 second later. `getServersAsyncEnd(servers)` | **bool** | Fills the `servers` array with all the currently broadcasting servers. Changes the state to `AUTHENTICATED` again. `connect(serverId)` | **bool** | Starts a connection with `serverId` and changes the state to `CONNECTING`. -`keepConnecting()` | **bool** | When connecting, this needs to be called until the state is `CONNECTED`. It assigns a player id. Keep in mind that `isConnected()` and `playerCount()` won't be updated until the first message from server arrives. +`keepConnecting()` | **bool** | When connecting, this needs to be called until the state is `CONNECTED`. It assigns a player ID. Keep in mind that `isConnected()` and `playerCount()` won't be updated until the first message from server arrives. `send(data)` | **bool** | Enqueues `data` to be sent to other nodes. `receive(messages)` | **bool** | Fills the `messages` array with incoming messages, forwarding if needed. `getState()` | **LinkWireless::State** | Returns the current state (one of `LinkWireless::State::NEEDS_RESET`, `LinkWireless::State::AUTHENTICATED`, `LinkWireless::State::SEARCHING`, `LinkWireless::State::SERVING`, `LinkWireless::State::CONNECTING`, or `LinkWireless::State::CONNECTED`). `isConnected()` | **bool** | Returns true if the player count is higher than 1. `isSessionActive()` | **bool** | Returns true if the state is `SERVING` or `CONNECTED`. `playerCount()` | **u8** *(1~5)* | Returns the number of connected players. -`currentPlayerId()` | **u8** *(0~4)* | Returns the current player id. +`currentPlayerId()` | **u8** *(0~4)* | Returns the current player ID. `getLastError([clear])` | **LinkWireless::Error** | If one of the other methods returns `false`, you can inspect this to know the cause. After this call, the last error is cleared if `clear` is `true` (default behavior). ⚠️ `0xFFFF` is a reserved value, so don't send it! @@ -227,7 +227,7 @@ Name | Return type | Description ## Methods -- There's one method for every supported wireless adapter command. +- There's one method for every supported Wireless Adapter command. - Use `sendCommand(...)` to send arbitrary commands. # 🔧🏛 LinkWirelessOpenSDK diff --git a/docs/wireless_adapter.md b/docs/wireless_adapter.md index 911f9b5..af01c4c 100644 --- a/docs/wireless_adapter.md +++ b/docs/wireless_adapter.md @@ -290,7 +290,7 @@ Both Pokemon games and the multiboot ROM that the adapter sends when no cartridg * The number of available slots depends on `maxPlayers` (see [Setup](#setup---0x17)) and/or [EndHost](#endhost---0x1b). * 4th byte: Zero. -🆔 IDs are randomly generated. Each time you broadcast or connect, the adapter assigns you a new id. +🆔 IDs are randomly generated. Each time you broadcast or connect, the adapter assigns you a new ID. ✅ Reading broadcasts is a three-step process: First, you send `0x1c` (you will get an ACK instantly), and start waiting until the adapter retrieves data (games usually wait 1 full second). Then, send a `0x1d` and it will return what's described above. Lastly, send a `0x1e` to finish the process (you can ignore what the adapter returns here). If you don't send that last `0x1e`, the next command will fail. diff --git a/examples/LinkCable_full/src/main.cpp b/examples/LinkCable_full/src/main.cpp index 9f8410e..fe10b35 100644 --- a/examples/LinkCable_full/src/main.cpp +++ b/examples/LinkCable_full/src/main.cpp @@ -45,7 +45,7 @@ int main() { static constexpr int BIT_ERROR = 6; static constexpr int BIT_START = 7; - // log player id/count and important flags + // log player ID/count and important flags TextStream::instance().setText( "P" + asStr(linkConnection->currentPlayerId()) + "/" + asStr(linkConnection->playerCount()) + "-R" + diff --git a/examples/LinkRawWireless_demo/src/scenes/DebugScene.cpp b/examples/LinkRawWireless_demo/src/scenes/DebugScene.cpp index 41d9edf..11cf04b 100644 --- a/examples/LinkRawWireless_demo/src/scenes/DebugScene.cpp +++ b/examples/LinkRawWireless_demo/src/scenes/DebugScene.cpp @@ -772,7 +772,7 @@ genericWait: } int DebugScene::selectServerId() { - switch (selectOption("Which server id?", std::vector{ + switch (selectOption("Which server ID?", std::vector{ "", "", "", "", ""})) { case 0: { diff --git a/lib/LinkCable.hpp b/lib/LinkCable.hpp index 57bbc54..8e65d73 100644 --- a/lib/LinkCable.hpp +++ b/lib/LinkCable.hpp @@ -213,7 +213,7 @@ class LinkCable { [[nodiscard]] u8 playerCount() { return state.playerCount; } /** - * @brief Returns the current player id (`0~3`). + * @brief Returns the current player ID (`0~3`). */ [[nodiscard]] u8 currentPlayerId() { return state.currentPlayerId; } @@ -242,7 +242,7 @@ class LinkCable { /** * @brief Waits for data from player #`playerId`. Returns `true` on success, * or `false` on disconnection. - * @param playerId A player id. + * @param playerId A player ID. */ bool waitFor(u8 playerId) { return waitFor(playerId, []() { return false; }); @@ -271,7 +271,7 @@ class LinkCable { /** * @brief Returns `true` if there are pending messages from player * #`playerId`. - * @param playerId A player id. + * @param playerId A player ID. * \warning Keep in mind that if this returns `false`, it will keep doing so * until you *fetch new data* with `sync()`. */ @@ -281,7 +281,7 @@ class LinkCable { /** * @brief Dequeues and returns the next message from player #`playerId`. - * @param playerId A player id. + * @param playerId A player ID. * \warning If there's no data from that player, a `0` will be returned. */ u16 read(u8 playerId) { return state.incomingMessages[playerId].pop(); } @@ -289,7 +289,7 @@ class LinkCable { /** * @brief Returns the next message from player #`playerId` without dequeuing * it. - * @param playerId A player id. + * @param playerId A player ID. * \warning If there's no data from that player, a `0` will be returned. */ [[nodiscard]] u16 peek(u8 playerId) { diff --git a/lib/LinkRawCable.hpp b/lib/LinkRawCable.hpp index 5b58690..3eece97 100644 --- a/lib/LinkRawCable.hpp +++ b/lib/LinkRawCable.hpp @@ -117,7 +117,7 @@ class LinkRawCable { /** * @brief Exchanges `data` with the connected consoles. Returns the received - * data from each player, including the assigned player id. + * data from each player, including the assigned player ID. * @param data The value to be sent. */ Response transfer(u16 data) { @@ -126,7 +126,7 @@ class LinkRawCable { /** * @brief Exchanges `data` with the connected consoles. Returns the received - * data from each player, including the assigned player id. + * data from each player, including the assigned player ID. * @param data The value to be sent. * @param cancel A function that will be continuously invoked. If it returns * `true`, the transfer will be aborted and the response will be empty. diff --git a/lib/LinkRawWireless.hpp b/lib/LinkRawWireless.hpp index fb4921f..f41637d 100644 --- a/lib/LinkRawWireless.hpp +++ b/lib/LinkRawWireless.hpp @@ -15,16 +15,12 @@ #include "LinkGPIO.hpp" #include "LinkSPI.hpp" -// Enable logging (set `linkRawWireless->logger` and uncomment to enable) +/** + * @brief Enable logging. + * \warning Set `linkRawWireless->logger` and uncomment to enable! + */ // #define LINK_RAW_WIRELESS_ENABLE_LOGGING -#ifdef LINK_RAW_WIRELESS_ENABLE_LOGGING -#include -#define LRWLOG(str) logger(str) -#else -#define LRWLOG(str) -#endif - static volatile char LINK_RAW_WIRELESS_VERSION[] = "LinkRawWireless/v7.0.0"; #define LINK_RAW_WIRELESS_MAX_PLAYERS 5 @@ -35,6 +31,18 @@ static volatile char LINK_RAW_WIRELESS_VERSION[] = "LinkRawWireless/v7.0.0"; #define LINK_RAW_WIRELESS_MAX_USER_NAME_LENGTH 8 #define LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH 23 +#ifdef LINK_RAW_WIRELESS_ENABLE_LOGGING +#include +#define LRWLOG(str) logger(str) +#else +#define LRWLOG(str) +#endif + +/** + * @brief A low level driver for the GBA Wireless Adapter. + * \warning Advanced usage only! + * \warning If you're building a game, use `LinkWireless`. + */ class LinkRawWireless { private: using u32 = unsigned int; @@ -149,8 +157,15 @@ class LinkRawWireless { u32 dataSize = 0; }; + /** + * @brief Returns whether the library is active or not. + */ [[nodiscard]] bool isActive() { return isEnabled; } + /** + * @brief Activates the library. + * Returns whether initialization was successful or not. + */ bool activate() { isEnabled = false; @@ -160,6 +175,9 @@ class LinkRawWireless { return success; } + /** + * @brief Deactivates the library. + */ bool deactivate() { bool success = sendCommand(COMMAND_BYE).success; @@ -170,6 +188,17 @@ class LinkRawWireless { return success; } + /** + * @brief Calls the Setup (`0x17`) command. + * @param maxPlayers `(2~5)` Maximum players in hosted rooms. Clients should + * set this to `0`. + * @param maxTransmissions Number of transmissions before marking a player as + * disconnected. `0` means infinite retransmissions. + * @param waitTimeout Timeout of the *waiting commands*, in frames (16.6ms). + * `0` means no timeout. + * @param magic A part of the protocol that hasn't been reverse-engineered + * yet. For now, it's magic (`0x003c0000`). + */ bool setup(u8 maxPlayers = LINK_RAW_WIRELESS_MAX_PLAYERS, u8 maxTransmissions = 4, u8 waitTimeout = 32, @@ -181,6 +210,12 @@ class LinkRawWireless { return sendCommand(COMMAND_SETUP, {config}, 1).success; } + /** + * @brief Calls the Broadcast (`0x16`) command. + * @param gameName Game name. Maximum `14` characters + NULL terminator. + * @param userName User name. Maximum `8` characters + NULL terminator. + * @param gameId `(0 ~ 0x7FFF)` Game ID. + */ bool broadcast(const char* gameName = "", const char* userName = "", u16 gameId = LINK_RAW_WIRELESS_MAX_GAME_ID) { @@ -223,6 +258,9 @@ class LinkRawWireless { return true; } + /** + * @brief Calls the StartHost (`0x19`) command. + */ bool startHost() { bool success = sendCommand(COMMAND_START_HOST).success; @@ -238,6 +276,10 @@ class LinkRawWireless { return true; } + /** + * @brief Calls the SlotStatus (`0x14`) command. + * @param response A structure that will be filled with the response data. + */ bool getSlotStatus(SlotStatusResponse& response) { auto result = sendCommand(COMMAND_SLOT_STATUS); @@ -260,6 +302,10 @@ class LinkRawWireless { return true; } + /** + * @brief Calls the AcceptConnections (`0x1a`) command. + * @param response A structure that will be filled with the response data. + */ bool acceptConnections(AcceptConnectionsResponse& response) { auto result = sendCommand(COMMAND_ACCEPT_CONNECTIONS); @@ -283,6 +329,10 @@ class LinkRawWireless { return true; } + /** + * @brief Calls the EndHost (`0x1b`) command. + * @param response A structure that will be filled with the response data. + */ bool endHost(AcceptConnectionsResponse& response) { auto result = sendCommand(COMMAND_END_HOST); @@ -306,6 +356,9 @@ class LinkRawWireless { return true; } + /** + * @brief Calls the BroadcastRead1 (`0x1c`) command. + */ bool broadcastReadStart() { bool success = sendCommand(COMMAND_BROADCAST_READ_START).success; @@ -320,6 +373,9 @@ class LinkRawWireless { return true; } + /** + * @brief Calls the BroadcastRead2 (`0x1d`) command. + */ bool broadcastReadPoll(BroadcastReadPollResponse& response) { auto result = sendCommand(COMMAND_BROADCAST_READ_POLL); bool success = @@ -357,6 +413,9 @@ class LinkRawWireless { return true; } + /** + * @brief Calls the BroadcastRead3 (`0x1e`) command. + */ bool broadcastReadEnd() { bool success = sendCommand(COMMAND_BROADCAST_READ_END).success; @@ -371,6 +430,10 @@ class LinkRawWireless { return true; } + /** + * @brief Calls the Connect (`0x1f`) command. + * @param serverId Device ID of the server. + */ bool connect(u16 serverId) { bool success = sendCommand(COMMAND_CONNECT, {serverId}, 1).success; @@ -385,6 +448,10 @@ class LinkRawWireless { return true; } + /** + * @brief Calls the IsFinishedConnect (`0x20`) command. + * @param response A structure that will be filled with the response data. + */ bool keepConnecting(ConnectionStatus& response) { auto result = sendCommand(COMMAND_IS_FINISHED_CONNECT); if (!result.success || result.responsesSize == 0) { @@ -413,6 +480,9 @@ class LinkRawWireless { return true; } + /** + * @brief Calls the FinishConnection (`0x21`) command. + */ bool finishConnection() { auto result = sendCommand(COMMAND_FINISH_CONNECTION); if (!result.success || result.responsesSize == 0) { @@ -437,6 +507,13 @@ class LinkRawWireless { return true; } + /** + * @brief Calls the SendData (`0x24`) command. + * @param data The values to be sent. + * @param dataSize The number of 32-bit values in the `data` array. + * @param _bytes The number of BYTES to send. If `0`, the method will use + * `dataSize * 4` instead. + */ bool sendData( std::array data, u32 dataSize, @@ -461,6 +538,15 @@ class LinkRawWireless { return true; } + /** + * @brief Calls the SendDataAndWait (`0x25`) command. + * @param data The values to be sent. + * @param dataSize The number of 32-bit values in the `data` array. + * @param remoteCommand A structure that will be filled with the remote + * command from the adapter. + * @param _bytes The number of BYTES to send. If `0`, the method will use + * `dataSize * 4` instead. + */ bool sendDataAndWait( std::array data, u32 dataSize, @@ -487,6 +573,10 @@ class LinkRawWireless { return remoteCommand.success; } + /** + * @brief Calls the ReceiveData (`0x26`) command. + * @param response A structure that will be filled with the response data. + */ bool receiveData(ReceiveDataResponse& response) { auto result = sendCommand(COMMAND_RECEIVE_DATA); for (u32 i = 0; i < result.responsesSize; i++) @@ -516,6 +606,11 @@ class LinkRawWireless { return true; } + /** + * @brief Calls the Wait (`0x27`) command. + * @param remoteCommand A structure that will be filled with the remote + * command from the adapter. + */ bool wait(RemoteCommand& remoteCommand) { if (!sendCommand(COMMAND_WAIT, {}, 0, true).success) { reset(); @@ -527,6 +622,13 @@ class LinkRawWireless { return remoteCommand.success; } + /** + * @brief Calls an arbitrary command and returns the response. + * @param type The ID of the command. + * @param params The command parameters. + * @param length The number of 32-bit values in the `params` array. + * @param invertsClock Whether this command inverts the clock or not (Wait). + */ CommandResult sendCommand( u8 type, std::array params = @@ -596,6 +698,10 @@ class LinkRawWireless { return result; } + /** + * @brief Inverts the clock and waits until the adapter sends a command. + * Returns the remote command. + */ RemoteCommand receiveCommandFromAdapter() { RemoteCommand remoteCommand; @@ -668,17 +774,40 @@ class LinkRawWireless { return remoteCommand; } + /** + * @brief Returns the maximum number of transferrable 32-bit values. + * It's 23 for servers and 4 for clients. + */ [[nodiscard]] u32 getDeviceTransferLength() { return state == SERVING ? LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH : LINK_RAW_WIRELESS_MAX_CLIENT_TRANSFER_LENGTH; } + /** + * @brief Returns the current state. + */ [[nodiscard]] State getState() { return state; } + + /** + * @brief Returns true if the player count is higher than 1. + */ [[nodiscard]] bool isConnected() { return sessionState.playerCount > 1; } + + /** + * @brief Returns true if the state is `SERVING` or `CONNECTED`. + */ [[nodiscard]] bool isSessionActive() { return state == SERVING || state == CONNECTED; } + + /** + * @brief Returns the number of connected players. + */ [[nodiscard]] u8 playerCount() { return sessionState.playerCount; } + + /** + * @brief Returns the current player ID. + */ [[nodiscard]] u8 currentPlayerId() { return sessionState.currentPlayerId; } ~LinkRawWireless() { @@ -702,6 +831,13 @@ class LinkRawWireless { State state = NEEDS_RESET; volatile bool isEnabled = false; + /** + * @brief Copies a null-terminated `source` string to a `target` destination + * (up to `length` characters). + * @param target Target string. + * @param source Source string. + * @param length Number of characters. + */ void copyName(char* target, const char* source, u32 length) { u32 len = std::strlen(source); @@ -712,6 +848,14 @@ class LinkRawWireless { target[i] = '\0'; } + /** + * @brief Recovers parts of the `name` of a Wireless Adapter room. + * @param name Target string. + * @param nameCursor Current position within `name`. + * @param word Current value. + * @param includeFirstTwoBytes Whether the first two bytes from `word` should + * be used. + */ void recoverName(char* name, u32& nameCursor, u32 word, @@ -733,6 +877,10 @@ class LinkRawWireless { name[nameCursor++] = character; } + /** + * @brief Resets the adapter + * @param initialize Whether it's an initialization (first time) or not. + */ bool reset(bool initialize = false) { resetState(); if (initialize) @@ -740,6 +888,9 @@ class LinkRawWireless { return initialize && start(); } + /** + * @brief Resets all the state. + */ void resetState() { LRWLOG("state = NEEDS_RESET"); this->state = NEEDS_RESET; @@ -747,8 +898,14 @@ class LinkRawWireless { this->sessionState.currentPlayerId = 0; } + /** + * @brief Stops the communication. + */ void stop() { linkSPI->deactivate(); } + /** + * @brief Starts the communication. + */ bool start() { pingAdapter(); LRWLOG("setting SPI to 256Kbps"); @@ -771,6 +928,9 @@ class LinkRawWireless { return true; } + /** + * @brief Sends the signal to reset the adapter. + */ void pingAdapter() { LRWLOG("setting SO as OUTPUT"); linkGPIO->setMode(LinkGPIO::Pin::SO, LinkGPIO::Direction::OUTPUT); @@ -783,6 +943,9 @@ class LinkRawWireless { linkGPIO->writePin(LinkGPIO::SD, false); } + /** + * @brief Sends the login sequence to the adapter. + */ bool login() { LoginMemory memory; @@ -800,6 +963,12 @@ class LinkRawWireless { return true; } + /** + * @brief Exchanges part of the login sequence with the adapter. + * @param data The value to be sent. + * @param expectedResponse The expected response. + * @param memory A structure that holds memory of the previous values. + */ bool exchangeLoginPacket(u16 data, u16 expectedResponse, LoginMemory& memory) { @@ -819,10 +988,21 @@ class LinkRawWireless { return true; } + /** + * @brief Builds a 32-bit value representing the command. + * @param type The ID of the command. + * @param length The number of 32-bit values that will be sent. + */ u32 buildCommand(u8 type, u8 length = 0) { return buildU32(COMMAND_HEADER, buildU16(length, type)); } + /** + * @brief Transfers `data` via SPI and performs the adapter's ACK procedure. + * Returns the received value. + * @param data The value to be sent. + * @param customAck Whether the adapter's ACK procedure should be used or not. + */ u32 transfer(u32 data, bool customAck = true) { if (!customAck) wait(TRANSFER_WAIT); @@ -839,6 +1019,11 @@ class LinkRawWireless { return receivedData; } + /** + * @brief Transfers `data` via SPI and performs the inverted adapter's ACK + * procedure. Returns the received value. + * @param data The value to be sent. + */ u32 transferAndStartClockInversionACK(u32 data) { u32 lines = 0; u32 vCount = Link::_REG_VCOUNT; @@ -852,6 +1037,9 @@ class LinkRawWireless { return receivedData; } + /** + * @brief Performs the adapter's ACK procedure. + */ bool acknowledge() { u32 lines = 0; u32 vCount = Link::_REG_VCOUNT; @@ -877,6 +1065,9 @@ class LinkRawWireless { return true; } + /** + * @brief Starts performing the inverted adapter's ACK procedure. + */ bool reverseAcknowledgeStart() { u32 lines = 0; u32 vCount = Link::_REG_VCOUNT; @@ -896,6 +1087,12 @@ class LinkRawWireless { return true; } + /** + * @brief Performs the inverted adapter's ACK procedure. + * @param isLastPart Whether it's the last part of the procedure or not. + * \warning `isLastPart` is required when there's no subsequent + * `linkSPI->transfer(...)` call. + */ bool reverseAcknowledge(bool isLastPart = false) { u32 lines = 0; u32 vCount = Link::_REG_VCOUNT; @@ -932,10 +1129,21 @@ class LinkRawWireless { return true; } + /** + * @brief Evaluates a timeout defined by `CMD_TIMEOUT`. + * @param lines A line counter that will be updated. + * @param vCount Starting `VCOUNT`. + */ bool cmdTimeout(u32& lines, u32& vCount) { return timeout(CMD_TIMEOUT, lines, vCount); } + /** + * @brief Evaluates a timeout defined by `limit`. + * @param limit Maximum number of lines to wait. + * @param lines A line counter that will be updated. + * @param vCount Starting `VCOUNT`. + */ bool timeout(u32 limit, u32& lines, u32& vCount) { if (Link::_REG_VCOUNT != vCount) { lines += Link::_max((int)Link::_REG_VCOUNT - (int)vCount, 0); @@ -945,6 +1153,10 @@ class LinkRawWireless { return lines > limit; } + /** + * @brief Waits a number of `verticalLines`. + * @param verticalLines Number of lines to wait. + */ void wait(u32 verticalLines) { u32 count = 0; u32 vCount = Link::_REG_VCOUNT; @@ -957,14 +1169,22 @@ class LinkRawWireless { }; } + /** + * @brief Logs an error message (expected vs received). + * @param expected The expected number. + * @param received The received number. + */ void logExpectedButReceived(u32 expected, u32 received) { LRWLOG("! expected 0x" + toHex(expected)); LRWLOG("! but received 0x" + toHex(received)); } #ifdef LINK_RAW_WIRELESS_ENABLE_LOGGING + /** + * @brief Converts `w` to an hexadecimal string. + */ template - std::string toHex(I w, size_t hex_len = sizeof(I) << 1) { + [[nodiscard]] std::string toHex(I w, size_t hex_len = sizeof(I) << 1) { static const char* digits = "0123456789ABCDEF"; std::string rc(hex_len, '0'); for (size_t i = 0, j = (hex_len - 1) * 4; i < hex_len; ++i, j -= 4) @@ -973,12 +1193,35 @@ class LinkRawWireless { } #endif - u32 buildU32(u16 msB, u16 lsB) { return (msB << 16) | lsB; } - u16 buildU16(u8 msB, u8 lsB) { return (msB << 8) | lsB; } - u16 msB32(u32 value) { return value >> 16; } - u16 lsB32(u32 value) { return value & 0xffff; } - u8 msB16(u16 value) { return value >> 8; } - u8 lsB16(u16 value) { return value & 0xff; } + /** + * @brief Builds a u32 numbers from `msB` and `lsB` + */ + [[nodiscard]] u32 buildU32(u16 msB, u16 lsB) { return (msB << 16) | lsB; } + + /** + * @brief Builds a u16 numbers from `msB` and `lsB` + */ + [[nodiscard]] u16 buildU16(u8 msB, u8 lsB) { return (msB << 8) | lsB; } + + /** + * @brief Returns the higher 16 bits of `value`. + */ + [[nodiscard]] u16 msB32(u32 value) { return value >> 16; } + + /** + * @brief Returns the lower 16 bits of `value`. + */ + [[nodiscard]] u16 lsB32(u32 value) { return value & 0xffff; } + + /** + * @brief Returns the higher 8 bits of `value`. + */ + [[nodiscard]] u8 msB16(u16 value) { return value >> 8; } + + /** + * @brief Returns the lower 8 bits of `value`. + */ + [[nodiscard]] u8 lsB16(u16 value) { return value & 0xff; } }; extern LinkRawWireless* linkRawWireless; diff --git a/lib/LinkWirelessMultiboot.hpp b/lib/LinkWirelessMultiboot.hpp index 50a99c5..c82f851 100644 --- a/lib/LinkWirelessMultiboot.hpp +++ b/lib/LinkWirelessMultiboot.hpp @@ -17,7 +17,7 @@ // romLength, // in bytes // "Multiboot", // game name // "Test", // user name -// 0xffff, // game id +// 0xffff, // game ID // 2, // number of players // [](LinkWirelessMultiboot::MultibootProgress progress) { // // check progress.[state,connectedClients,percentage]