(Feat): Implement DMX Engine
This commit is contained in:
parent
3e73cd63bb
commit
0f5c1da12f
11
src/DmxWriter.cpp
Normal file
11
src/DmxWriter.cpp
Normal 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
19
src/DmxWriter.h
Normal 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
|
114
src/dmx.cpp
114
src/dmx.cpp
@ -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();
|
||||
}
|
||||
|
37
src/dmx.h
37
src/dmx.h
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user