diff --git a/README.md b/README.md index 7f4f814..76aa9e2 100644 --- a/README.md +++ b/README.md @@ -507,6 +507,7 @@ _(aka General Purpose Mode)_ | `readPin(pin)` | **bool** | Returns whether a `pin` is _HIGH_ or not (when set as an input). | | `writePin(pin, isHigh)` | - | Sets a `pin` to be high or not (when set as an output). | | `setSIInterrupts(isEnabled)` | - | If it `isEnabled`, an IRQ will be generated when `SI` changes from _HIGH_ to _LOW_. | +| `getSIInterrupts()` | **bool** | Returns whether SI-falling interrupts are enabled or not. | ⚠️ always set the `SI` terminal to an input! diff --git a/examples/LinkGPIO_demo/src/main.cpp b/examples/LinkGPIO_demo/src/main.cpp index 198f7f3..297087e 100644 --- a/examples/LinkGPIO_demo/src/main.cpp +++ b/examples/LinkGPIO_demo/src/main.cpp @@ -5,16 +5,22 @@ #include "../../_lib/interrupt.h" std::string mode(std::string name, LinkGPIO::Pin pin); -std::string value(std::string name, LinkGPIO::Pin pin, bool isHigh); +std::string value(std::string name, LinkGPIO::Pin pin); // (1) Create a LinkGPIO instance LinkGPIO* linkGPIO = new LinkGPIO(); +static vu32 irqCount = 0; +void SERIAL() { + irqCount++; +} + void init() { Common::initTTE(); interrupt_init(); interrupt_add(INTR_VBLANK, []() {}); + interrupt_add(INTR_SERIAL, SERIAL); // (2) Initialize the library linkGPIO->reset(); @@ -23,58 +29,77 @@ void init() { int main() { init(); + bool left = false, up = false, right = false, down = false; + bool start = false, select = false; + while (true) { // (3) Use the pins std::string output = "LinkGPIO_demo (v8.0.0)\n\n"; // Commands u16 keys = ~REG_KEYS & KEY_ANY; - bool setSOOutput = keys & KEY_L; - bool setSDOutput = keys & KEY_UP; - bool setSCOutput = keys & KEY_R; - bool setSOInput = keys & KEY_LEFT; - bool setSDInput = keys & KEY_DOWN; - bool setSCInput = keys & KEY_RIGHT; - bool sendSOHigh = keys & KEY_B; - bool sendSDHigh = keys & KEY_START; - bool sendSCHigh = keys & KEY_A; - // Modes + // (3) Set modes + if (Common::didPress(KEY_LEFT, left)) + linkGPIO->setMode( + LinkGPIO::Pin::SI, + (LinkGPIO::Direction)((int)linkGPIO->getMode(LinkGPIO::Pin::SI) + 1)); + if (Common::didPress(KEY_UP, up)) + linkGPIO->setMode( + LinkGPIO::Pin::SD, + (LinkGPIO::Direction)((int)linkGPIO->getMode(LinkGPIO::Pin::SD) + 1)); + if (Common::didPress(KEY_DOWN, down)) + linkGPIO->setMode( + LinkGPIO::Pin::SC, + (LinkGPIO::Direction)((int)linkGPIO->getMode(LinkGPIO::Pin::SC) + 1)); + if (Common::didPress(KEY_RIGHT, right)) + linkGPIO->setMode( + LinkGPIO::Pin::SO, + (LinkGPIO::Direction)((int)linkGPIO->getMode(LinkGPIO::Pin::SO) + 1)); + + // (3) Write pins + if (linkGPIO->getMode(LinkGPIO::Pin::SI) == LinkGPIO::Direction::OUTPUT) + linkGPIO->writePin(LinkGPIO::Pin::SI, keys & KEY_L); + if (linkGPIO->getMode(LinkGPIO::Pin::SO) == LinkGPIO::Direction::OUTPUT) + linkGPIO->writePin(LinkGPIO::Pin::SO, keys & KEY_R); + if (linkGPIO->getMode(LinkGPIO::Pin::SD) == LinkGPIO::Direction::OUTPUT) + linkGPIO->writePin(LinkGPIO::Pin::SD, keys & KEY_B); + if (linkGPIO->getMode(LinkGPIO::Pin::SC) == LinkGPIO::Direction::OUTPUT) + linkGPIO->writePin(LinkGPIO::Pin::SC, keys & KEY_A); + + // (4) Subscribe to SI falling + if (Common::didPress(KEY_START, start)) + linkGPIO->setSIInterrupts(!linkGPIO->getSIInterrupts()); + if (Common::didPress(KEY_SELECT, select)) + irqCount = 0; + + // Print modes output += mode("SI", LinkGPIO::Pin::SI); output += mode("SO", LinkGPIO::Pin::SO); output += mode("SD", LinkGPIO::Pin::SD); output += mode("SC", LinkGPIO::Pin::SC); - // Separator + // Print separator output += "\n---\n\n"; - // Values - output += value("SI", LinkGPIO::Pin::SI, false); - output += value("SO", LinkGPIO::Pin::SO, sendSOHigh); - output += value("SD", LinkGPIO::Pin::SD, sendSDHigh); - output += value("SC", LinkGPIO::Pin::SC, sendSCHigh); + // Print values + output += value("SI", LinkGPIO::Pin::SI); + output += value("SO", LinkGPIO::Pin::SO); + output += value("SD", LinkGPIO::Pin::SD); + output += value("SC", LinkGPIO::Pin::SC); - // Set modes - if (setSOOutput) - linkGPIO->setMode(LinkGPIO::Pin::SO, LinkGPIO::Direction::OUTPUT); - if (setSDOutput) - linkGPIO->setMode(LinkGPIO::Pin::SD, LinkGPIO::Direction::OUTPUT); - if (setSCOutput) - linkGPIO->setMode(LinkGPIO::Pin::SC, LinkGPIO::Direction::OUTPUT); - if (setSOInput) - linkGPIO->setMode(LinkGPIO::Pin::SO, LinkGPIO::Direction::INPUT); - if (setSDInput) - linkGPIO->setMode(LinkGPIO::Pin::SD, LinkGPIO::Direction::INPUT); - if (setSCInput) - linkGPIO->setMode(LinkGPIO::Pin::SC, LinkGPIO::Direction::INPUT); + // Print interrupts + if (linkGPIO->getMode(LinkGPIO::Pin::SI) == LinkGPIO::Direction::INPUT) + output += + "\nSI IRQ: " + std::to_string(linkGPIO->getSIInterrupts()) + + (irqCount > 0 + ? " !!!" + (irqCount > 1 ? " (x" + std::to_string(irqCount) + ")" + : "") + : ""); - // Set values - if (linkGPIO->getMode(LinkGPIO::Pin::SO) == LinkGPIO::Direction::OUTPUT) - linkGPIO->writePin(LinkGPIO::Pin::SO, sendSOHigh); - if (linkGPIO->getMode(LinkGPIO::Pin::SD) == LinkGPIO::Direction::OUTPUT) - linkGPIO->writePin(LinkGPIO::Pin::SD, sendSDHigh); - if (linkGPIO->getMode(LinkGPIO::Pin::SC) == LinkGPIO::Direction::OUTPUT) - linkGPIO->writePin(LinkGPIO::Pin::SC, sendSCHigh); + output += + "\n\n---\nUse the D-PAD to change modes\nUse the buttons to set " + "values\nUse STA/SEL to toggle SI IRQ"; // Print VBlankIntrWait(); @@ -90,10 +115,9 @@ std::string mode(std::string name, LinkGPIO::Pin pin) { : "INPUT\n"); } -std::string value(std::string name, LinkGPIO::Pin pin, bool isHigh) { +std::string value(std::string name, LinkGPIO::Pin pin) { auto title = name + ": "; - return linkGPIO->getMode(pin) == LinkGPIO::Direction::INPUT - ? "< " + title + std::to_string(linkGPIO->readPin(pin)) + "\n" - : "> " + title + std::to_string(isHigh) + "\n"; + return (linkGPIO->getMode(pin) == LinkGPIO::Direction::INPUT ? "< " : "> ") + + title + std::to_string(linkGPIO->readPin(pin)) + "\n"; } diff --git a/examples/LinkPS2Keyboard_demo/src/main.cpp b/examples/LinkPS2Keyboard_demo/src/main.cpp index d54aca8..3895667 100644 --- a/examples/LinkPS2Keyboard_demo/src/main.cpp +++ b/examples/LinkPS2Keyboard_demo/src/main.cpp @@ -6,10 +6,10 @@ static std::string scanCodes = ""; static std::string output = ""; -static u32 irqs = 0; +static vu32 irqCount = 0; void SERIAL() { LINK_PS2_KEYBOARD_ISR_SERIAL(); - irqs++; + irqCount++; } // (1) Create a LinkPS2Keyboard instance @@ -49,9 +49,9 @@ int main() { } else { if (keys & KEY_B) { scanCodes = ""; - irqs = 0; + irqCount = 0; } - output += std::to_string(irqs) + " - " + scanCodes; + output += std::to_string(irqCount) + " - " + scanCodes; } // Print diff --git a/lib/LinkGPIO.hpp b/lib/LinkGPIO.hpp index 550497e..aaad60e 100644 --- a/lib/LinkGPIO.hpp +++ b/lib/LinkGPIO.hpp @@ -107,6 +107,11 @@ class LinkGPIO { setBit(Link::_REG_RCNT, BIT_SI_INTERRUPT, isEnabled); } + /** + * @brief Returns whether SI-falling interrupts are enabled or not. + */ + bool getSIInterrupts() { return getBit(Link::_REG_RCNT, BIT_SI_INTERRUPT); } + private: int getBit(u16 reg, int bit) { return (reg >> bit) & 1; } diff --git a/lib/c_bindings/C_LinkGPIO.cpp b/lib/c_bindings/C_LinkGPIO.cpp index 545358b..44aa32b 100644 --- a/lib/c_bindings/C_LinkGPIO.cpp +++ b/lib/c_bindings/C_LinkGPIO.cpp @@ -44,4 +44,8 @@ void C_LinkGPIO_writePin(C_LinkGPIOHandle handle, void C_LinkGPIO_setSIInterrupts(C_LinkGPIOHandle handle, bool isEnabled) { static_cast(handle)->setSIInterrupts(isEnabled); } + +bool C_LinkGPIO_getSIInterrupts(C_LinkGPIOHandle handle) { + return static_cast(handle)->getSIInterrupts(); +} } diff --git a/lib/c_bindings/C_LinkGPIO.h b/lib/c_bindings/C_LinkGPIO.h index 2afd919..70635f1 100644 --- a/lib/c_bindings/C_LinkGPIO.h +++ b/lib/c_bindings/C_LinkGPIO.h @@ -37,6 +37,7 @@ void C_LinkGPIO_writePin(C_LinkGPIOHandle handle, bool isHigh); void C_LinkGPIO_setSIInterrupts(C_LinkGPIOHandle handle, bool isEnabled); +bool C_LinkGPIO_getSIInterrupts(C_LinkGPIOHandle handle); extern C_LinkGPIOHandle cLinkGPIO;