src/ds/ipc.c (view raw)
1/* Copyright (c) 2013-2017 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include <mgba/internal/ds/ipc.h>
7
8#include <mgba/internal/ds/ds.h>
9#include <mgba/internal/ds/io.h>
10
11void DSIPCWriteSYNC(struct ARMCore* remoteCpu, uint16_t* remoteIo, int16_t value) {
12 remoteIo[DS_REG_IPCSYNC >> 1] &= 0xFFF0;
13 remoteIo[DS_REG_IPCSYNC >> 1] |= (value >> 8) & 0x0F;
14 if (value & 0x2000 && remoteIo[DS_REG_IPCSYNC >> 1] & 0x4000) {
15 mLOG(DS_IO, STUB, "Unimplemented IPC IRQ");
16 UNUSED(remoteCpu);
17 }
18}
19
20int16_t DSIPCWriteFIFOCNT(struct DSCommon* dscore, int16_t value) {
21 value &= 0xC40C;
22 int16_t oldValue = dscore->memory.io[DS_REG_IPCFIFOCNT >> 1] & 0x4303;
23 int16_t newValue = value | oldValue;
24 // TODO: Does Enable set enabled on both ends?
25 if (DSIPCFIFOCNTIsError(value)) {
26 newValue = DSIPCFIFOCNTClearError(newValue);
27 }
28 if (DSIPCFIFOCNTIsSendClear(newValue)) {
29 CircleBufferClear(&dscore->ipc->fifo);
30 dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTFillRecvEmpty(dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1]);
31 newValue = DSIPCFIFOCNTFillSendEmpty(newValue);
32 newValue = DSIPCFIFOCNTClearSendClear(newValue);
33 }
34 return newValue;
35}
36
37void DSIPCWriteFIFO(struct DSCommon* dscore, int32_t value) {
38 if (!DSIPCFIFOCNTIsEnable(dscore->memory.io[DS_REG_IPCFIFOCNT >> 1])) {
39 return;
40 }
41 CircleBufferWrite32(&dscore->ipc->fifo, value);
42 size_t fullness = CircleBufferSize(&dscore->ipc->fifo);
43 if (fullness == 4) {
44 dscore->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTClearSendEmpty(dscore->memory.io[DS_REG_IPCFIFOCNT >> 1]);
45 dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTClearRecvEmpty(dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1]);
46 if (DSIPCFIFOCNTIsRecvIRQ(dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1])) {
47 // TODO: Adaptive time slicing?
48 DSRaiseIRQ(dscore->ipc->cpu, dscore->ipc->memory.io, DS_IRQ_IPC_NOT_EMPTY);
49 }
50 } else if (fullness == 64) {
51 dscore->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTFillSendFull(dscore->memory.io[DS_REG_IPCFIFOCNT >> 1]);
52 dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTFillRecvFull(dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1]);
53 }
54}
55
56int32_t DSIPCReadFIFO(struct DSCommon* dscore) {
57 if (!DSIPCFIFOCNTIsEnable(dscore->memory.io[DS_REG_IPCFIFOCNT >> 1])) {
58 return 0;
59 }
60 int32_t value = ((int32_t*) dscore->ipc->memory.io)[DS_REG_IPCFIFOSEND_LO >> 2]; // TODO: actual last value
61 CircleBufferRead32(&dscore->fifo, &value);
62 size_t fullness = CircleBufferSize(&dscore->fifo);
63 dscore->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTClearRecvFull(dscore->memory.io[DS_REG_IPCFIFOCNT >> 1]);
64 dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTClearSendFull(dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1]);
65 if (fullness == 0) {
66 dscore->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTFillRecvEmpty(dscore->memory.io[DS_REG_IPCFIFOCNT >> 1]);
67 dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1] = DSIPCFIFOCNTFillSendEmpty(dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1]);
68 if (DSIPCFIFOCNTIsSendIRQ(dscore->ipc->memory.io[DS_REG_IPCFIFOCNT >> 1])) {
69 // TODO: Adaptive time slicing?
70 DSRaiseIRQ(dscore->ipc->cpu, dscore->ipc->memory.io, DS_IRQ_IPC_NOT_EMPTY);
71 }
72 }
73 return value;
74}