add LED pipe for billboard
parent
44ba947998
commit
48c5a4f053
|
@ -10,6 +10,13 @@ add_library(chuniio_brokenithm SHARED src/chuniio.c
|
||||||
src/chuniio.h
|
src/chuniio.h
|
||||||
src/config.c
|
src/config.c
|
||||||
src/config.h
|
src/config.h
|
||||||
|
src/leddata.h
|
||||||
|
src/ledoutput.c
|
||||||
|
src/ledoutput.h
|
||||||
|
src/pipeimpl.c
|
||||||
|
src/pipeimpl.h
|
||||||
|
src/serialimpl.c
|
||||||
|
src/serialimpl.h
|
||||||
src/servers/socket.h
|
src/servers/socket.h
|
||||||
src/ipc_memory_info.h
|
src/ipc_memory_info.h
|
||||||
src/servers/android.c
|
src/servers/android.c
|
||||||
|
|
|
@ -9,13 +9,16 @@
|
||||||
|
|
||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "ledoutput.h"
|
||||||
#include "ipc_memory_info.h"
|
#include "ipc_memory_info.h"
|
||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
#ifdef ENV32BIT
|
#ifdef ENV32BIT
|
||||||
|
|
||||||
#include "servers/android.h"
|
#include "servers/android.h"
|
||||||
#include "servers/common.h"
|
#include "servers/common.h"
|
||||||
#include "servers/ios.h"
|
#include "servers/ios.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MEM_FILE_NAME "Local\\BROKENITHM_SHARED_BUFFER"
|
#define MEM_FILE_NAME "Local\\BROKENITHM_SHARED_BUFFER"
|
||||||
|
@ -37,7 +40,7 @@ HRESULT chuni_io_init_shared_memory() {
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((chuni_io_file_mapping = (struct IPCMemoryInfo *)MapViewOfFile(
|
if ((chuni_io_file_mapping = (struct IPCMemoryInfo *) MapViewOfFile(
|
||||||
chuni_io_file_mapping_handle, FILE_MAP_ALL_ACCESS, 0, 0,
|
chuni_io_file_mapping_handle, FILE_MAP_ALL_ACCESS, 0, 0,
|
||||||
sizeof(struct IPCMemoryInfo))) == 0) {
|
sizeof(struct IPCMemoryInfo))) == 0) {
|
||||||
dprintf("chuni_io_init_shared_memory: could not get view of file: %ld\n",
|
dprintf("chuni_io_init_shared_memory: could not get view of file: %ld\n",
|
||||||
|
@ -71,6 +74,12 @@ HRESULT chuni_io_jvs_init() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
led_init_mutex = CreateMutex(NULL, FALSE, NULL);
|
||||||
|
|
||||||
|
if (led_init_mutex == NULL) {
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ENV32BIT
|
#ifdef ENV32BIT
|
||||||
if ((result = android_init_server(chuni_io_file_mapping))) {
|
if ((result = android_init_server(chuni_io_file_mapping))) {
|
||||||
print_err("[ERROR] Android server intialization failed: %ld", result);
|
print_err("[ERROR] Android server intialization failed: %ld", result);
|
||||||
|
@ -148,7 +157,9 @@ void chuni_io_jvs_poll(uint8_t *opbtn, uint8_t *beams) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT chuni_io_slider_init() { return S_OK; }
|
HRESULT chuni_io_slider_init() {
|
||||||
|
return led_output_init(&chuni_io_cfg);
|
||||||
|
}
|
||||||
|
|
||||||
void chuni_io_slider_start(void *callback) {
|
void chuni_io_slider_start(void *callback) {
|
||||||
if (chuni_io_slider_thread != NULL) {
|
if (chuni_io_slider_thread != NULL) {
|
||||||
|
@ -158,7 +169,7 @@ void chuni_io_slider_start(void *callback) {
|
||||||
atomic_flag_test_and_set(&chuni_io_slider_run_flag);
|
atomic_flag_test_and_set(&chuni_io_slider_run_flag);
|
||||||
|
|
||||||
chuni_io_slider_thread =
|
chuni_io_slider_thread =
|
||||||
(HANDLE)_beginthreadex(NULL, 0, chuni_io_slider_thread_proc, callback, 0, NULL);
|
(HANDLE) _beginthreadex(NULL, 0, chuni_io_slider_thread_proc, callback, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void chuni_io_slider_stop(void) {
|
void chuni_io_slider_stop(void) {
|
||||||
|
@ -174,14 +185,20 @@ void chuni_io_slider_stop(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void chuni_io_slider_set_leds(const uint8_t *rgb) {
|
void chuni_io_slider_set_leds(const uint8_t *rgb) {
|
||||||
|
led_output_update(2, rgb);
|
||||||
|
|
||||||
if (chuni_io_file_mapping) {
|
if (chuni_io_file_mapping) {
|
||||||
memcpy(chuni_io_file_mapping->ledRgbData, rgb, 32 * 3);
|
memcpy(chuni_io_file_mapping->ledRgbData, rgb, 32 * 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT chuni_io_led_init(void) { return S_OK; }
|
HRESULT chuni_io_led_init(void) {
|
||||||
|
return led_output_init(&chuni_io_cfg);
|
||||||
|
}
|
||||||
|
|
||||||
void chuni_io_led_set_colors(uint8_t board, uint8_t *rgb) {}
|
void chuni_io_led_set_colors(uint8_t board, uint8_t *rgb) {
|
||||||
|
led_output_update(board, rgb);
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned int __stdcall chuni_io_slider_thread_proc(void *ctx) {
|
static unsigned int __stdcall chuni_io_slider_thread_proc(void *ctx) {
|
||||||
const chuni_io_slider_callback_t callback = ctx;
|
const chuni_io_slider_callback_t callback = ctx;
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define LED_PACKET_FRAMING 0xE0
|
||||||
|
#define LED_PACKET_ESCAPE 0xD0
|
||||||
|
#define LED_NUM_MAX 66
|
||||||
|
#define LED_BOARDS_TOTAL 3
|
||||||
|
#define LED_OUTPUT_HEADER_SIZE 2
|
||||||
|
#define LED_OUTPUT_DATA_SIZE_MAX LED_NUM_MAX * 3 * 2 // max if every byte's escaped
|
||||||
|
#define LED_OUTPUT_TOTAL_SIZE_MAX LED_OUTPUT_HEADER_SIZE + LED_OUTPUT_DATA_SIZE_MAX
|
||||||
|
|
||||||
|
// This struct is used to send data related to the slider and billboard LEDs
|
||||||
|
struct _chuni_led_data_buf_t {
|
||||||
|
byte framing; // Sync byte
|
||||||
|
uint8_t board; // LED output the data is for (0-1: billboard, 2: slider)
|
||||||
|
byte data[LED_OUTPUT_DATA_SIZE_MAX]; // Buffer for LEDs
|
||||||
|
byte data_len; // How many bytes to output from the buffer
|
||||||
|
};
|
||||||
|
|
||||||
|
static byte chuni_led_board_data_lens[LED_BOARDS_TOTAL] = {53*3, 63*3, 31*3};
|
|
@ -0,0 +1,131 @@
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "leddata.h"
|
||||||
|
#include "ledoutput.h"
|
||||||
|
#include "pipeimpl.h"
|
||||||
|
#include "serialimpl.h"
|
||||||
|
|
||||||
|
static struct _chuni_led_data_buf_t led_unescaped_buf[LED_BOARDS_TOTAL];
|
||||||
|
static struct _chuni_led_data_buf_t led_escaped_buf[LED_BOARDS_TOTAL];
|
||||||
|
|
||||||
|
static bool led_output_is_init = false;
|
||||||
|
static struct chuni_io_config* config;
|
||||||
|
static bool any_outputs_enabled;
|
||||||
|
|
||||||
|
HANDLE led_init_mutex;
|
||||||
|
|
||||||
|
HRESULT led_output_init(struct chuni_io_config* const cfg)
|
||||||
|
{
|
||||||
|
DWORD dwWaitResult = WaitForSingleObject(led_init_mutex, INFINITE);
|
||||||
|
if (dwWaitResult == WAIT_FAILED)
|
||||||
|
{
|
||||||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||||||
|
// return 1;
|
||||||
|
}
|
||||||
|
else if (dwWaitResult != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
return E_FAIL;
|
||||||
|
// return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!led_output_is_init)
|
||||||
|
{
|
||||||
|
config = cfg;
|
||||||
|
|
||||||
|
// Set up the framing bytes for the packets
|
||||||
|
for (int i = 0; i < LED_BOARDS_TOTAL; i++) {
|
||||||
|
led_unescaped_buf[i].framing = LED_PACKET_FRAMING;
|
||||||
|
led_unescaped_buf[i].board = i;
|
||||||
|
led_unescaped_buf[i].data_len = chuni_led_board_data_lens[i];
|
||||||
|
|
||||||
|
led_escaped_buf[i].framing = LED_PACKET_FRAMING;
|
||||||
|
led_escaped_buf[i].board = i;
|
||||||
|
led_escaped_buf[i].data_len = chuni_led_board_data_lens[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
any_outputs_enabled = config->led_output_pipe || config->slider_led_output_pipe
|
||||||
|
|| config->led_output_serial || config->slider_led_output_serial;
|
||||||
|
|
||||||
|
if (config->led_output_pipe || config->slider_led_output_pipe)
|
||||||
|
{
|
||||||
|
led_pipe_init(); // don't really care about errors here tbh
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->led_output_serial || config->slider_led_output_serial)
|
||||||
|
{
|
||||||
|
led_serial_init(config->led_serial_port, config->led_serial_baud);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
led_output_is_init = true;
|
||||||
|
|
||||||
|
ReleaseMutex(led_init_mutex);
|
||||||
|
return S_OK;
|
||||||
|
// return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct _chuni_led_data_buf_t* escape_led_data(struct _chuni_led_data_buf_t* unescaped)
|
||||||
|
{
|
||||||
|
struct _chuni_led_data_buf_t* out_struct = &led_escaped_buf[unescaped->board];
|
||||||
|
|
||||||
|
byte* in_buf = unescaped->data;
|
||||||
|
byte* out_buf = out_struct->data;
|
||||||
|
int i = 0;
|
||||||
|
int o = 0;
|
||||||
|
|
||||||
|
while (i < unescaped->data_len)
|
||||||
|
{
|
||||||
|
byte b = in_buf[i++];
|
||||||
|
if (b == LED_PACKET_FRAMING || b == LED_PACKET_ESCAPE)
|
||||||
|
{
|
||||||
|
out_buf[o++] = LED_PACKET_ESCAPE;
|
||||||
|
b--;
|
||||||
|
}
|
||||||
|
out_buf[o++] = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_struct->data_len = o;
|
||||||
|
|
||||||
|
return out_struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_output_update(uint8_t board, const uint8_t* rgb)
|
||||||
|
{
|
||||||
|
if (board < 0 || board > 2 || !any_outputs_enabled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(led_unescaped_buf[board].data, rgb, led_unescaped_buf[board].data_len);
|
||||||
|
struct _chuni_led_data_buf_t* escaped_data = escape_led_data(&led_unescaped_buf[board]);
|
||||||
|
|
||||||
|
if (board < 2)
|
||||||
|
{
|
||||||
|
// billboard
|
||||||
|
if (config->led_output_pipe)
|
||||||
|
{
|
||||||
|
led_pipe_update(escaped_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->led_output_serial)
|
||||||
|
{
|
||||||
|
led_serial_update(escaped_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// slider
|
||||||
|
if (config->slider_led_output_pipe)
|
||||||
|
{
|
||||||
|
led_pipe_update(escaped_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->slider_led_output_serial)
|
||||||
|
{
|
||||||
|
led_serial_update(escaped_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
LED output functions
|
||||||
|
|
||||||
|
Credits:
|
||||||
|
somewhatlurker, skogaby
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
extern HANDLE led_init_mutex;
|
||||||
|
HRESULT led_output_init(struct chuni_io_config* const cfg);
|
||||||
|
void led_output_update(uint8_t board, const uint8_t* rgb);
|
|
@ -0,0 +1,160 @@
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <process.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "leddata.h"
|
||||||
|
#include "pipeimpl.h"
|
||||||
|
|
||||||
|
static bool pipe_update[LED_BOARDS_TOTAL];
|
||||||
|
|
||||||
|
// incoming data is copied into these to ensure it isn't written during output
|
||||||
|
static struct _chuni_led_data_buf_t pipe_write_buf[LED_BOARDS_TOTAL];
|
||||||
|
static HANDLE pipe_write_mutex;
|
||||||
|
|
||||||
|
static HRESULT pipe_create(LPHANDLE hPipe, LPCWSTR lpszPipename, DWORD dwBufSize)
|
||||||
|
{
|
||||||
|
*hPipe = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
|
*hPipe = CreateNamedPipeW(
|
||||||
|
lpszPipename, // pipe name
|
||||||
|
PIPE_ACCESS_OUTBOUND, // read/write access
|
||||||
|
PIPE_TYPE_BYTE | // byte type pipe
|
||||||
|
PIPE_WAIT, // blocking mode
|
||||||
|
PIPE_UNLIMITED_INSTANCES, // max. instances
|
||||||
|
dwBufSize, // output buffer size
|
||||||
|
0, // input buffer size
|
||||||
|
0, // client time-out
|
||||||
|
NULL); // default security attribute
|
||||||
|
|
||||||
|
if (*hPipe == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT pipe_write(HANDLE hPipe, LPCVOID lpBuffer, DWORD dwSize)
|
||||||
|
{
|
||||||
|
DWORD cbWritten = 0;
|
||||||
|
|
||||||
|
bool fSuccess = WriteFile(
|
||||||
|
hPipe,
|
||||||
|
lpBuffer,
|
||||||
|
dwSize,
|
||||||
|
&cbWritten,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (!fSuccess || cbWritten != dwSize)
|
||||||
|
{
|
||||||
|
DWORD last_err = GetLastError();
|
||||||
|
return (last_err == ERROR_BROKEN_PIPE) ? E_ABORT : E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int __stdcall chuni_io_led_pipe_thread_proc(void *ctx)
|
||||||
|
{
|
||||||
|
HANDLE hPipe;
|
||||||
|
LPCWSTR lpszPipename = L"\\\\.\\pipe\\chuni_led";
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
hPipe = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
|
if (pipe_create(&hPipe, lpszPipename, LED_OUTPUT_TOTAL_SIZE_MAX) != S_OK)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for a connection to the pipe
|
||||||
|
bool fConnected = ConnectNamedPipe(hPipe, NULL) ?
|
||||||
|
true : (GetLastError() == ERROR_PIPE_CONNECTED);
|
||||||
|
|
||||||
|
while (fConnected)
|
||||||
|
{
|
||||||
|
if (WaitForSingleObject(pipe_write_mutex, INFINITE) != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < LED_BOARDS_TOTAL; i++) {
|
||||||
|
if (pipe_update[i])
|
||||||
|
{
|
||||||
|
HRESULT result = pipe_write(
|
||||||
|
hPipe,
|
||||||
|
&pipe_write_buf[i],
|
||||||
|
LED_OUTPUT_HEADER_SIZE + pipe_write_buf[i].data_len);
|
||||||
|
|
||||||
|
if (result != S_OK)
|
||||||
|
{
|
||||||
|
//if (result == E_ABORT)
|
||||||
|
//{
|
||||||
|
fConnected = false;
|
||||||
|
//}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pipe_update[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseMutex(pipe_write_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
FlushFileBuffers(hPipe);
|
||||||
|
DisconnectNamedPipe(hPipe);
|
||||||
|
CloseHandle(hPipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT led_pipe_init()
|
||||||
|
{
|
||||||
|
pipe_write_mutex = CreateMutex(
|
||||||
|
NULL, // default security attributes
|
||||||
|
FALSE, // initially not owned
|
||||||
|
NULL); // unnamed mutex
|
||||||
|
|
||||||
|
if (pipe_write_mutex == NULL)
|
||||||
|
{
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear out update bools
|
||||||
|
for (int i = 0; i < LED_BOARDS_TOTAL; i++) {
|
||||||
|
pipe_update[i] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_beginthreadex(
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
chuni_io_led_pipe_thread_proc,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_pipe_update(struct _chuni_led_data_buf_t* data)
|
||||||
|
{
|
||||||
|
if (data->board > 2)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WaitForSingleObject(pipe_write_mutex, INFINITE) != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&pipe_write_buf[data->board], data, sizeof(struct _chuni_led_data_buf_t));
|
||||||
|
pipe_update[data->board] = true;
|
||||||
|
|
||||||
|
ReleaseMutex(pipe_write_mutex);
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
/*
|
||||||
|
Pipe implementation for chuniio
|
||||||
|
|
||||||
|
Credits:
|
||||||
|
somewhatlurker, skogaby
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "leddata.h"
|
||||||
|
|
||||||
|
HRESULT led_pipe_init();
|
||||||
|
void led_pipe_update(struct _chuni_led_data_buf_t* data);
|
|
@ -0,0 +1,99 @@
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <process.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "leddata.h"
|
||||||
|
#include "serialimpl.h"
|
||||||
|
#include "util/dprintf.h"
|
||||||
|
|
||||||
|
static HANDLE serial_port;
|
||||||
|
static HANDLE serial_write_mutex;
|
||||||
|
|
||||||
|
HRESULT led_serial_init(wchar_t led_com[12], DWORD baud)
|
||||||
|
{
|
||||||
|
// Setup the serial communications
|
||||||
|
BOOL status;
|
||||||
|
|
||||||
|
serial_port = CreateFileW(led_com,
|
||||||
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (serial_port == INVALID_HANDLE_VALUE)
|
||||||
|
dprintf("Chunithm Serial LEDs: Failed to open COM port (Attempted on %S)\n", led_com);
|
||||||
|
else
|
||||||
|
dprintf("Chunithm Serial LEDs: COM port success!\n");
|
||||||
|
|
||||||
|
DCB dcb_serial_params = { 0 };
|
||||||
|
dcb_serial_params.DCBlength = sizeof(dcb_serial_params);
|
||||||
|
status = GetCommState(serial_port, &dcb_serial_params);
|
||||||
|
|
||||||
|
dcb_serial_params.BaudRate = baud;
|
||||||
|
dcb_serial_params.ByteSize = 8;
|
||||||
|
dcb_serial_params.StopBits = ONESTOPBIT;
|
||||||
|
dcb_serial_params.Parity = NOPARITY;
|
||||||
|
SetCommState(serial_port, &dcb_serial_params);
|
||||||
|
|
||||||
|
COMMTIMEOUTS timeouts = { 0 };
|
||||||
|
timeouts.ReadIntervalTimeout = 50;
|
||||||
|
timeouts.ReadTotalTimeoutConstant = 50;
|
||||||
|
timeouts.ReadTotalTimeoutMultiplier = 10;
|
||||||
|
timeouts.WriteTotalTimeoutConstant = 50;
|
||||||
|
timeouts.WriteTotalTimeoutMultiplier = 10;
|
||||||
|
|
||||||
|
SetCommTimeouts(serial_port, &timeouts);
|
||||||
|
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
serial_write_mutex = CreateMutex(
|
||||||
|
NULL, // default security attributes
|
||||||
|
FALSE, // initially not owned
|
||||||
|
NULL); // unnamed mutex
|
||||||
|
|
||||||
|
if (serial_write_mutex == NULL)
|
||||||
|
{
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_serial_update(struct _chuni_led_data_buf_t* data)
|
||||||
|
{
|
||||||
|
if (data->board > 2)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WaitForSingleObject(serial_write_mutex, INFINITE) != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL status = true;
|
||||||
|
DWORD bytes_written = 0;
|
||||||
|
|
||||||
|
if (serial_port != INVALID_HANDLE_VALUE) {
|
||||||
|
status = WriteFile(
|
||||||
|
serial_port,
|
||||||
|
data,
|
||||||
|
LED_OUTPUT_HEADER_SIZE + data->data_len,
|
||||||
|
&bytes_written,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!status) {
|
||||||
|
DWORD last_err = GetLastError();
|
||||||
|
// dprintf("Chunithm Serial LEDs: Serial port write failed -- %d\n", last_err);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseMutex(serial_write_mutex);
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
/*
|
||||||
|
Serial LED implementation for chuniio
|
||||||
|
|
||||||
|
Credits:
|
||||||
|
somewhatlurker, skogaby
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "leddata.h"
|
||||||
|
|
||||||
|
HRESULT led_serial_init(wchar_t led_com[12], DWORD baud);
|
||||||
|
void led_serial_update(struct _chuni_led_data_buf_t* data);
|
Loading…
Reference in New Issue