mirror of
https://github.com/afska/gba-link-connection.git
synced 2026-04-25 16:23:41 -05:00
Organizing ISR functions
This commit is contained in:
parent
8e17f9a1a2
commit
6055e4faac
|
|
@ -1,8 +1,5 @@
|
|||
#include "LinkWireless.hpp"
|
||||
|
||||
#if defined(LINK_WIRELESS_PUT_ISR_IN_IWRAM) || \
|
||||
defined(LINK_WIRELESS_ENABLE_NESTED_IRQ)
|
||||
|
||||
#ifdef LINK_WIRELESS_PUT_ISR_IN_IWRAM
|
||||
|
||||
#if LINK_WIRELESS_PUT_ISR_IN_IWRAM_SERIAL == 1
|
||||
|
|
@ -21,37 +18,21 @@
|
|||
#define _LINK_TIMER_ISR
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
_LINK_SERIAL_ISR void LinkWireless::_onSerial() {
|
||||
#ifdef LINK_WIRELESS_ENABLE_NESTED_IRQ
|
||||
interrupt = true;
|
||||
LINK_BARRIER;
|
||||
// (nested interrupts are enabled by LinkRawWireless::_onSerial(...))
|
||||
#endif
|
||||
|
||||
__onSerial();
|
||||
|
||||
#ifdef LINK_WIRELESS_ENABLE_NESTED_IRQ
|
||||
irqEnd();
|
||||
#endif
|
||||
}
|
||||
|
||||
_LINK_TIMER_ISR void LinkWireless::_onTimer() {
|
||||
#ifdef LINK_WIRELESS_ENABLE_NESTED_IRQ
|
||||
if (interrupt)
|
||||
return;
|
||||
|
||||
interrupt = true;
|
||||
LINK_BARRIER;
|
||||
Link::_REG_IME = 1;
|
||||
#endif
|
||||
|
||||
__onTimer();
|
||||
}
|
||||
|
||||
#ifdef LINK_WIRELESS_ENABLE_NESTED_IRQ
|
||||
irqEnd();
|
||||
#endif
|
||||
_LINK_SERIAL_ISR void LinkWireless::processMessage(u32 playerId,
|
||||
u32 data,
|
||||
u32& currentPacketId,
|
||||
u32& playerBitMap,
|
||||
int& playerBitMapCount) {
|
||||
_processMessage(playerId, data, currentPacketId, playerBitMap,
|
||||
playerBitMapCount);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -114,6 +114,21 @@
|
|||
// #define LINK_WIRELESS_ENABLE_NESTED_IRQ
|
||||
#endif
|
||||
|
||||
// --- LINK_WIRELESS_PUT_ISR_IN_IWRAM knobs ---
|
||||
#ifndef LINK_WIRELESS_PUT_ISR_IN_IWRAM_SERIAL
|
||||
#define LINK_WIRELESS_PUT_ISR_IN_IWRAM_SERIAL 1
|
||||
#endif
|
||||
#ifndef LINK_WIRELESS_PUT_ISR_IN_IWRAM_TIMER
|
||||
#define LINK_WIRELESS_PUT_ISR_IN_IWRAM_TIMER 0
|
||||
#endif
|
||||
#ifndef LINK_WIRELESS_PUT_ISR_IN_IWRAM_SERIAL_LEVEL
|
||||
#define LINK_WIRELESS_PUT_ISR_IN_IWRAM_SERIAL_LEVEL "-Ofast"
|
||||
#endif
|
||||
#ifndef LINK_WIRELESS_PUT_ISR_IN_IWRAM_TIMER_LEVEL
|
||||
#define LINK_WIRELESS_PUT_ISR_IN_IWRAM_TIMER_LEVEL "-Ofast"
|
||||
#endif
|
||||
//---
|
||||
|
||||
LINK_VERSION_TAG LINK_WIRELESS_VERSION = "vLinkWireless/v8.0.0";
|
||||
|
||||
#define LINK_WIRELESS_MAX_PLAYERS LINK_RAW_WIRELESS_MAX_PLAYERS
|
||||
|
|
@ -133,19 +148,6 @@ LINK_VERSION_TAG LINK_WIRELESS_VERSION = "vLinkWireless/v8.0.0";
|
|||
if (!reset()) \
|
||||
return false;
|
||||
|
||||
// --- LINK_WIRELESS_PUT_ISR_IN_IWRAM knobs ---
|
||||
#ifndef LINK_WIRELESS_PUT_ISR_IN_IWRAM_SERIAL
|
||||
#define LINK_WIRELESS_PUT_ISR_IN_IWRAM_SERIAL 1
|
||||
#endif
|
||||
#ifndef LINK_WIRELESS_PUT_ISR_IN_IWRAM_TIMER
|
||||
#define LINK_WIRELESS_PUT_ISR_IN_IWRAM_TIMER 0
|
||||
#endif
|
||||
#ifndef LINK_WIRELESS_PUT_ISR_IN_IWRAM_SERIAL_LEVEL
|
||||
#define LINK_WIRELESS_PUT_ISR_IN_IWRAM_SERIAL_LEVEL "-Ofast"
|
||||
#endif
|
||||
#ifndef LINK_WIRELESS_PUT_ISR_IN_IWRAM_TIMER_LEVEL
|
||||
#define LINK_WIRELESS_PUT_ISR_IN_IWRAM_TIMER_LEVEL "-Ofast"
|
||||
#endif
|
||||
#ifdef LINK_WIRELESS_PUT_ISR_IN_IWRAM
|
||||
#if LINK_WIRELESS_PUT_ISR_IN_IWRAM_SERIAL == 1
|
||||
#define LINK_WIRELESS_SERIAL_ISR LINK_INLINE
|
||||
|
|
@ -157,11 +159,19 @@ LINK_VERSION_TAG LINK_WIRELESS_VERSION = "vLinkWireless/v8.0.0";
|
|||
#else
|
||||
#define LINK_WIRELESS_TIMER_ISR
|
||||
#endif
|
||||
|
||||
#define LINK_WIRELESS_ISR_FUNC(name, params, args, body) \
|
||||
void name params; \
|
||||
LINK_INLINE void _##name params body
|
||||
#else
|
||||
#define LINK_WIRELESS_SERIAL_ISR
|
||||
#define LINK_WIRELESS_TIMER_ISR
|
||||
#define LINK_WIRELESS_ISR_FUNC(name, params, args, body) \
|
||||
void name params { \
|
||||
_##name args; \
|
||||
} \
|
||||
LINK_INLINE void _##name params body
|
||||
#endif
|
||||
// ---
|
||||
|
||||
/**
|
||||
* @brief A high level driver for the GBA Wireless Adapter.
|
||||
|
|
@ -886,64 +896,44 @@ class LinkWireless {
|
|||
#endif
|
||||
}
|
||||
|
||||
#if defined(LINK_WIRELESS_PUT_ISR_IN_IWRAM) || \
|
||||
defined(LINK_WIRELESS_ENABLE_NESTED_IRQ)
|
||||
void _onSerial();
|
||||
void _onTimer();
|
||||
#else
|
||||
void _onSerial() { __onSerial(); }
|
||||
void _onTimer() { __onTimer(); }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief This method is called by the SERIAL interrupt handler.
|
||||
* \warning This is internal API!
|
||||
*/
|
||||
LINK_INLINE void __onSerial() {
|
||||
if (!isEnabled)
|
||||
return;
|
||||
|
||||
#ifdef LINK_WIRELESS_PROFILING_ENABLED
|
||||
profileStart();
|
||||
LINK_WIRELESS_ISR_FUNC(_onSerial, (), (), {
|
||||
#ifdef LINK_WIRELESS_ENABLE_NESTED_IRQ
|
||||
interrupt = true;
|
||||
LINK_BARRIER;
|
||||
// (nested interrupts are enabled by LinkRawWireless::_onSerial(...))
|
||||
#endif
|
||||
|
||||
int status = linkRawWireless._onSerial(false);
|
||||
if (status <= -4) {
|
||||
return (void)abort(Error::ACKNOWLEDGE_FAILED);
|
||||
} else if (status > 0) {
|
||||
auto result = linkRawWireless._getAsyncCommandResultRef();
|
||||
processAsyncCommand(result);
|
||||
}
|
||||
___onSerial();
|
||||
|
||||
#ifdef LINK_WIRELESS_PROFILING_ENABLED
|
||||
serialTime += profileStop();
|
||||
serialIRQs++;
|
||||
#ifdef LINK_WIRELESS_ENABLE_NESTED_IRQ
|
||||
irqEnd();
|
||||
#endif
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* @brief This method is called by the TIMER interrupt handler.
|
||||
* \warning This is internal API!
|
||||
*/
|
||||
LINK_INLINE void __onTimer() {
|
||||
if (!isEnabled)
|
||||
LINK_WIRELESS_ISR_FUNC(_onTimer, (), (), {
|
||||
#ifdef LINK_WIRELESS_ENABLE_NESTED_IRQ
|
||||
if (interrupt)
|
||||
return;
|
||||
|
||||
#ifdef LINK_WIRELESS_PROFILING_ENABLED
|
||||
profileStart();
|
||||
interrupt = true;
|
||||
LINK_BARRIER;
|
||||
Link::_REG_IME = 1;
|
||||
#endif
|
||||
|
||||
if (!isSessionActive())
|
||||
return;
|
||||
___onTimer();
|
||||
|
||||
if (!isAsyncCommandActive())
|
||||
checkConnectionsOrTransferData();
|
||||
|
||||
#ifdef LINK_WIRELESS_PROFILING_ENABLED
|
||||
timerTime += profileStop();
|
||||
timerIRQs++;
|
||||
#ifdef LINK_WIRELESS_ENABLE_NESTED_IRQ
|
||||
irqEnd();
|
||||
#endif
|
||||
}
|
||||
})
|
||||
|
||||
struct Config {
|
||||
bool forwarding;
|
||||
|
|
@ -1086,10 +1076,8 @@ class LinkWireless {
|
|||
|
||||
#ifdef LINK_WIRELESS_ENABLE_NESTED_IRQ
|
||||
volatile bool interrupt = false, pendingVBlank = false;
|
||||
#endif
|
||||
|
||||
#ifdef LINK_WIRELESS_ENABLE_NESTED_IRQ
|
||||
void irqEnd() {
|
||||
LINK_INLINE void irqEnd() {
|
||||
Link::_REG_IME = 0;
|
||||
interrupt = false;
|
||||
LINK_BARRIER;
|
||||
|
|
@ -1100,6 +1088,48 @@ class LinkWireless {
|
|||
}
|
||||
#endif
|
||||
|
||||
LINK_INLINE void ___onSerial() {
|
||||
if (!isEnabled)
|
||||
return;
|
||||
|
||||
#ifdef LINK_WIRELESS_PROFILING_ENABLED
|
||||
profileStart();
|
||||
#endif
|
||||
|
||||
int status = linkRawWireless._onSerial(false);
|
||||
if (status <= -4) {
|
||||
return (void)abort(Error::ACKNOWLEDGE_FAILED);
|
||||
} else if (status > 0) {
|
||||
auto result = linkRawWireless._getAsyncCommandResultRef();
|
||||
processAsyncCommand(result);
|
||||
}
|
||||
|
||||
#ifdef LINK_WIRELESS_PROFILING_ENABLED
|
||||
serialTime += profileStop();
|
||||
serialIRQs++;
|
||||
#endif
|
||||
}
|
||||
|
||||
LINK_INLINE void ___onTimer() {
|
||||
if (!isEnabled)
|
||||
return;
|
||||
|
||||
#ifdef LINK_WIRELESS_PROFILING_ENABLED
|
||||
profileStart();
|
||||
#endif
|
||||
|
||||
if (!isSessionActive())
|
||||
return;
|
||||
|
||||
if (!isAsyncCommandActive())
|
||||
checkConnectionsOrTransferData();
|
||||
|
||||
#ifdef LINK_WIRELESS_PROFILING_ENABLED
|
||||
timerTime += profileStop();
|
||||
timerIRQs++;
|
||||
#endif
|
||||
}
|
||||
|
||||
LINK_INLINE void processAsyncCommand(
|
||||
const LinkRawWireless::CommandResult* commandResult) { // (irq only)
|
||||
if (!commandResult->success) {
|
||||
|
|
@ -1164,7 +1194,7 @@ class LinkWireless {
|
|||
}
|
||||
}
|
||||
|
||||
LINK_WIRELESS_TIMER_ISR void checkConnectionsOrTransferData() { // (irq only)
|
||||
void checkConnectionsOrTransferData() { // (irq only)
|
||||
if (linkRawWireless.getState() == State::SERVING &&
|
||||
!sessionState.signalLevelCalled) {
|
||||
// SignalLevel (start)
|
||||
|
|
@ -1185,7 +1215,7 @@ class LinkWireless {
|
|||
}
|
||||
}
|
||||
|
||||
LINK_WIRELESS_TIMER_ISR void sendPendingData() { // (irq only)
|
||||
void sendPendingData() { // (irq only)
|
||||
copyOutgoingState();
|
||||
|
||||
setDataFromOutgoingMessages();
|
||||
|
|
@ -1193,9 +1223,9 @@ class LinkWireless {
|
|||
clearInflightMessagesIfNeeded();
|
||||
}
|
||||
|
||||
LINK_WIRELESS_TIMER_ISR void setDataFromOutgoingMessages() { // (irq only)
|
||||
addAsyncData(0, true); // SendData header (filled later)
|
||||
addAsyncData(0); // Transfer header (filled later)
|
||||
void setDataFromOutgoingMessages() { // (irq only)
|
||||
addAsyncData(0, true); // SendData header (filled later)
|
||||
addAsyncData(0); // Transfer header (filled later)
|
||||
|
||||
bool isServer = linkRawWireless.getState() == State::SERVING;
|
||||
u32 maxPacketIds = isServer ? MAX_PACKET_IDS_SERVER : MAX_PACKET_IDS_CLIENT;
|
||||
|
|
@ -1285,12 +1315,11 @@ class LinkWireless {
|
|||
nextAsyncCommandData[0] = linkRawWireless.getSendDataHeaderFor(bytes);
|
||||
}
|
||||
|
||||
LINK_WIRELESS_TIMER_ISR u32
|
||||
buildTransferHeader(bool isServer,
|
||||
u32 firstPacketId,
|
||||
u32 firstMsg,
|
||||
u32 msgCount,
|
||||
bool highPart) { // (irq only)
|
||||
u32 buildTransferHeader(bool isServer,
|
||||
u32 firstPacketId,
|
||||
u32 firstMsg,
|
||||
u32 msgCount,
|
||||
bool highPart) { // (irq only)
|
||||
TransferHeader transferHeader = {};
|
||||
|
||||
// player count / client heartbeat
|
||||
|
|
@ -1335,7 +1364,7 @@ class LinkWireless {
|
|||
return packer.asInt;
|
||||
}
|
||||
|
||||
LINK_WIRELESS_TIMER_ISR void clearInflightMessagesIfNeeded() { // (irq only)
|
||||
void clearInflightMessagesIfNeeded() { // (irq only)
|
||||
if (config.retransmission)
|
||||
return;
|
||||
|
||||
|
|
@ -1475,71 +1504,77 @@ class LinkWireless {
|
|||
copyIncomingState();
|
||||
}
|
||||
|
||||
LINK_WIRELESS_SERIAL_ISR void processMessage(
|
||||
u32 playerId,
|
||||
u32 data,
|
||||
u32& currentPacketId,
|
||||
u32& playerBitMap,
|
||||
int& playerBitMapCount) { // (irq only)
|
||||
// store the packet ID and increment (msgs are consecutive inside transfers)
|
||||
u32 packetId = currentPacketId;
|
||||
currentPacketId =
|
||||
(currentPacketId + 1) %
|
||||
(playerId == 0 ? MAX_PACKET_IDS_SERVER : MAX_PACKET_IDS_CLIENT);
|
||||
LINK_WIRELESS_ISR_FUNC(
|
||||
processMessage,
|
||||
(u32 playerId,
|
||||
u32 data,
|
||||
u32& currentPacketId,
|
||||
u32& playerBitMap,
|
||||
int& playerBitMapCount),
|
||||
(playerId, data, currentPacketId, playerBitMap, playerBitMapCount),
|
||||
{
|
||||
// (irq only)
|
||||
// store the packet ID and increment (msgs are consecutive inside
|
||||
// transfers)
|
||||
u32 packetId = currentPacketId;
|
||||
currentPacketId =
|
||||
(currentPacketId + 1) %
|
||||
(playerId == 0 ? MAX_PACKET_IDS_SERVER : MAX_PACKET_IDS_CLIENT);
|
||||
|
||||
// get msg player ID based on player bitmap
|
||||
u32 msgPlayerId = playerId;
|
||||
if (playerBitMapCount >= 0) {
|
||||
msgPlayerId =
|
||||
(playerBitMap >> PLAYER_ID_BITS * playerBitMapCount) & PLAYER_ID_MASK;
|
||||
playerBitMapCount++;
|
||||
// get msg player ID based on player bitmap
|
||||
u32 msgPlayerId = playerId;
|
||||
if (playerBitMapCount >= 0) {
|
||||
msgPlayerId = (playerBitMap >> PLAYER_ID_BITS * playerBitMapCount) &
|
||||
PLAYER_ID_MASK;
|
||||
playerBitMapCount++;
|
||||
|
||||
if (playerBitMapCount >= MAX_PLAYER_BITMAP_ENTRIES &&
|
||||
!((playerBitMap >> BIT_HAS_MORE) & 1))
|
||||
playerBitMapCount = -1;
|
||||
}
|
||||
if (playerBitMapCount >= MAX_PLAYER_BITMAP_ENTRIES &&
|
||||
!((playerBitMap >> BIT_HAS_MORE) & 1))
|
||||
playerBitMapCount = -1;
|
||||
}
|
||||
|
||||
if (playerId == 0 && !sessionState.didReceiveFirstPacketFromServer) {
|
||||
// the first time clients receive something from the server,
|
||||
// they shouldn't have any expectations (since they can join at any time)
|
||||
sessionState.lastPacketIdFromServer = packetId;
|
||||
sessionState.didReceiveFirstPacketFromServer = true;
|
||||
} else {
|
||||
// if retransmission is enabled, the packet ID needs to be expected
|
||||
if (config.retransmission) {
|
||||
u32 expectedPacketId =
|
||||
playerId > 0
|
||||
? (sessionState.lastPacketIdFromClients[playerId] + 1) %
|
||||
MAX_PACKET_IDS_CLIENT
|
||||
: (sessionState.lastPacketIdFromServer + 1) %
|
||||
MAX_PACKET_IDS_SERVER;
|
||||
if (playerId == 0 && !sessionState.didReceiveFirstPacketFromServer) {
|
||||
// the first time clients receive something from the server,
|
||||
// they shouldn't have any expectations (since they can join at any
|
||||
// time)
|
||||
sessionState.lastPacketIdFromServer = packetId;
|
||||
sessionState.didReceiveFirstPacketFromServer = true;
|
||||
} else {
|
||||
// if retransmission is enabled, the packet ID needs to be expected
|
||||
if (config.retransmission) {
|
||||
u32 expectedPacketId =
|
||||
playerId > 0
|
||||
? (sessionState.lastPacketIdFromClients[playerId] + 1) %
|
||||
MAX_PACKET_IDS_CLIENT
|
||||
: (sessionState.lastPacketIdFromServer + 1) %
|
||||
MAX_PACKET_IDS_SERVER;
|
||||
|
||||
if (packetId != expectedPacketId)
|
||||
if (packetId != expectedPacketId)
|
||||
return;
|
||||
|
||||
if (playerId > 0)
|
||||
sessionState.lastPacketIdFromClients[playerId] = expectedPacketId;
|
||||
else
|
||||
sessionState.lastPacketIdFromServer = expectedPacketId;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore messages from myself
|
||||
if (msgPlayerId == linkRawWireless.sessionState.currentPlayerId)
|
||||
return;
|
||||
|
||||
if (playerId > 0)
|
||||
sessionState.lastPacketIdFromClients[playerId] = expectedPacketId;
|
||||
else
|
||||
sessionState.lastPacketIdFromServer = expectedPacketId;
|
||||
}
|
||||
}
|
||||
// add new message
|
||||
Message message;
|
||||
message.playerId = msgPlayerId;
|
||||
message.data = data;
|
||||
message.packetId = packetId;
|
||||
sessionState.newIncomingMessages.push(message);
|
||||
|
||||
// ignore messages from myself
|
||||
if (msgPlayerId == linkRawWireless.sessionState.currentPlayerId)
|
||||
return;
|
||||
|
||||
// add new message
|
||||
Message message;
|
||||
message.playerId = msgPlayerId;
|
||||
message.data = data;
|
||||
message.packetId = packetId;
|
||||
sessionState.newIncomingMessages.push(message);
|
||||
|
||||
// forward to other clients if needed
|
||||
if (playerId > 0 && config.forwarding &&
|
||||
linkRawWireless.sessionState.playerCount > 2)
|
||||
forwardMessage(message);
|
||||
}
|
||||
// forward to other clients if needed
|
||||
if (playerId > 0 && config.forwarding &&
|
||||
linkRawWireless.sessionState.playerCount > 2)
|
||||
forwardMessage(message);
|
||||
})
|
||||
|
||||
LINK_WIRELESS_SERIAL_ISR void forwardMessage(
|
||||
Message& message) { // (irq only)
|
||||
|
|
@ -1661,22 +1696,24 @@ class LinkWireless {
|
|||
return true;
|
||||
}
|
||||
|
||||
LINK_INLINE u32 newPacketId(u32 maxPacketIds) { // (irq only)
|
||||
LINK_WIRELESS_TIMER_ISR u32 newPacketId(u32 maxPacketIds) { // (irq only)
|
||||
return (sessionState.lastPacketId =
|
||||
(sessionState.lastPacketId + 1) % maxPacketIds);
|
||||
}
|
||||
|
||||
LINK_INLINE void addToLastAsyncDataHalfword(u16 value) { // (irq only)
|
||||
LINK_WIRELESS_TIMER_ISR void addToLastAsyncDataHalfword(
|
||||
u16 value) { // (irq only)
|
||||
addToAsyncDataShifted(nextAsyncCommandDataSize - 1, value, 16);
|
||||
}
|
||||
|
||||
LINK_INLINE void addToAsyncDataShifted(u32 index,
|
||||
u16 value,
|
||||
u32 shift) { // (irq only)
|
||||
LINK_WIRELESS_TIMER_ISR void addToAsyncDataShifted(u32 index,
|
||||
u16 value,
|
||||
u32 shift) { // (irq only)
|
||||
nextAsyncCommandData[index] |= value << shift;
|
||||
}
|
||||
|
||||
LINK_INLINE void addAsyncData(u32 value, bool start = false) { // (irq only)
|
||||
LINK_WIRELESS_TIMER_ISR void addAsyncData(u32 value,
|
||||
bool start = false) { // (irq only)
|
||||
if (start)
|
||||
nextAsyncCommandDataSize = 0;
|
||||
nextAsyncCommandData[nextAsyncCommandDataSize] = value;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user