Add D-pad peripheral
ADD
src/io/iodpad.cpp
+#include "iodpad.h"
+#include "ioregistry.h"
+
+#include <QGridLayout>
+#include <QKeyEvent>
+#include <QPainter>
+#include <QPen>
+#include <QToolButton>
+
+namespace Ripes {
+
+IODPad::IODPad(QWidget* parent) : IOBase(IOType::DPAD, parent) {
+ for (unsigned i = 0; i < DIRECTIONS; i++) {
+ QString name;
+ Qt::ArrowType arrow;
+ switch (i) {
+ case UP:
+ name = "UP";
+ arrow = Qt::UpArrow;
+ break;
+ case DOWN:
+ name = "DOWN";
+ arrow = Qt::DownArrow;
+ break;
+ case LEFT:
+ name = "LEFT";
+ arrow = Qt::LeftArrow;
+ break;
+ case RIGHT:
+ name = "RIGHT";
+ arrow = Qt::RightArrow;
+ break;
+ }
+ auto* button = new QToolButton();
+ m_buttons[static_cast<IdxToDir>(i)] = button;
+ button->setArrowType(arrow);
+
+ m_regDescs.push_back(RegDesc{name, RegDesc::RW::R, 1, i * 4});
+ }
+
+ auto* gridLayout = new QGridLayout();
+ gridLayout->addWidget(m_buttons[UP], 0, 1);
+ gridLayout->addWidget(m_buttons[DOWN], 2, 1);
+ gridLayout->addWidget(m_buttons[LEFT], 1, 0);
+ gridLayout->addWidget(m_buttons[RIGHT], 1, 2);
+
+ setLayout(gridLayout);
+}
+
+uint32_t IODPad::size() const {
+ return 4 * 4;
+}
+
+void IODPad::keyPressEvent(QKeyEvent* e) {
+ switch (e->key()) {
+ case Qt::Key_A:
+ m_buttons.at(LEFT)->setDown(true);
+ return;
+ case Qt::Key_D:
+ m_buttons.at(RIGHT)->setDown(true);
+ return;
+ case Qt::Key_W:
+ m_buttons.at(UP)->setDown(true);
+ return;
+ case Qt::Key_S:
+ m_buttons.at(DOWN)->setDown(true);
+ return;
+ }
+ IOBase::keyPressEvent(e);
+}
+void IODPad::keyReleaseEvent(QKeyEvent* e) {
+ switch (e->key()) {
+ case Qt::Key_A:
+ m_buttons.at(LEFT)->setDown(false);
+ return;
+ case Qt::Key_D:
+ m_buttons.at(RIGHT)->setDown(false);
+ return;
+ case Qt::Key_W:
+ m_buttons.at(UP)->setDown(false);
+ return;
+ case Qt::Key_S:
+ m_buttons.at(DOWN)->setDown(false);
+ return;
+ }
+ IOBase::keyReleaseEvent(e);
+}
+
+QString IODPad::description() const {
+ QStringList desc;
+ desc << "Each button maps to a 32-bit register, with the least-significant bit indicating the state of the "
+ "button.\n";
+ desc << "If the D-pad window is in focus, the buttons may be pressed using the \"WASD\" keys of the keyboard.";
+
+ return desc.join('\n');
+}
+
+uint32_t IODPad::ioRead(uint32_t offset, unsigned) {
+ switch (offset) {
+ case LEFT * 4: {
+ return m_buttons.at(LEFT)->isDown();
+ }
+ case RIGHT * 4: {
+ return m_buttons.at(RIGHT)->isDown();
+ }
+ case UP * 4: {
+ return m_buttons.at(UP)->isDown();
+ }
+ case DOWN * 4: {
+ return m_buttons.at(DOWN)->isDown();
+ }
+ }
+ return 0;
+}
+
+void IODPad::ioWrite(uint32_t, uint32_t, unsigned) {
+ // Write-only
+}
+
+} // namespace Ripes

ADD
src/io/iodpad.h
+#pragma once
+
+#include <QPen>
+#include <QVariant>
+#include <QWidget>
+
+QT_FORWARD_DECLARE_CLASS(QAbstractButton);
+
+#include "iobase.h"
+
+namespace Ripes {
+
+class IODPad : public IOBase {
+ Q_OBJECT
+
+ enum IdxToDir { UP, DOWN, LEFT, RIGHT, DIRECTIONS };
+
+public:
+ IODPad(QWidget* parent);
+ ~IODPad() { unregister(); };
+
+ virtual uint32_t size() const override;
+ virtual QString description() const override;
+ virtual QString baseName() const override { return "D-Pad"; };
+
+ virtual const std::vector<RegDesc>& registers() const override { return m_regDescs; };
+
+ /**
+ * Hardware read/write functions
+ */
+ virtual uint32_t ioRead(uint32_t offset, unsigned size) override;
+ virtual void ioWrite(uint32_t offset, uint32_t value, unsigned size) override;
+
+protected:
+ virtual void parameterChanged(unsigned) override{/* no parameters */};
+ void keyPressEvent(QKeyEvent* e) override;
+ void keyReleaseEvent(QKeyEvent* e) override;
+
+private:
+ unsigned m_maxSideWidth = 256;
+ std::vector<uint32_t> m_ledRegs;
+ std::vector<RegDesc> m_regDescs;
+ std::map<IdxToDir, QAbstractButton*> m_buttons;
+};
+} // namespace Ripes

MODIFY
src/io/ioregistry.h
src/io/ioregistry.h
#include <QWidget>
#include "iobase.h"
+#include "iodpad.h"
#include "ioledmatrix.h"
#include "ioswitches.h"
namespace Ripes {
-enum class IOType { LED_MATRIX, SWITCHES };
+enum class IOType { LED_MATRIX, SWITCHES, DPAD };
template <typename T>
IOBase* createIO(QWidget* parent) {
@@ -28,9 +29,11 @@ IOBase* createIO(QWidget* parent) {
using IOFactory = std::function<IOBase*(QWidget* parent)>;
const static std::map<IOType, QString> IOTypeTitles = {{IOType::LED_MATRIX, "LED Matrix"},
- {IOType::SWITCHES, "Switches"}};
+ {IOType::SWITCHES, "Switches"},
+ {IOType::DPAD, "D-Pad"}};
const static std::map<IOType, IOFactory> IOFactories = {{IOType::LED_MATRIX, createIO<IOLedMatrix>},
- {IOType::SWITCHES, createIO<IOSwitches>}};
+ {IOType::SWITCHES, createIO<IOSwitches>},
+ {IOType::DPAD, createIO<IODPad>}};
} // namespace Ripes

Add D-pad peripheral