mirror of
https://github.com/Gericom/libtwl.git
synced 2025-06-19 19:45:33 -04:00
90 lines
2.5 KiB
C
90 lines
2.5 KiB
C
#include <nds.h>
|
|
#include "libtwl/rtos/rtosIrq.h"
|
|
#include "libtwl/ipc/ipcSync.h"
|
|
#include "libtwl/ipc/ipcFifo.h"
|
|
#include "libtwl/ipc/ipcFifoSystem.h"
|
|
|
|
#define HANDSHAKE_PART0 0xA
|
|
#define HANDSHAKE_PART1 0xB
|
|
#define HANDSHAKE_PART2 0xC
|
|
|
|
static ipc_fifo_ch_handler_func_t sHandlerFuncs[IPC_FIFO_MSG_CHANNEL_COUNT];
|
|
static void* sHandlerArgs[IPC_FIFO_MSG_CHANNEL_COUNT];
|
|
|
|
static void recvFifoNotEmptyIrq(u32 irqMask)
|
|
{
|
|
while (!ipc_isRecvFifoEmpty())
|
|
{
|
|
u32 msg = ipc_recvWordDirect();
|
|
u32 channel = msg & IPC_FIFO_MSG_CHANNEL_MASK;
|
|
|
|
sHandlerFuncs[channel](channel, msg >> IPC_FIFO_MSG_CHANNEL_BITS, sHandlerArgs[channel]);
|
|
}
|
|
}
|
|
|
|
static void dummyChannelHandler(u32 channel, u32 data, void* arg)
|
|
{
|
|
|
|
}
|
|
|
|
void ipc_initFifoSystem(void)
|
|
{
|
|
for (int i = 0; i < IPC_FIFO_MSG_CHANNEL_COUNT; i++)
|
|
sHandlerFuncs[i] = &dummyChannelHandler;
|
|
|
|
u32 irqs = rtos_disableIrqs();
|
|
{
|
|
ipc_clearSendFifo();
|
|
ipc_ackFifoError();
|
|
ipc_enableRecvFifoNotEmptyIrq();
|
|
ipc_enableFifo();
|
|
|
|
rtos_ackIrqMask(RTOS_IRQ_IPC_FIFO_RECV);
|
|
rtos_setIrqFunc(RTOS_IRQ_IPC_FIFO_RECV, recvFifoNotEmptyIrq);
|
|
rtos_enableIrqMask(RTOS_IRQ_IPC_FIFO_RECV);
|
|
|
|
#ifdef LIBTWL_ARM9
|
|
while (ipc_getArm7SyncBits() != HANDSHAKE_PART0);
|
|
ipc_setArm9SyncBits(HANDSHAKE_PART0);
|
|
while (ipc_getArm7SyncBits() != HANDSHAKE_PART1);
|
|
ipc_setArm9SyncBits(HANDSHAKE_PART1);
|
|
while (ipc_getArm7SyncBits() != HANDSHAKE_PART2);
|
|
ipc_setArm9SyncBits(HANDSHAKE_PART2);
|
|
#endif
|
|
#ifdef LIBTWL_ARM7
|
|
ipc_setArm7SyncBits(HANDSHAKE_PART0);
|
|
while (ipc_getArm9SyncBits() != HANDSHAKE_PART0);
|
|
ipc_setArm7SyncBits(HANDSHAKE_PART1);
|
|
while (ipc_getArm9SyncBits() != HANDSHAKE_PART1);
|
|
ipc_setArm7SyncBits(HANDSHAKE_PART2);
|
|
while (ipc_getArm9SyncBits() != HANDSHAKE_PART2);
|
|
#endif
|
|
}
|
|
rtos_restoreIrqs(irqs);
|
|
}
|
|
|
|
void ipc_setChannelHandler(u32 channel, ipc_fifo_ch_handler_func_t handler, void* arg)
|
|
{
|
|
if (handler == NULL)
|
|
handler = &dummyChannelHandler;
|
|
sHandlerFuncs[channel] = handler;
|
|
sHandlerArgs[channel] = arg;
|
|
}
|
|
|
|
bool ipc_trySendFifoMessage(u32 channel, u32 data)
|
|
{
|
|
u32 irqs = rtos_disableIrqs();
|
|
if (ipc_isSendFifoFull())
|
|
{
|
|
rtos_restoreIrqs(irqs);
|
|
return false;
|
|
}
|
|
ipc_sendWordDirect((channel & IPC_FIFO_MSG_CHANNEL_MASK) | (data << IPC_FIFO_MSG_CHANNEL_BITS));
|
|
rtos_restoreIrqs(irqs);
|
|
return true;
|
|
}
|
|
|
|
void ipc_sendFifoMessage(u32 channel, u32 data)
|
|
{
|
|
while (!ipc_trySendFifoMessage(channel, data));
|
|
} |