140 lines
7.0 KiB
C++
140 lines
7.0 KiB
C++
#ifndef RH56DFTP_TACTILE_BUFFER_H
|
|
#define RH56DFTP_TACTILE_BUFFER_H
|
|
#pragma once
|
|
|
|
#include <array>
|
|
#include <cstddef>
|
|
#include <stdexcept>
|
|
|
|
#include "../../abstract_dexhand.h"
|
|
|
|
namespace cmvr::device {
|
|
|
|
enum class RH56TactileFillOrder {
|
|
ROW_MAJOR,
|
|
COLUMN_MAJOR_TOP_TO_BOTTOM,
|
|
COLUMN_MAJOR_BOTTOM_TO_TOP
|
|
};
|
|
|
|
struct RH56TactileRegionLayout {
|
|
AbstractDexHand::FingerType finger{AbstractDexHand::FingerType::PINKY};
|
|
AbstractDexHand::TactileRegion region{AbstractDexHand::TactileRegion::TIP};
|
|
const char* name{nullptr};
|
|
int rows{0};
|
|
int cols{0};
|
|
size_t offset{0};
|
|
size_t point_count{0};
|
|
RH56TactileFillOrder fill_order{RH56TactileFillOrder::ROW_MAJOR};
|
|
|
|
AbstractDexHand::TactileMatrixView view(const AbstractDexHand::TactilePoint* buffer) const {
|
|
return AbstractDexHand::TactileMatrixView{buffer + offset, rows, cols};
|
|
}
|
|
};
|
|
|
|
class RH56TactileBuffer {
|
|
public:
|
|
static constexpr size_t REGION_COUNT = 17;
|
|
static constexpr size_t POINT_COUNT = 1062;
|
|
|
|
void clear() {
|
|
values_.fill(0);
|
|
}
|
|
|
|
void assignRegionData(AbstractDexHand::FingerType finger,
|
|
AbstractDexHand::TactileRegion region,
|
|
const AbstractDexHand::TactilePoint* input,
|
|
int valueCount) {
|
|
const auto& layout = regionLayout(finger, region);
|
|
auto* destination = values_.data() + layout.offset;
|
|
const auto sanitize_point = [](const AbstractDexHand::TactilePoint value) {
|
|
return value > static_cast<AbstractDexHand::TactilePoint>(4096) ? 0 : value;
|
|
};
|
|
int input_index = 0;
|
|
|
|
if (layout.fill_order == RH56TactileFillOrder::ROW_MAJOR) {
|
|
for (size_t point = 0; point < layout.point_count && input_index < valueCount; ++point, ++input_index) {
|
|
destination[point] = sanitize_point(input[input_index]);
|
|
}
|
|
return;
|
|
}
|
|
|
|
const bool reverse_rows = layout.fill_order == RH56TactileFillOrder::COLUMN_MAJOR_BOTTOM_TO_TOP;
|
|
for (int col = 0; col < layout.cols; ++col) {
|
|
for (int row_index = 0; row_index < layout.rows && input_index < valueCount; ++row_index, ++input_index) {
|
|
const int row = reverse_rows ? (layout.rows - 1 - row_index) : row_index;
|
|
destination[static_cast<size_t>(row * layout.cols + col)] = sanitize_point(input[input_index]);
|
|
}
|
|
}
|
|
}
|
|
|
|
const RH56TactileRegionLayout& regionLayout(AbstractDexHand::FingerType finger,
|
|
AbstractDexHand::TactileRegion region) const {
|
|
return layouts()[findRegionIndex(finger, region)];
|
|
}
|
|
|
|
AbstractDexHand::TactileMatrixView regionView(AbstractDexHand::FingerType finger,
|
|
AbstractDexHand::TactileRegion region) const {
|
|
const auto& layout = regionLayout(finger, region);
|
|
return layout.view(values_.data());
|
|
}
|
|
|
|
const std::array<RH56TactileRegionLayout, REGION_COUNT>& layouts() const {
|
|
return staticLayouts();
|
|
}
|
|
|
|
const AbstractDexHand::TactilePoint* data() const {
|
|
return values_.data();
|
|
}
|
|
|
|
private:
|
|
static const std::array<RH56TactileRegionLayout, REGION_COUNT>& staticLayouts() {
|
|
static const std::array<RH56TactileRegionLayout, REGION_COUNT> layouts = {{
|
|
{AbstractDexHand::FingerType::PINKY, AbstractDexHand::TactileRegion::TIP, "小拇指指端", 3, 3, 0, 9, RH56TactileFillOrder::ROW_MAJOR},
|
|
{AbstractDexHand::FingerType::PINKY, AbstractDexHand::TactileRegion::FINGER, "小拇指指尖", 12, 8, 9, 96, RH56TactileFillOrder::ROW_MAJOR},
|
|
{AbstractDexHand::FingerType::PINKY, AbstractDexHand::TactileRegion::PAD, "小拇指指腹", 10, 8, 105, 80, RH56TactileFillOrder::ROW_MAJOR},
|
|
|
|
{AbstractDexHand::FingerType::RING, AbstractDexHand::TactileRegion::TIP, "无名指指端", 3, 3, 185, 9, RH56TactileFillOrder::ROW_MAJOR},
|
|
{AbstractDexHand::FingerType::RING, AbstractDexHand::TactileRegion::FINGER, "无名指指尖", 12, 8, 194, 96, RH56TactileFillOrder::ROW_MAJOR},
|
|
{AbstractDexHand::FingerType::RING, AbstractDexHand::TactileRegion::PAD, "无名指指腹", 10, 8, 290, 80, RH56TactileFillOrder::ROW_MAJOR},
|
|
|
|
{AbstractDexHand::FingerType::MIDDLE, AbstractDexHand::TactileRegion::TIP, "中指指端", 3, 3, 370, 9, RH56TactileFillOrder::ROW_MAJOR},
|
|
{AbstractDexHand::FingerType::MIDDLE, AbstractDexHand::TactileRegion::FINGER, "中指指尖", 12, 8, 379, 96, RH56TactileFillOrder::ROW_MAJOR},
|
|
{AbstractDexHand::FingerType::MIDDLE, AbstractDexHand::TactileRegion::PAD, "中指指腹", 10, 8, 475, 80, RH56TactileFillOrder::ROW_MAJOR},
|
|
|
|
{AbstractDexHand::FingerType::INDEX, AbstractDexHand::TactileRegion::TIP, "食指指端", 3, 3, 555, 9, RH56TactileFillOrder::ROW_MAJOR},
|
|
{AbstractDexHand::FingerType::INDEX, AbstractDexHand::TactileRegion::FINGER, "食指指尖", 12, 8, 564, 96, RH56TactileFillOrder::ROW_MAJOR},
|
|
{AbstractDexHand::FingerType::INDEX, AbstractDexHand::TactileRegion::PAD, "食指指腹", 10, 8, 660, 80, RH56TactileFillOrder::ROW_MAJOR},
|
|
|
|
{AbstractDexHand::FingerType::THUMB, AbstractDexHand::TactileRegion::TIP, "大拇指指端", 3, 3, 740, 9, RH56TactileFillOrder::ROW_MAJOR},
|
|
{AbstractDexHand::FingerType::THUMB, AbstractDexHand::TactileRegion::FINGER, "大拇指尖", 12, 8, 749, 96, RH56TactileFillOrder::ROW_MAJOR},
|
|
{AbstractDexHand::FingerType::THUMB, AbstractDexHand::TactileRegion::THUMB_MIDDLE, "大拇指指中", 3, 3, 845, 9, RH56TactileFillOrder::ROW_MAJOR},
|
|
{AbstractDexHand::FingerType::THUMB, AbstractDexHand::TactileRegion::PAD, "大拇指指腹", 12, 8, 854, 96, RH56TactileFillOrder::ROW_MAJOR},
|
|
|
|
{AbstractDexHand::FingerType::PALM,
|
|
AbstractDexHand::TactileRegion::PALM_PAD,
|
|
"掌心",
|
|
8,
|
|
14,
|
|
950,
|
|
112,
|
|
RH56TactileFillOrder::COLUMN_MAJOR_TOP_TO_BOTTOM}
|
|
}};
|
|
return layouts;
|
|
}
|
|
|
|
static size_t findRegionIndex(AbstractDexHand::FingerType finger, AbstractDexHand::TactileRegion region) {
|
|
const auto& region_layouts = staticLayouts();
|
|
for (size_t index = 0; index < region_layouts.size(); ++index) {
|
|
if (region_layouts[index].finger == finger && region_layouts[index].region == region) {
|
|
return index;
|
|
}
|
|
}
|
|
throw std::invalid_argument("Invalid tactile region for selected finger.");
|
|
}
|
|
|
|
std::array<AbstractDexHand::TactilePoint, POINT_COUNT> values_{};
|
|
};
|
|
}
|
|
|
|
#endif //RH56DFTP_TACTILE_BUFFER_H
|