(Feat): Implement DMX Engine

This commit is contained in:
illyum 2024-08-16 02:17:43 -06:00
parent 3e73cd63bb
commit 0f5c1da12f
4 changed files with 178 additions and 3 deletions

11
src/DmxWriter.cpp Normal file
View File

@ -0,0 +1,11 @@
//
// Created by illyum on 8/16/2024.
//
#include "DmxWriter.h"
DmxWriter::DmxWriter(DMXEngine& engine) : dmxEngine(engine) {}
void DmxWriter::setChannel(int channel, unsigned char value) {
dmxEngine.setChannelValue(channel, value);
}

19
src/DmxWriter.h Normal file
View File

@ -0,0 +1,19 @@
//
// Created by illyum on 8/16/2024.
//
#ifndef DMXWRITER_H
#define DMXWRITER_H
#include "dmx.h"
class DmxWriter {
public:
DmxWriter(DMXEngine& engine);
void setChannel(int channel, unsigned char value);
private:
DMXEngine& dmxEngine;
};
#endif // DMXWRITER_H

View File

@ -1,3 +1,117 @@
//
// Created by illyum on 8/15/2024.
//
#include "dmx.h"
#include <iostream>
#include <chrono>
#include <thread>
#include "windows.h"
DMXEngine::DMXEngine(const char* portName, int baudRate, int dataSize)
: running(false), buffer(dataSize, 0) {
hSerial = CreateFileA(portName, GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hSerial == INVALID_HANDLE_VALUE) {
std::cerr << "Error opening " << portName << " port" << std::endl;
exit(EXIT_FAILURE);
}
configurePort();
}
DMXEngine::~DMXEngine() {
if (running) {
stop();
}
CloseHandle(hSerial);
}
void DMXEngine::configurePort() {
DCB dcbSerialParams = { 0 };
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (!GetCommState(hSerial, &dcbSerialParams)) {
std::cerr << "Error getting COM port state" << std::endl;
CloseHandle(hSerial);
exit(EXIT_FAILURE);
}
dcbSerialParams.BaudRate = 250000;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = TWOSTOPBITS;
dcbSerialParams.Parity = NOPARITY;
if (!SetCommState(hSerial, &dcbSerialParams)) {
std::cerr << "Error setting COM port state" << std::endl;
CloseHandle(hSerial);
exit(EXIT_FAILURE);
}
COMMTIMEOUTS timeouts = { 0 };
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (!SetCommTimeouts(hSerial, &timeouts)) {
std::cerr << "Error setting COM port timeouts" << std::endl;
CloseHandle(hSerial);
exit(EXIT_FAILURE);
}
}
void DMXEngine::start() {
running = true;
dmxThread = std::thread(dmxThreadFunc, this);
}
void DMXEngine::stop() {
running = false;
if (dmxThread.joinable()) {
dmxThread.join();
}
DMXEngine::dumpZeros();
}
void DMXEngine::setChannelValue(int channel, unsigned char value) {
if (channel >= 0 && channel < buffer.size()) {
buffer[channel] = value;
}
}
void DMXEngine::sendDMXData() {
while (running) {
// Break condition
EscapeCommFunction(hSerial, SETBREAK);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
EscapeCommFunction(hSerial, CLRBREAK);
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // MAB
DWORD bytesWritten;
unsigned char startCode = 0;
WriteFile(hSerial, &startCode, 1, &bytesWritten, NULL);
WriteFile(hSerial, buffer.data(), buffer.size(), &bytesWritten, NULL);
std::this_thread::sleep_for(std::chrono::milliseconds(25));
}
}
void DMXEngine::dumpZeros() {
std::fill(buffer.begin(), buffer.end(), 0);
EscapeCommFunction(hSerial, SETBREAK);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
EscapeCommFunction(hSerial, CLRBREAK);
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // MAB
DWORD bytesWritten;
unsigned char startCode = 0;
WriteFile(hSerial, &startCode, 1, &bytesWritten, NULL);
WriteFile(hSerial, buffer.data(), buffer.size(), &bytesWritten, NULL);
}
void DMXEngine::dmxThreadFunc(DMXEngine* engine) {
engine->sendDMXData();
}

View File

@ -2,7 +2,38 @@
// Created by illyum on 8/15/2024.
//
#ifndef RAYLIBDMX_DMX_H
#define RAYLIBDMX_DMX_H
#ifndef DMX_H
#define DMX_H
#endif //RAYLIBDMX_DMX_H
#include <vector>
#include <tuple>
#include <atomic>
#include <thread>
struct DMXFixture {
unsigned char r, g, b;
int channel;
};
class DMXEngine {
public:
explicit DMXEngine(const char* portName, int baudRate = 250000, int dataSize = 512);
~DMXEngine();
void start();
void stop();
void setChannelValue(int channel, unsigned char value);
private:
void sendDMXData();
void dumpZeros();
void configurePort();
static void dmxThreadFunc(DMXEngine* engine);
void* hSerial;
std::atomic<bool> running;
std::vector<unsigned char> buffer;
std::thread dmxThread;
};
#endif // DMX_H