2019-05-10 05:17:29 +00:00
|
|
|
#pragma once
|
2021-03-29 08:10:55 +00:00
|
|
|
#include <Figments.h>
|
|
|
|
|
2022-06-11 09:02:27 +00:00
|
|
|
struct MaskCoordinateMapping : CoordinateMapping {
|
|
|
|
struct Span {
|
|
|
|
int length = 0;
|
|
|
|
int x = 0;
|
|
|
|
int y = 0;
|
|
|
|
|
|
|
|
Span(int length, int x, int y) : length(length), x(x), y(y) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
Span displayMap[13] = {
|
|
|
|
{6, 0, 6},
|
|
|
|
{6, 1, 6},
|
|
|
|
{7, 2, 6},
|
|
|
|
{9, 3, 4},
|
|
|
|
{14, 4, 4},
|
|
|
|
{17, 5, 0},
|
|
|
|
{12, 6, 2},
|
|
|
|
{18, 7, 0},
|
|
|
|
{14, 8, 4},
|
|
|
|
{9, 9, 5},
|
|
|
|
{7, 10, 4},
|
|
|
|
{6, 11, 5},
|
|
|
|
{6, 12, 5}
|
|
|
|
};
|
|
|
|
|
|
|
|
VirtualCoordinates physicalToVirtualCoords(const PhysicalCoordinates localCoords) const override {
|
|
|
|
int offset = localCoords.x;
|
|
|
|
for(int i = 0; i < 12; i++) {
|
|
|
|
if (offset > displayMap[i].length) {
|
|
|
|
offset -= displayMap[i].length;
|
|
|
|
} else {
|
|
|
|
return VirtualCoordinates{i, offset};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PhysicalCoordinates virtualToPhysicalCoords(const VirtualCoordinates virtualCoords) const override {
|
|
|
|
const uint8_t spanIdx = scale8(12, virtualCoords.x);
|
|
|
|
const uint8_t spanOffset = scale8(17, virtualCoords.y);
|
|
|
|
return PhysicalCoordinates{spanIdx, spanOffset};
|
|
|
|
}
|
|
|
|
|
|
|
|
int physicalCoordsToIndex(const PhysicalCoordinates localCoords) const override {
|
|
|
|
uint8_t idx = 0;
|
|
|
|
bool inverse = false;
|
|
|
|
for(int i = 0; i < localCoords.x; i++) {
|
|
|
|
idx += displayMap[i].length;
|
|
|
|
inverse = !inverse;
|
|
|
|
}
|
|
|
|
if (inverse) {
|
|
|
|
idx += std::max(0, displayMap[localCoords.x].length - 1 - std::max(0, (int)localCoords.y - displayMap[localCoords.x].y));
|
|
|
|
} else {
|
|
|
|
idx += std::min((int)displayMap[localCoords.x].length - 1, std::max(0, (int)localCoords.y - displayMap[localCoords.x].y));
|
|
|
|
}
|
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int physicalPixelCount() const override {
|
|
|
|
int total = 0;
|
|
|
|
for(int i = 0; i < 13; i++) {
|
|
|
|
total += displayMap[i].length;
|
|
|
|
}
|
|
|
|
return total;
|
|
|
|
}
|
|
|
|
};
|
2019-05-10 05:17:29 +00:00
|
|
|
|
|
|
|
struct HardwareConfig {
|
2022-06-11 09:02:27 +00:00
|
|
|
uint8_t version = 3;
|
2019-05-10 05:17:29 +00:00
|
|
|
uint8_t checksum = 0;
|
|
|
|
struct Data {
|
|
|
|
uint16_t pixelCount = 255;
|
|
|
|
uint16_t startPixel = 0;
|
2021-03-29 00:18:03 +00:00
|
|
|
uint8_t lastRed = 255;
|
|
|
|
uint8_t lastGreen = 255;
|
|
|
|
uint8_t lastBlue = 255;
|
|
|
|
char lastScene[16] = {0};
|
2019-05-10 05:17:29 +00:00
|
|
|
};
|
|
|
|
Data data;
|
|
|
|
|
|
|
|
static HardwareConfig load();
|
|
|
|
void save();
|
|
|
|
bool isValid() const;
|
|
|
|
|
2021-03-28 01:19:55 +00:00
|
|
|
LinearCoordinateMapping toCoordMap() const;
|
|
|
|
static constexpr uint16_t MAX_LED_NUM = 255;
|
|
|
|
|
2019-05-10 05:17:29 +00:00
|
|
|
private:
|
|
|
|
uint8_t getCRC() const;
|
|
|
|
|
|
|
|
static constexpr uint8_t CRC7_POLY = 0x91;
|
|
|
|
};
|
|
|
|
|
|
|
|
// A task that manages the EEPROM settings and coord mapping when modified via
|
|
|
|
// Particle. This allows for multiple devices with wildly different displays to
|
|
|
|
// run the same code
|
|
|
|
struct ConfigService: public Task {
|
|
|
|
ConfigService() : Task("Configuration") {}
|
|
|
|
void onStart();
|
|
|
|
void loop() override;
|
|
|
|
void handleEvent(const InputEvent &evt) override;
|
2022-06-11 09:02:27 +00:00
|
|
|
const CoordinateMapping* coordMap() const { return /*&m_maskMap;*/ &m_coordMap; }
|
2019-05-10 05:17:29 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
HardwareConfig m_config;
|
2022-06-11 09:02:27 +00:00
|
|
|
MaskCoordinateMapping m_maskMap;
|
2019-05-10 05:17:29 +00:00
|
|
|
LinearCoordinateMapping m_coordMap;
|
|
|
|
};
|