Dropping tonc dependency in LinkRawCable

This commit is contained in:
Rodrigo Alfonso 2024-08-05 23:50:29 -03:00
parent b7bcd7848d
commit a113eccb1f
4 changed files with 70 additions and 20 deletions

View File

@ -24,7 +24,7 @@ A set of Game Boy Advance (GBA) C++ libraries to interact with the Serial Port.
## Usage
- Include the library you want (e.g. [LinkCable.hpp](lib/LinkCable.hpp)) in your game code, and refer to its comments for instructions. Most of these libraries are provided as single header files for simplicity. The only external dependency is **libtonc**, which comes preinstalled with *devkitARM*.
- Include the `lib/` folder in your project's include directory, and use the library you want (e.g. [LinkCable.hpp](lib/LinkCable.hpp)). Refer to its comments for instructions. No external dependencies are required.
- Check out the [examples](examples) folder.
* Builds are available in [Releases](https://github.com/afska/gba-link-connection/releases).
* They can be tested on real GBAs or using emulators.

View File

@ -1,10 +1,10 @@
// (0) Include the header
#include "../../../lib/LinkRawCable.hpp"
#include <tonc.h>
#include <string>
#include "../../_lib/interrupt.h"
// (0) Include the header
#include "../../../lib/LinkRawCable.hpp"
void log(std::string text);
void wait(u32 verticalLines);
inline void VBLANK() {}

View File

@ -17,15 +17,15 @@
// LinkRawCable::Response data = linkRawCable->transfer(0x1234);
// // (this blocks the console indefinitely)
// - 5) Exchange data with a cancellation callback:
// u16 data = linkRawCable->transfer(0x1234, []() {
// u16 keys = ~REG_KEYS & KEY_ANY;
// auto data = linkRawCable->transfer(0x1234, []() {
// auto keys = ~REG_KEYS & KEY_ANY;
// return keys & KEY_START;
// });
// - 6) Exchange data asynchronously:
// linkRawCable->transferAsync(0x1234);
// // ...
// if (linkRawCable->getAsyncState() == LinkRawCable::AsyncState::READY) {
// u16 data = linkRawCable->getAsyncData();
// auto data = linkRawCable->getAsyncData();
// // ...
// }
// --------------------------------------------------------------------------
@ -34,7 +34,7 @@
// - only transfer(...) if isReady()
// --------------------------------------------------------------------------
#include <tonc_core.h>
#include "_link_common.h"
#define LINK_RAW_CABLE_MAX_PLAYERS 4
#define LINK_RAW_CABLE_DISCONNECTED 0xffff
@ -58,6 +58,10 @@
static volatile char LINK_RAW_CABLE_VERSION[] = "LinkRawCable/v6.4.0";
class LinkRawCable {
using u32 = unsigned int;
using u16 = unsigned short;
using u8 = unsigned char;
public:
enum BaudRate {
BAUD_RATE_0, // 9600 bps
@ -162,26 +166,28 @@ class LinkRawCable {
volatile bool isEnabled = false;
void setMultiPlayMode() {
REG_RCNT = REG_RCNT & ~(1 << LINK_RAW_CABLE_BIT_GENERAL_PURPOSE_HIGH);
REG_SIOCNT = (1 << LINK_RAW_CABLE_BIT_MULTIPLAYER);
REG_SIOCNT |= baudRate;
REG_SIOMLT_SEND = 0;
Link::_REG_RCNT =
Link::_REG_RCNT & ~(1 << LINK_RAW_CABLE_BIT_GENERAL_PURPOSE_HIGH);
Link::_REG_SIOCNT = (1 << LINK_RAW_CABLE_BIT_MULTIPLAYER);
Link::_REG_SIOCNT |= baudRate;
Link::_REG_SIOMLT_SEND = 0;
}
void setGeneralPurposeMode() {
REG_RCNT = (REG_RCNT & ~(1 << LINK_RAW_CABLE_BIT_GENERAL_PURPOSE_LOW)) |
(1 << LINK_RAW_CABLE_BIT_GENERAL_PURPOSE_HIGH);
Link::_REG_RCNT =
(Link::_REG_RCNT & ~(1 << LINK_RAW_CABLE_BIT_GENERAL_PURPOSE_LOW)) |
(1 << LINK_RAW_CABLE_BIT_GENERAL_PURPOSE_HIGH);
}
void setData(u16 data) { REG_SIOMLT_SEND = data; }
void setData(u16 data) { Link::_REG_SIOMLT_SEND = data; }
Response getData() {
Response response = LINK_RAW_CABLE_EMPTY_RESPONSE;
for (u32 i = 0; i < LINK_RAW_CABLE_MAX_PLAYERS; i++)
response.data[i] = REG_SIOMULTI[i];
response.data[i] = Link::_REG_SIOMULTI[i];
response.playerId =
(REG_SIOCNT & (0b11 << LINK_RAW_CABLE_BITS_PLAYER_ID)) >>
(Link::_REG_SIOCNT & (0b11 << LINK_RAW_CABLE_BITS_PLAYER_ID)) >>
LINK_RAW_CABLE_BITS_PLAYER_ID;
return response;
@ -196,9 +202,9 @@ class LinkRawCable {
void setInterruptsOn() { setBitHigh(LINK_RAW_CABLE_BIT_IRQ); }
void setInterruptsOff() { setBitLow(LINK_RAW_CABLE_BIT_IRQ); }
bool isBitHigh(u8 bit) { return (REG_SIOCNT >> bit) & 1; }
void setBitHigh(u8 bit) { REG_SIOCNT |= 1 << bit; }
void setBitLow(u8 bit) { REG_SIOCNT &= ~(1 << bit); }
bool isBitHigh(u8 bit) { return (Link::_REG_SIOCNT >> bit) & 1; }
void setBitHigh(u8 bit) { Link::_REG_SIOCNT |= 1 << bit; }
void setBitLow(u8 bit) { Link::_REG_SIOCNT &= ~(1 << bit); }
};
extern LinkRawCable* linkRawCable;

44
lib/_link_common.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef LINK_COMMON_H
#define LINK_COMMON_H
namespace Link {
using u32 = unsigned int;
using u16 = unsigned short;
using u8 = unsigned char;
struct _TMR_REC {
union {
u16 start;
u16 count;
} __attribute__((packed));
u16 cnt;
} __attribute__((aligned(4)));
constexpr u32 _REG_BASE = 0x04000000;
inline volatile u16& _REG_RCNT =
*reinterpret_cast<volatile u16*>(_REG_BASE + 0x0134);
inline volatile u16& _REG_SIOCNT =
*reinterpret_cast<volatile u16*>(_REG_BASE + 0x0128);
inline volatile u32& _REG_SIODATA32 =
*reinterpret_cast<volatile u32*>(_REG_BASE + 0x0120);
inline volatile u16& _REG_SIODATA8 =
*reinterpret_cast<volatile u16*>(_REG_BASE + 0x012A);
inline volatile u16& _REG_SIOMLT_SEND =
*reinterpret_cast<volatile u16*>(_REG_BASE + 0x012A);
inline volatile u16* const _REG_SIOMULTI =
reinterpret_cast<volatile u16*>(_REG_BASE + 0x0120);
inline volatile _TMR_REC* const _REG_TM =
reinterpret_cast<volatile _TMR_REC*>(_REG_BASE + 0x0100);
} // namespace Link
#endif // LINK_COMMON_H