Improving LinkGPIO example and adding LinkGPIO::getSIInterrupts()

This commit is contained in:
Rodrigo Alfonso 2025-02-07 20:38:54 -03:00
parent 97bb7ca405
commit e7574ccd14
6 changed files with 80 additions and 45 deletions

View File

@ -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!

View File

@ -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";
}

View File

@ -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

View File

@ -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; }

View File

@ -44,4 +44,8 @@ void C_LinkGPIO_writePin(C_LinkGPIOHandle handle,
void C_LinkGPIO_setSIInterrupts(C_LinkGPIOHandle handle, bool isEnabled) {
static_cast<LinkGPIO*>(handle)->setSIInterrupts(isEnabled);
}
bool C_LinkGPIO_getSIInterrupts(C_LinkGPIOHandle handle) {
return static_cast<LinkGPIO*>(handle)->getSIInterrupts();
}
}

View File

@ -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;