Init
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
// This file is part of Necroware's GamePort adapter firmware.
|
||||
// Copyright (C) 2021 Necroware
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DigitalPin.h"
|
||||
#include "Joystick.h"
|
||||
|
||||
/// Class to communicate with Gravis joysticks using GrIP.
|
||||
/// @remark This is a green field implementation, but it was heavily
|
||||
/// inspired by Linux Gravis/Kensington GrIP driver
|
||||
/// implementation. See
|
||||
class GrIP : public Joystick {
|
||||
/// https://github.com/torvalds/linux/blob/master/drivers/input/joystick/grip.c
|
||||
public:
|
||||
/// Resets the joystick and tries to detect the model.
|
||||
bool init() override {
|
||||
while (!readPacket())
|
||||
;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Reads the joystick state.
|
||||
/// @returns the state of axis, buttons etc.
|
||||
/// @remark if reading the state fails, the last known state is
|
||||
/// returned and the joystick reset is executed.
|
||||
bool update() override {
|
||||
|
||||
const auto packet = readPacket();
|
||||
if (packet == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto getBit = [&](uint8_t pos) { return uint8_t(packet >> pos) & 1; };
|
||||
|
||||
m_state.axes[0] = map(1 + getBit(15) - getBit(16), 0, 2, 0, 1023);
|
||||
m_state.axes[1] = map(1 + getBit(13) - getBit(12), 0, 2, 0, 1023);
|
||||
|
||||
m_state.buttons = getBit(8);
|
||||
m_state.buttons |= getBit(3) << 1;
|
||||
m_state.buttons |= getBit(7) << 2;
|
||||
m_state.buttons |= getBit(6) << 3;
|
||||
m_state.buttons |= getBit(10) << 4;
|
||||
m_state.buttons |= getBit(11) << 5;
|
||||
m_state.buttons |= getBit(5) << 6;
|
||||
m_state.buttons |= getBit(2) << 7;
|
||||
m_state.buttons |= getBit(0) << 8;
|
||||
m_state.buttons |= getBit(1) << 9;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const State &getState() const override {
|
||||
return m_state;
|
||||
}
|
||||
|
||||
const Description &getDescription() const override {
|
||||
static Description desc{"Gravis GamePad Pro", 2, 10, 0};
|
||||
return desc;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Supported Gravis model types.
|
||||
///
|
||||
/// @remark currently only GamePad Pro is supported and
|
||||
// this enum is not used yet
|
||||
enum class Model {
|
||||
|
||||
/// Unknown model
|
||||
GRIP_UNKNOWN,
|
||||
|
||||
/// GamePad Pro
|
||||
GRIP_GAMEPAD_PRO,
|
||||
};
|
||||
|
||||
DigitalInput<GamePort<2>::pin, true> m_clock;
|
||||
DigitalInput<GamePort<7>::pin, true> m_data;
|
||||
State m_state;
|
||||
|
||||
/// Read bits packet from the joystick.
|
||||
uint32_t readPacket() const {
|
||||
|
||||
// Gravis GamePad Pro sends 24 bits long packages of data all the
|
||||
// time. Every package starts with a binary tag sequence 011111.
|
||||
|
||||
static const auto length = 24u;
|
||||
uint32_t result = 0u;
|
||||
|
||||
// read a package of 24 bits
|
||||
for (auto i = 0u; i < length; i++) {
|
||||
if (!m_clock.wait(Edge::falling, 100)) {
|
||||
return 0u;
|
||||
}
|
||||
result |= uint32_t(m_data.isHigh()) << i;
|
||||
}
|
||||
|
||||
// alighn the bits to have the binary tag in front. This code
|
||||
// was taken almost unchanged from the linux kernel.
|
||||
for (auto i = 0u; i < length; i++) {
|
||||
result = (result >> 1) | (result & 1) << (length - 1u);
|
||||
if ((result & 0xfe4210) == 0x7c0000) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return 0u;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user