feat(agb02): gpio reader sketch
This commit is contained in:
parent
81289eb5da
commit
f43db5224f
3 changed files with 160 additions and 0 deletions
|
@ -3,6 +3,7 @@
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
"${modulesPath}/installer/sd-card/sd-image-aarch64.nix"
|
"${modulesPath}/installer/sd-card/sd-image-aarch64.nix"
|
||||||
|
./users.nix
|
||||||
];
|
];
|
||||||
sdImage.compressImage = false;
|
sdImage.compressImage = false;
|
||||||
services = {
|
services = {
|
||||||
|
@ -13,5 +14,10 @@
|
||||||
networking.hostName = "agb02";
|
networking.hostName = "agb02";
|
||||||
networking.networkmanager.enable = true;
|
networking.networkmanager.enable = true;
|
||||||
|
|
||||||
|
environment.systemPackages = [
|
||||||
|
(pkgs.callPackage ./agb {})
|
||||||
|
pkgs.libgpiod
|
||||||
|
];
|
||||||
|
|
||||||
system.stateVersion = "24.11";
|
system.stateVersion = "24.11";
|
||||||
}
|
}
|
||||||
|
|
137
machines/agb02/agb/agb.cpp
Normal file
137
machines/agb02/agb/agb.cpp
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
#include <curlpp/cURLpp.hpp>
|
||||||
|
#include <gpiod.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
|
||||||
|
constexpr std::chrono::microseconds debounce = 40ms;
|
||||||
|
constexpr std::chrono::microseconds poll_period = 50ms;
|
||||||
|
|
||||||
|
constexpr std::pair<double, double> joystick_movement(1.0, 1.0);
|
||||||
|
|
||||||
|
const gpiod::line::offsets drive_down = { 21, 13, 6 };
|
||||||
|
|
||||||
|
const gpiod::line::offsets decoder = { 0, 0, 0, 0, 0, 0, 0, 0 }; // lsbf
|
||||||
|
const gpiod::line::offsets joystick = { 0, 0, 0, 0 }; // x+, y+, x-, y-
|
||||||
|
const gpiod::line::offset black_button = 0;
|
||||||
|
const gpiod::line::offset white_button = 0;
|
||||||
|
|
||||||
|
const gpiod::line_settings input_settings =
|
||||||
|
gpiod::line_settings()
|
||||||
|
.set_direction(gpiod::line::direction::INPUT)
|
||||||
|
.set_bias(gpiod::line::bias::PULL_UP)
|
||||||
|
.set_active_low(true)
|
||||||
|
.set_debounce_period(debounce);
|
||||||
|
|
||||||
|
// thanks to https://en.wikipedia.org/wiki/Gray_code#Converting_to_and_from_Gray_code
|
||||||
|
inline uint8_t gray_to_binary(uint8_t num)
|
||||||
|
{
|
||||||
|
num ^= num >> 4;
|
||||||
|
num ^= num >> 2;
|
||||||
|
num ^= num >> 1;
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t read_decoder_realpos(gpiod::line_request& line_reader){
|
||||||
|
static gpiod::line::values decoder_read(8);
|
||||||
|
line_reader.get_values(decoder, decoder_read);
|
||||||
|
uint8_t graycode = 0;
|
||||||
|
for(uint8_t i = 0; i < 8; ++i) graycode |= uint8_t(decoder_read[i]) << i;
|
||||||
|
return gray_to_binary(graycode);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void clamp_decoder(uint8_t& decoder, int move){
|
||||||
|
decoder = uint8_t(std::clamp(decoder + move, 0, 255));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(const int argc, char const* const* const argv) {
|
||||||
|
if(argc < 2)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/// init gpio chip ///
|
||||||
|
|
||||||
|
gpiod::chip chip(argv[1]);
|
||||||
|
gpiod::line_request line_reader =
|
||||||
|
chip.prepare_request()
|
||||||
|
.set_consumer("AGB")
|
||||||
|
.add_line_settings(drive_down,
|
||||||
|
gpiod::line_settings()
|
||||||
|
.set_direction(gpiod::line::direction::OUTPUT)
|
||||||
|
.set_drive(gpiod::line::drive::OPEN_DRAIN)
|
||||||
|
.set_output_value(gpiod::line::value::INACTIVE)
|
||||||
|
)
|
||||||
|
.add_line_settings({ black_button, white_button }, input_settings)
|
||||||
|
.add_line_settings(joystick, input_settings)
|
||||||
|
.add_line_settings(decoder, input_settings)
|
||||||
|
.do_request();
|
||||||
|
|
||||||
|
// let the settings apply
|
||||||
|
std::this_thread::sleep_for(poll_period);
|
||||||
|
|
||||||
|
/// init server communication ///
|
||||||
|
|
||||||
|
cURLpp::initialize();
|
||||||
|
|
||||||
|
/// internal state ///
|
||||||
|
|
||||||
|
gpiod::line::values joystick_read(4);
|
||||||
|
std::pair<double, double> spot_pos(0.0, 0.0); //TODO: init from server
|
||||||
|
|
||||||
|
uint8_t decoder_pos = 0; //TODO: init from server
|
||||||
|
uint8_t decoder_realpos = read_decoder_realpos(line_reader);
|
||||||
|
|
||||||
|
bool white_pressed = false;
|
||||||
|
bool black_pressed = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for(;;){
|
||||||
|
std::this_thread::sleep_for(poll_period);
|
||||||
|
|
||||||
|
/// joystick ///
|
||||||
|
line_reader.get_values(joystick, joystick_read);
|
||||||
|
|
||||||
|
if(bool(joystick_read[0])) spot_pos.first += joystick_movement.first;
|
||||||
|
if(bool(joystick_read[1])) spot_pos.second += joystick_movement.second;
|
||||||
|
if(bool(joystick_read[2])) spot_pos.first -= joystick_movement.first;
|
||||||
|
if(bool(joystick_read[3])) spot_pos.second -= joystick_movement.second;
|
||||||
|
|
||||||
|
if (bool(joystick_read[0]) || bool(joystick_read[1])
|
||||||
|
|| bool(joystick_read[2]) || bool(joystick_read[3]))
|
||||||
|
; //TODO: send to server
|
||||||
|
|
||||||
|
/// Buttons ///
|
||||||
|
bool pressed = bool(line_reader.get_value(black_button));
|
||||||
|
if(pressed ^ black_pressed)
|
||||||
|
; //TODO: send to server
|
||||||
|
black_pressed = pressed;
|
||||||
|
|
||||||
|
pressed = bool(line_reader.get_value(white_button));
|
||||||
|
if(pressed ^ white_pressed)
|
||||||
|
; //TODO: send to server
|
||||||
|
white_pressed = pressed;
|
||||||
|
|
||||||
|
/// decoder ///
|
||||||
|
uint8_t new_realpos = read_decoder_realpos(line_reader);
|
||||||
|
uint8_t seen_travel = std::abs(int(new_realpos) - int(decoder_realpos));
|
||||||
|
|
||||||
|
//TODO: check CW and CCW
|
||||||
|
|
||||||
|
// CW
|
||||||
|
if(seen_travel < 50 && new_realpos < decoder_realpos)
|
||||||
|
clamp_decoder(decoder_pos, seen_travel);
|
||||||
|
if(seen_travel >= 50 && new_realpos > decoder_realpos)
|
||||||
|
clamp_decoder(decoder_pos, 256 - seen_travel);
|
||||||
|
|
||||||
|
// CCW
|
||||||
|
if(seen_travel < 50 && new_realpos > decoder_realpos)
|
||||||
|
clamp_decoder(decoder_pos, -seen_travel);
|
||||||
|
if(seen_travel >= 50 && new_realpos < decoder_realpos)
|
||||||
|
clamp_decoder(decoder_pos, seen_travel - 256);
|
||||||
|
|
||||||
|
if(seen_travel)
|
||||||
|
; //TODO: send to server
|
||||||
|
}
|
||||||
|
}
|
17
machines/agb02/agb/default.nix
Normal file
17
machines/agb02/agb/default.nix
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{ stdenv, libgpiod, curlpp, curl }:
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "agb";
|
||||||
|
version = "oct-24";
|
||||||
|
src = ./.;
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
g++ --std=c++23 agb.cpp -o agb \
|
||||||
|
-L${libgpiod}/lib -lgpiodcxx -I${libgpiod}/include \
|
||||||
|
-L${curl.out}/lib -lcurl -I${curl.dev}/include \
|
||||||
|
-L${curlpp}/lib -lcurlpp -I${curlpp}/include
|
||||||
|
'';
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
cp agb $out/bin
|
||||||
|
'';
|
||||||
|
}
|
Loading…
Reference in a new issue