Compare commits
No commits in common. "60da6c131aa4115b5a0d72b0441285feced4169a" and "4eff7eb2772fe0158b2488593c7e71bb234e01c6" have entirely different histories.
60da6c131a
...
4eff7eb277
26
Makefile
26
Makefile
|
@ -22,31 +22,22 @@ libs: $(BUILD_DIR)/hid.o
|
||||||
# Flags and autodetection
|
# Flags and autodetection
|
||||||
|
|
||||||
# -MMD and -MP generate makefiles with extension .d.
|
# -MMD and -MP generate makefiles with extension .d.
|
||||||
CPPFLAGS := -MMD -MP \
|
CPPFLAGS := -Wall -MMD -MP -I src -I libs/hidapi/hidapi
|
||||||
-Wall \
|
|
||||||
-I src \
|
|
||||||
-I libs/hidapi/hidapi
|
|
||||||
|
|
||||||
# udev: required by hidapi
|
|
||||||
LDFLAGS := -l fftw3 -l udev
|
LDFLAGS := -l fftw3 -l udev
|
||||||
|
|
||||||
# Find all cpp files in source dirs
|
# Find all cpp files in source dirs
|
||||||
SRCS := $(shell find $(SRC_DIRS) -name '*.cpp')
|
SRCS := $(shell find $(SRC_DIRS) -name '*.cpp')
|
||||||
# Turns src/a.cpp into build/src/a.cpp.o
|
# Turns ./build/a.cpp into ./build/a.cpp.o
|
||||||
SRC_OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
|
OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
|
||||||
LIB_OBJS := $(BUILD_DIR)/hid.o
|
LIB_OBJS := $(BUILD_DIR)/hid.o
|
||||||
OBJS = $(SRC_OBJS) $(LIB_OBJS)
|
# Turns ./build/a.cpp.o into ./build/a.cpp.d
|
||||||
# Turns build/a.cpp.o into build/a.cpp.d
|
|
||||||
DEPS := $(OBJS:.o=.d)
|
DEPS := $(OBJS:.o=.d)
|
||||||
|
|
||||||
#################################################
|
#################################################
|
||||||
# Build targets
|
# Build targets
|
||||||
|
|
||||||
|
|
||||||
### Libraries
|
|
||||||
|
|
||||||
# Build hidapi
|
|
||||||
HIDAPI_PATH := libs/hidapi
|
HIDAPI_PATH := libs/hidapi
|
||||||
|
# Build hidapi
|
||||||
$(BUILD_DIR)/hid.o:
|
$(BUILD_DIR)/hid.o:
|
||||||
@mkdir -p $(BUILD_DIR)
|
@mkdir -p $(BUILD_DIR)
|
||||||
|
|
||||||
|
@ -58,18 +49,15 @@ $(BUILD_DIR)/hid.o:
|
||||||
$(HIDAPI_PATH)/linux/hid.c \
|
$(HIDAPI_PATH)/linux/hid.c \
|
||||||
-o $(BUILD_DIR)/hid.o
|
-o $(BUILD_DIR)/hid.o
|
||||||
|
|
||||||
|
|
||||||
### Source
|
|
||||||
|
|
||||||
# C++ build step
|
# C++ build step
|
||||||
$(BUILD_DIR)/%.cpp.o: %.cpp
|
$(BUILD_DIR)/%.cpp.o: %.cpp $(BUILD_DIR)/hid.o
|
||||||
mkdir -p $(dir $@)
|
mkdir -p $(dir $@)
|
||||||
g++ $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
|
g++ $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
|
||||||
# Final build step
|
# Final build step
|
||||||
$(TARGET_EXEC) : $(OBJS)
|
$(TARGET_EXEC) : $(OBJS)
|
||||||
g++ $(OBJS) -o $@ $(LDFLAGS)
|
g++ $(OBJS) $(LIB_OBJS) -o $@ $(LDFLAGS)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
118
src/ergodox.cpp
118
src/ergodox.cpp
|
@ -1,118 +0,0 @@
|
||||||
#include "ergodox.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Ergodox::Ergodox(
|
|
||||||
unsigned short vendor_id,
|
|
||||||
unsigned short product_id,
|
|
||||||
unsigned short usage,
|
|
||||||
unsigned short usage_page
|
|
||||||
) :
|
|
||||||
vendor_id(vendor_id),
|
|
||||||
product_id(product_id),
|
|
||||||
usage(usage),
|
|
||||||
usage_page(usage_page),
|
|
||||||
handle(NULL)
|
|
||||||
{
|
|
||||||
hid_init();
|
|
||||||
open();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Initialize Ergodox interface.
|
|
||||||
|
|
||||||
Should be called once at start of execution. Arguments are the USB parameters of the keyboard.
|
|
||||||
|
|
||||||
Returns instance of singleton.
|
|
||||||
*/
|
|
||||||
Ergodox& Ergodox::init(
|
|
||||||
unsigned short vendor_id,
|
|
||||||
unsigned short product_id,
|
|
||||||
unsigned short usage,
|
|
||||||
unsigned short usage_page
|
|
||||||
) {
|
|
||||||
static bool has_been_initialized = false;
|
|
||||||
static Ergodox Instance(
|
|
||||||
vendor_id,
|
|
||||||
product_id,
|
|
||||||
usage,
|
|
||||||
usage_page
|
|
||||||
);
|
|
||||||
|
|
||||||
// This isn't strictly necessary, but there is no reason
|
|
||||||
// to call init() twice.
|
|
||||||
if (has_been_initialized) {
|
|
||||||
has_been_initialized = true;
|
|
||||||
throw std::runtime_error("Ergodox has already been initialized!");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ergodox::~Ergodox() {
|
|
||||||
close();
|
|
||||||
hid_exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Try to open this keyboard's hid device.
|
|
||||||
Throws a runtime error if device is already open,
|
|
||||||
or if we can't find a device with the given params.
|
|
||||||
*/
|
|
||||||
void Ergodox::open() {
|
|
||||||
if (handle != NULL) {
|
|
||||||
throw std::runtime_error("Device already open");
|
|
||||||
}
|
|
||||||
|
|
||||||
struct hid_device_info *devs, *cur_dev;
|
|
||||||
const char *path_to_open = NULL;
|
|
||||||
|
|
||||||
devs = hid_enumerate(vendor_id, product_id);
|
|
||||||
cur_dev = devs;
|
|
||||||
while (cur_dev) {
|
|
||||||
if (cur_dev->vendor_id == vendor_id &&
|
|
||||||
cur_dev->product_id == product_id &&
|
|
||||||
cur_dev->usage == usage &&
|
|
||||||
cur_dev->usage_page == usage_page
|
|
||||||
) {
|
|
||||||
path_to_open = cur_dev->path;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cur_dev = cur_dev->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path_to_open) {
|
|
||||||
handle = hid_open_path(path_to_open);
|
|
||||||
hid_free_enumeration(devs);
|
|
||||||
} else {
|
|
||||||
hid_free_enumeration(devs);
|
|
||||||
throw std::runtime_error("Could not open hid device");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Close hid device if it is open.
|
|
||||||
void Ergodox::close() {
|
|
||||||
if (handle != NULL) {
|
|
||||||
hid_close(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Send data to Ergodox.
|
|
||||||
|
|
||||||
@param data Data to send
|
|
||||||
@param length How many bytes to send
|
|
||||||
@returns Actual number of bytes written, or -1 on error.
|
|
||||||
*/
|
|
||||||
int Ergodox::write(uint8_t* data, size_t length) const {
|
|
||||||
if (handle == NULL) {
|
|
||||||
throw std::runtime_error("Cannot write, device is not open!");
|
|
||||||
}
|
|
||||||
|
|
||||||
return hid_write(handle, data, length);
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <wchar.h>
|
|
||||||
#include "hidapi.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
A singleton Ergodox interface. Wraps all hidapi methods, including
|
|
||||||
hid_init() and hid_exit().
|
|
||||||
*/
|
|
||||||
class Ergodox {
|
|
||||||
public:
|
|
||||||
static Ergodox& init(
|
|
||||||
unsigned short vendor_id,
|
|
||||||
unsigned short product_id,
|
|
||||||
unsigned short usage,
|
|
||||||
unsigned short usage_page
|
|
||||||
);
|
|
||||||
|
|
||||||
~Ergodox();
|
|
||||||
|
|
||||||
int write(
|
|
||||||
uint8_t* data,
|
|
||||||
size_t length
|
|
||||||
) const;
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ergodox(
|
|
||||||
unsigned short vendor_id,
|
|
||||||
unsigned short product_id,
|
|
||||||
unsigned short usage,
|
|
||||||
unsigned short usage_page
|
|
||||||
);
|
|
||||||
|
|
||||||
// Disable copy and assignment
|
|
||||||
//Ergodox(void);
|
|
||||||
//Ergodox(Ergodox& other);
|
|
||||||
//Ergodox& operator=(Ergodox& other);
|
|
||||||
|
|
||||||
void open();
|
|
||||||
void close();
|
|
||||||
|
|
||||||
// USB Device paramaters
|
|
||||||
const unsigned short vendor_id;
|
|
||||||
const unsigned short product_id;
|
|
||||||
const unsigned short usage;
|
|
||||||
const unsigned short usage_page;
|
|
||||||
|
|
||||||
// HID device.
|
|
||||||
// NULL if not opened.
|
|
||||||
hid_device* handle;
|
|
||||||
};
|
|
67
src/test.cpp
67
src/test.cpp
|
@ -1,17 +1,27 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
// For reading FIFO
|
// For reading FIFO
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
// Math libs
|
||||||
|
#include <math.h>
|
||||||
|
#include <fftw3.h>
|
||||||
|
// HIDapi
|
||||||
|
#include <wchar.h>
|
||||||
|
#include "hidapi.h"
|
||||||
|
|
||||||
// Local files
|
// Local files
|
||||||
#include "utility/bitmap.hpp"
|
#include "utility/bitmap.hpp"
|
||||||
#include "utility/buffer.hpp"
|
#include "utility/buffer.hpp"
|
||||||
#include "signal_processing/fft.hpp"
|
#include "signal_processing/fft.hpp"
|
||||||
#include "ergodox.hpp"
|
|
||||||
|
|
||||||
|
#define HID_VEND 0x3297
|
||||||
|
#define HID_PROD 0x4976
|
||||||
|
#define HID_USAGE 0x61
|
||||||
|
#define HID_PAGE 0xff60
|
||||||
|
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
|
@ -27,6 +37,36 @@
|
||||||
// beat detection
|
// beat detection
|
||||||
|
|
||||||
|
|
||||||
|
hid_device* get_keyboard() {
|
||||||
|
struct hid_device_info *devs, *cur_dev;
|
||||||
|
const char *path_to_open = NULL;
|
||||||
|
hid_device *handle = NULL;
|
||||||
|
|
||||||
|
devs = hid_enumerate(HID_VEND, HID_PROD);
|
||||||
|
cur_dev = devs;
|
||||||
|
while (cur_dev) {
|
||||||
|
if (cur_dev->vendor_id == HID_VEND &&
|
||||||
|
cur_dev->product_id == HID_PROD &&
|
||||||
|
cur_dev->usage == HID_USAGE&&
|
||||||
|
cur_dev->usage_page == HID_PAGE
|
||||||
|
) {
|
||||||
|
path_to_open = cur_dev->path;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cur_dev = cur_dev->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path_to_open) {
|
||||||
|
handle = hid_open_path(path_to_open);
|
||||||
|
} else {
|
||||||
|
wprintf(L"Could not find device, exiting.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
hid_free_enumeration(devs);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void draw_spectrum_bitmap(
|
void draw_spectrum_bitmap(
|
||||||
const std::vector<size_t>& waveform,
|
const std::vector<size_t>& waveform,
|
||||||
Bitmap& bitmap
|
Bitmap& bitmap
|
||||||
|
@ -44,13 +84,15 @@ const size_t height = 150;
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
uint8_t hid_buf[20];
|
|
||||||
Ergodox Dox = Ergodox::init(
|
// HID connect
|
||||||
0x3297,
|
int res;
|
||||||
0x4976,
|
uint8_t hid_buf[65];
|
||||||
0x61,
|
hid_device *handle;
|
||||||
0xFF60
|
// Initialize the hidapi library
|
||||||
);
|
hid_init();
|
||||||
|
// Get Ergodox
|
||||||
|
handle = get_keyboard();
|
||||||
|
|
||||||
// buffer size for waveform:
|
// buffer size for waveform:
|
||||||
// (44100 / fps * 10), make 10 bigger for slower scrolling
|
// (44100 / fps * 10), make 10 bigger for slower scrolling
|
||||||
|
@ -90,7 +132,12 @@ int main(int argc, char *argv[]) {
|
||||||
hid_buf[i + 2] = h;
|
hid_buf[i + 2] = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dox.write(hid_buf, 12);
|
res = hid_write(handle, hid_buf, 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close the device
|
||||||
|
hid_close(handle);
|
||||||
|
// Finalize the hidapi library
|
||||||
|
hid_exit();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
Loading…
Reference in New Issue