This repository has been archived on 2022-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
Luma3DS-3GX/sysmodules/pxi/source/PXI.c
2020-04-25 13:42:10 +01:00

140 lines
3.4 KiB
C

/*
PXI.c:
PXI I/O functions.
(c) TuxSH, 2016-2020
This is part of 3ds_pxi, which is licensed under the MIT license (see LICENSE for details).
*/
#include "PXI.h"
void PXIReset(void)
{
REG_PXI_SYNC = 0;
REG_PXI_CNT = CNT_CLEAR_SEND_FIFO;
for(u32 i = 0; i < 16; i += 2)
{
REG_PXI_RECV;
REG_PXI_RECV;
}
REG_PXI_CNT = 0;
REG_PXI_CNT = CNT_ENABLE_FIFOs | CNT_ACKNOWLEDGE_FIFO_ERROR | CNT_CLEAR_SEND_FIFO;
}
void PXITriggerSync9IRQ(void)
{
REG_PXI_INTERRUPT_CNT |= SYNC_TRIGGER_SYNC9_IRQ;
}
bool PXIIsSendFIFOFull(void)
{
return (REG_PXI_CNT & CNT_SEND_FIFO_FULL_STATUS) != 0;
}
void PXISendByte(u8 byte)
{
REG_PXI_BYTE_SENT_TO_REMOTE = byte;
}
void PXISendWord(u32 word)
{
while(REG_PXI_CNT & CNT_SEND_FIFO_FULL_STATUS);
REG_PXI_SEND = word;
}
void PXISendBuffer(const u32 *buffer, u32 nbWords)
{
for(; nbWords > 0; nbWords--)
{
while(REG_PXI_CNT & CNT_SEND_FIFO_FULL_STATUS);
REG_PXI_SEND = *buffer++;
}
}
bool PXIIsReceiveFIFOEmpty(void)
{
return (REG_PXI_CNT & CNT_RECEIVE_FIFO_EMPTY_STATUS) != 0;
}
u8 PXIReceiveByte(void)
{
return REG_PXI_BYTE_RECEIVED_FROM_REMOTE;
}
u32 PXIReceiveWord(void)
{
while(REG_PXI_CNT & CNT_RECEIVE_FIFO_EMPTY_STATUS);
return REG_PXI_RECV;
}
void PXIReceiveBuffer(u32 *buffer, u32 nbWords)
{
for(; nbWords > 0; nbWords--)
{
while(REG_PXI_CNT & CNT_RECEIVE_FIFO_EMPTY_STATUS);
*buffer++ = REG_PXI_RECV;
}
}
Result bindPXIInterrupts(Handle *syncInterrupt, Handle *receiveFIFONotEmptyInterrupt, Handle *sendFIFOEmptyInterrupt)
{
Result res = 0;
u32 mask = CNT_ENABLE_FIFOs | CNT_ENABLE_RECEIVE_FIFO_NOT_EMPTY_IRQ | CNT_ENABLE_SEND_FIFO_EMPTY_IRQ;
if(receiveFIFONotEmptyInterrupt != NULL)
{
res = svcBindInterrupt(0x53, *receiveFIFONotEmptyInterrupt, 0, false);
if(R_FAILED(res))
{
unbindPXIInterrupts(syncInterrupt, receiveFIFONotEmptyInterrupt, sendFIFOEmptyInterrupt);
return res;
}
REG_PXI_CNT = (REG_PXI_CNT & mask) | CNT_ENABLE_RECEIVE_FIFO_NOT_EMPTY_IRQ;
}
if(sendFIFOEmptyInterrupt != NULL)
{
res = svcBindInterrupt(0x52, *sendFIFOEmptyInterrupt, 0, false);
if(R_FAILED(res))
{
unbindPXIInterrupts(syncInterrupt, receiveFIFONotEmptyInterrupt, sendFIFOEmptyInterrupt);
return res;
}
REG_PXI_CNT = (REG_PXI_CNT & mask) | CNT_ENABLE_SEND_FIFO_EMPTY_IRQ;
}
if(syncInterrupt != NULL)
{
res = svcBindInterrupt(0x50, *syncInterrupt, 0, false);
if(R_FAILED(res))
{
unbindPXIInterrupts(syncInterrupt, receiveFIFONotEmptyInterrupt, sendFIFOEmptyInterrupt);
return res;
}
REG_PXI_INTERRUPT_CNT |= SYNC_ENABLE_SYNC11_IRQ;
}
return res;
}
void unbindPXIInterrupts(Handle *syncInterrupt, Handle *receiveFIFONotEmptyInterrupt, Handle *sendFIFOEmptyInterrupt)
{
if(receiveFIFONotEmptyInterrupt != NULL)
{
REG_PXI_CNT &= CNT_ENABLE_FIFOs | CNT_ENABLE_SEND_FIFO_EMPTY_IRQ;
svcUnbindInterrupt(0x53, *receiveFIFONotEmptyInterrupt);
}
if(sendFIFOEmptyInterrupt != NULL)
{
REG_PXI_CNT &= CNT_ENABLE_FIFOs | CNT_ENABLE_RECEIVE_FIFO_NOT_EMPTY_IRQ;
svcUnbindInterrupt(0x52, *sendFIFOEmptyInterrupt);
}
if(syncInterrupt != NULL)
{
REG_PXI_INTERRUPT_CNT &= ~SYNC_ENABLE_SYNC11_IRQ;
svcUnbindInterrupt(0x50, *syncInterrupt);
}
}