spicetools/games/onpara/touchpanel.cpp

136 lines
3.7 KiB
C++

#include <thread>
#include <chrono>
#include "touchpanel.h"
#include "util/logging.h"
#include "touch/touch.h"
using namespace std::chrono_literals;
void games::onpara::TouchPanelHandle::set_state(touch_panel_state state) {
state_ = state;
// reset the output queue as well for good measure
output_queue_ = {};
}
void games::onpara::TouchPanelHandle::enqueue_packet(touch_panel_message const &message) {
// push magic
output_queue_.push('U');
// push message
for (auto b : message.raw) {
output_queue_.push(b);
}
// push checksum
output_queue_.push(message.raw[0] +
message.raw[1] +
message.raw[2] +
message.raw[3] +
message.raw[4] +
message.raw[5] +
message.raw[6] +
message.raw[7] - 1);
}
bool games::onpara::TouchPanelHandle::open(LPCWSTR lpFileName) {
if (wcscmp(lpFileName, L"COM1: baud=9600 parity=N data=8 stop=1") != 0) {
return false;
}
log_info("touchpanel", "Opened COM1 (Touch Panel)");
return true;
}
int games::onpara::TouchPanelHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
DWORD i;
auto buffer = reinterpret_cast<uint8_t *>(lpBuffer);
if (state_ == TOUCH_PANEL_STATE_REPORT && output_queue_.empty()) {
// create a new status report message
touch_panel_message report = {
'T', 'K', 0, 0, 0
};
std::vector<TouchPoint> touch_points;
touch_get_points(touch_points);
if (!touch_points.empty()) {
auto &touch_point = touch_points[0];
report.x = static_cast<uint16_t>(touch_point.x);
report.y = 768 - static_cast<uint16_t>(touch_point.y);
report.z = ~0;
}
enqueue_packet(report);
// prevent cpu bullying
std::this_thread::sleep_for(1ms);
}
// copy from output queue
for (i = 0; i < nNumberOfBytesToRead && !output_queue_.empty(); i++) {
buffer[i] = output_queue_.front();
output_queue_.pop();
}
return i;
}
int games::onpara::TouchPanelHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
// static messages
static const touch_panel_message acknowledge_message = {
'A', 0, 0, 0, 0
};
static const touch_panel_message diagnostics_message = {
'D', 0, 0, 0, 0
};
// make sure that we received the correct amount of data
if (nNumberOfBytesToWrite != 10) {
log_warning("touchscreen", "invalid packet size");
return 0;
}
auto op = reinterpret_cast<const char *>(lpBuffer)[1];
switch (op) {
case 'R': // reset
set_state(TOUCH_PANEL_STATE_INACTIVE);
break;
case 'a': // acknowledge
if (state_ == TOUCH_PANEL_STATE_INACTIVE) {
set_state(TOUCH_PANEL_STATE_ACKNOWLEDGE);
enqueue_packet(acknowledge_message);
}
else if (state_ == TOUCH_PANEL_STATE_DIAGNOSTICS) {
// start reporting
set_state(TOUCH_PANEL_STATE_REPORT);
}
break;
case 'D': // diagnositcs
set_state(TOUCH_PANEL_STATE_DIAGNOSTICS);
enqueue_packet(diagnostics_message);
break;
default:
log_warning("touchpanel", "invalid operation: {:c}", op);
break;
}
return nNumberOfBytesToWrite;
}
int games::onpara::TouchPanelHandle::device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
LPVOID lpOutBuffer, DWORD nOutBufferSize) {
return -1;
}
bool games::onpara::TouchPanelHandle::close() {
log_info("touchpanel", "Closed COM1 (Touch Panel)");
return true;
}