First working version with some test executables

This commit is contained in:
T. van der Zwan
2013-07-26 20:38:34 +00:00
commit 10b5b80675
62 changed files with 15621 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
# Define the current source locations
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/hyperion)
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion)
add_library(hyperion
${CURRENT_HEADER_DIR}/Hyperion.h
${CURRENT_HEADER_DIR}/LedDevice.h
${CURRENT_HEADER_DIR}/LedString.h
${CURRENT_HEADER_DIR}/ImageToLedsMap.h
${CURRENT_SOURCE_DIR}/LedDeviceWs2801.h
${CURRENT_SOURCE_DIR}/LedDeviceWs2801.cpp
${CURRENT_SOURCE_DIR}/LedString.cpp
${CURRENT_SOURCE_DIR}/Hyperion.cpp
${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp
)

View File

@@ -0,0 +1,101 @@
// Syslog include
#include <syslog.h>
// JsonSchema include
#include <utils/jsonschema/JsonFactory.h>
// hyperion include
#include <hyperion/Hyperion.h>
#include <hyperion/LedDevice.h>
#include "LedDeviceWs2801.h"
LedDevice* constructDevice(const Json::Value& deviceConfig)
{
std::cout << "Device configuration: " << deviceConfig << std::endl;
LedDevice* device = nullptr;
if (deviceConfig["type"].asString() == "ws2801")
{
const std::string name = "WS-2801";
const std::string output = deviceConfig["output"].asString();
const unsigned interval = deviceConfig["interval"].asInt();
const unsigned rate = deviceConfig["rate"].asInt();
LedDeviceWs2801* deviceWs2801 = new LedDeviceWs2801(name, output, interval, rate);
deviceWs2801->open();
device = deviceWs2801;
}
else
{
// Unknown / Unimplemented device
}
return device;
}
Hyperion::Hyperion(const Json::Value &jsonConfig) :
mLedString(LedString::construct(jsonConfig["leds"], jsonConfig["color"])),
mImage(nullptr),
mDevice(constructDevice(jsonConfig["device"]))
{
// empty
}
Hyperion::~Hyperion()
{
// Delete the existing image (or delete nullptr)
delete mImage;
// Delete the Led-String
delete mDevice;
}
void Hyperion::setInputSize(const unsigned width, const unsigned height)
{
// Delete the existing image (or delete nullptr)
delete mImage;
// Create the new image with the mapping to the leds
mImage = new RgbImage(width, height);
mLedsMap.createMapping(*mImage, mLedString.leds());
}
void Hyperion::commit()
{
// Derive the color per led
const std::vector<RgbColor> ledColors = mLedsMap.getMedianLedColor();
// Write the Led colors to the led-string
mDevice->write(ledColors);
}
void Hyperion::operator() (const RgbImage& inputImage)
{
std::cout << "Cached image size: [" << mImage->width() << "x" << mImage->height() << "]. Input image size: [" << inputImage.width() << "x" << inputImage.height() << "]" << std::endl;
// Copy the input-image into the buffer
mImage->copy(inputImage);
// Derive the color per led
// std::vector<RgbColor> ledColors = mLedsMap.getMeanLedColor();
std::vector<RgbColor> ledColors = mLedsMap.getMedianLedColor();
applyTransform(ledColors);
// Write the Led colors to the led-string
mDevice->write(ledColors);
}
void Hyperion::setColor(const RgbColor& color)
{
mDevice->write(std::vector<RgbColor>(mLedString.leds().size(), color));
}
void Hyperion::applyTransform(std::vector<RgbColor>& colors) const
{
for (RgbColor& color : colors)
{
color.red = (color.red < mLedString.red.blacklevel)? 0 : mLedString.red.adjust + mLedString.red.gamma * color.red;
color.green = (color.green < mLedString.green.blacklevel)? 0 : mLedString.green.adjust + mLedString.green.gamma * color.green;
color.blue = (color.blue < mLedString.blue.blacklevel)? 0 : mLedString.blue.adjust + mLedString.blue.gamma * color.blue;
}
}

View File

@@ -0,0 +1,90 @@
// STL includes
#include <algorithm>
// hyperion includes
#include <hyperion/ImageToLedsMap.h>
ImageToLedsMap::ImageToLedsMap()
{
// empty
}
void ImageToLedsMap::createMapping(const RgbImage& image, const std::vector<Led>& leds)
{
mColorsMap.resize(leds.size(), std::vector<const RgbColor*>());
auto ledColors = mColorsMap.begin();
for (auto led = leds.begin(); ledColors != mColorsMap.end() && led != leds.end(); ++ledColors, ++led)
{
ledColors->clear();
const unsigned minX_idx = unsigned(image.width() * led->minX_frac);
const unsigned maxX_idx = unsigned(image.width() * led->maxX_frac);
const unsigned minY_idx = unsigned(image.height() * led->minY_frac);
const unsigned maxY_idx = unsigned(image.height() * led->maxY_frac);
for (unsigned y = minY_idx; y<=maxY_idx && y<image.height(); ++y)
{
for (unsigned x = minX_idx; x<=maxX_idx && x<image.width(); ++x)
{
ledColors->push_back(&image(x,y));
}
}
}
}
std::vector<RgbColor> ImageToLedsMap::getMeanLedColor()
{
std::vector<RgbColor> colors;
for (auto ledColors = mColorsMap.begin(); ledColors != mColorsMap.end(); ++ledColors)
{
const RgbColor color = findMeanColor(*ledColors);
colors.push_back(color);
}
return colors;
}
RgbColor ImageToLedsMap::findMeanColor(const std::vector<const RgbColor*>& colors)
{
uint_fast16_t cummRed = 0;
uint_fast16_t cummGreen = 0;
uint_fast16_t cummBlue = 0;
for (const RgbColor* color : colors)
{
cummRed += color->red;
cummGreen += color->green;
cummBlue += color->blue;
}
const uint8_t avgRed = uint8_t(cummRed/colors.size());
const uint8_t avgGreen = uint8_t(cummGreen/colors.size());
const uint8_t avgBlue = uint8_t(cummBlue/colors.size());
return {avgRed, avgGreen, avgBlue};
}
std::vector<RgbColor> ImageToLedsMap::getMedianLedColor()
{
std::vector<RgbColor> ledColors;
for (std::vector<const RgbColor*>& colors : mColorsMap)
{
const RgbColor color = findMedianColor(colors);
ledColors.push_back(color);
}
return ledColors;
}
RgbColor ImageToLedsMap::findMedianColor(std::vector<const RgbColor*>& colors)
{
std::sort(colors.begin(), colors.end(), [](const RgbColor* lhs, const RgbColor* rhs){ return lhs->red < rhs->red; });
const uint8_t red = colors.at(colors.size()/2)->red;
std::sort(colors.begin(), colors.end(), [](const RgbColor* lhs, const RgbColor* rhs){ return lhs->green < rhs->green; });
const uint8_t green = colors.at(colors.size()/2)->green;
std::sort(colors.begin(), colors.end(), [](const RgbColor* lhs, const RgbColor* rhs){ return lhs->blue < rhs->blue; });
const uint8_t blue = colors.at(colors.size()/2)->blue;
return {red, green, blue};
}

View File

@@ -0,0 +1,85 @@
// STL includes
#include <cstring>
#include <cstdio>
#include <iostream>
// Linux includes
#include <fcntl.h>
#include <sys/ioctl.h>
// hyperion local includes
#include "LedDeviceWs2801.h"
LedDeviceWs2801::LedDeviceWs2801(const std::string& name,
const std::string& outputDevice,
const unsigned interval,
const unsigned baudrate) :
mDeviceName(outputDevice),
mBaudRate_Hz(baudrate),
mFid(-1)
{
memset(&spi, 0, sizeof(spi));
latchTime.tv_sec = 0;
latchTime.tv_nsec = 500000;
}
LedDeviceWs2801::~LedDeviceWs2801()
{
// close(mFid);
}
int LedDeviceWs2801::open()
{
const int bitsPerWord = 8;
mFid = ::open(mDeviceName.c_str(), O_RDWR);
if (mFid < 0)
{
std::cerr << "Failed to open device('" << mDeviceName << "') " << std::endl;
return -1;
}
int mode = SPI_MODE_0;
if (ioctl(mFid, SPI_IOC_WR_MODE, &mode) == -1 || ioctl(mFid, SPI_IOC_RD_MODE, &mode) == -1)
{
return -2;
}
if (ioctl(mFid, SPI_IOC_WR_BITS_PER_WORD, &bitsPerWord) == -1 || ioctl(mFid, SPI_IOC_RD_BITS_PER_WORD, &bitsPerWord) == -1)
{
return -4;
}
if (ioctl(mFid, SPI_IOC_WR_MAX_SPEED_HZ, &mBaudRate_Hz) == -1 || ioctl(mFid, SPI_IOC_RD_MAX_SPEED_HZ, &mBaudRate_Hz) == -1)
{
return -6;
}
return 0;
}
int LedDeviceWs2801::write(const std::vector<RgbColor> &ledValues)
{
if (mFid < 0)
{
std::cerr << "Can not write to device which is open." << std::endl;
return -1;
}
spi.tx_buf = (__u64)ledValues.data();
spi.len = ledValues.size() * sizeof(RgbColor);
int retVal = ioctl(mFid, SPI_IOC_MESSAGE(1), &spi);
if (retVal == 0)
{
// Sleep to latch the leds (only if write succesfull)
nanosleep(&latchTime, NULL);
}
return retVal;
}

View File

@@ -0,0 +1,33 @@
#pragma once
// STL includes
#include <string>
// Linux-SPI includes
#include <linux/spi/spidev.h>
// hyperion incluse
#include <hyperion/LedDevice.h>
class LedDeviceWs2801 : public LedDevice
{
public:
LedDeviceWs2801(const std::string& name,
const std::string& outputDevice,
const unsigned interval,
const unsigned baudrate);
virtual ~LedDeviceWs2801();
int open();
virtual int write(const std::vector<RgbColor> &ledValues);
private:
const std::string mDeviceName;
const int mBaudRate_Hz;
int mFid;
spi_ioc_transfer spi;
timespec latchTime;
};

View File

@@ -0,0 +1,60 @@
// STL includes
#include <cstring>
#include <unistd.h>
#include <iostream>
// Json includes
#include <json/json.h>
// hyperion includes
#include <hyperion/LedString.h>
LedString LedString::construct(const Json::Value& ledsConfig, const Json::Value& colorConfig)
{
LedString ledString;
const Json::Value& redConfig = colorConfig["red"];
const Json::Value& greenConfig = colorConfig["greem"];
const Json::Value& blueConfig = colorConfig["blue"];
ledString.red.gamma = redConfig["gamma"].asDouble();
ledString.red.adjust = redConfig["adjust"].asDouble();
ledString.red.blacklevel = redConfig["blacklevel"].asDouble();
ledString.green.gamma = greenConfig["gamma"].asDouble();
ledString.green.adjust = colorConfig["adjust"].asDouble();
ledString.green.blacklevel = colorConfig["blacklevel"].asDouble();
ledString.blue.gamma = blueConfig["gamma"].asDouble();
ledString.blue.adjust = blueConfig["adjust"].asDouble();
ledString.blue.blacklevel = blueConfig["blacklevel"].asDouble();
for (const Json::Value& ledConfig : ledsConfig)
{
Led led;
led.index = ledConfig["index"].asInt();
const Json::Value& hscanConfig = ledConfig["hscan"];
const Json::Value& vscanConfig = ledConfig["vscan"];
led.minX_frac = std::max(0.0, std::min(100.0, hscanConfig["minimum"].asDouble()))/100.0;
led.maxX_frac = std::max(0.0, std::min(100.0, hscanConfig["maximum"].asDouble()))/100.0;
led.minY_frac = 1.0 - std::max(0.0, std::min(100.0, vscanConfig["maximum"].asDouble()))/100.0;
led.maxY_frac = 1.0 - std::max(0.0, std::min(100.0, vscanConfig["minimum"].asDouble()))/100.0;
ledString.mLeds.push_back(led);
}
return ledString;
}
LedString::LedString()
{
// empty
}
LedString::~LedString()
{
}
const std::vector<Led>& LedString::leds() const
{
return mLeds;
}