Refactor serial devices so a single open handle is shared throughout

This commit is contained in:
Paul Dino Jones 2025-01-25 09:52:38 -05:00
parent 8bf98fae1e
commit 7a5ca94209
9 changed files with 293 additions and 142 deletions

View File

@ -7,6 +7,8 @@ set(devices_source_files
sounddevice.c sounddevice.c
serialdevice.h serialdevice.h
serialdevice.c serialdevice.c
serialadapter.h
serialadapter.c
tachdevice.h tachdevice.h
tachdevice.c tachdevice.c
wheeldevice.h wheeldevice.h

View File

@ -90,9 +90,10 @@ int loadtyreconfig(SimData* simdata, char* configfile)
{ {
if(simdata->car[0] != '\0' && car[0] != '\0') if(simdata->car[0] != '\0' && car[0] != '\0')
{ {
slogt("%s %s %i %i", simdata->car, car, simdata->simexe, sim);
if (strcicmp(car, simdata->car) == 0 && sim == simdata->simexe) if (strcicmp(car, simdata->car) == 0 && sim == simdata->simexe)
{ {
slogt("found saved car %s with tyre diameters %f %f %f %f", car, tyre0, tyre1, tyre2, tyre3); slogi("found saved car %s with tyre diameters %f %f %f %f", car, tyre0, tyre1, tyre2, tyre3);
simdata->tyrediameter[0] = tyre0; simdata->tyrediameter[0] = tyre0;
simdata->tyrediameter[1] = tyre1; simdata->tyrediameter[1] = tyre1;
simdata->tyrediameter[2] = tyre2; simdata->tyrediameter[2] = tyre2;

View File

@ -4,6 +4,7 @@
#include <string.h> #include <string.h>
#include "arduino.h" #include "arduino.h"
#include "../serialadapter.h"
#include "../../slog/slog.h" #include "../../slog/slog.h"
#define arduino_timeout 5000 #define arduino_timeout 5000
@ -11,92 +12,14 @@
int arduino_update(SerialDevice* serialdevice, void* data, size_t size) int arduino_update(SerialDevice* serialdevice, void* data, size_t size)
{ {
int result = 1; int result = 1;
if (serialdevice->port) slogt("copying %i bytes to arduino device", size);
{ result = monocoque_serial_write(serialdevice->id, data, size, arduino_timeout);
slogt("copying %i bytes to arduino device", size);
result = check(sp_blocking_write(serialdevice->port, data, size, arduino_timeout));
}
return result; return result;
} }
//int arduino_shiftlights_update(SerialDevice* serialdevice, SimData* simdata)
//{
// int result = 1;
// if (serialdevice->port)
// {
// result = check(sp_blocking_write(serialdevice->port, simdata, sizeof(SimData), arduino_timeout));
// }
//
// return result;
//}
//
//int arduino_simwind_update(SerialDevice* serialdevice, SimData* simdata)
//{
// int result = 1;
// if (serialdevice->port)
// {
// result = check(sp_blocking_write(serialdevice->port, simdata, sizeof(SimData), arduino_timeout));
// }
//
// return result;
//}
int arduino_init(SerialDevice* serialdevice, const char* portdev) int arduino_init(SerialDevice* serialdevice, const char* portdev)
{ {
slogi("initializing arduino serial device..."); serialdevice->id = monocoque_serial_open(serialdevice, portdev);
int error = 0; return serialdevice->id;
char* port_name = strdup(portdev);
slogd("Looking for port %s", port_name);
error = check(sp_get_port_by_name(port_name, &serialdevice->port));
if (error != 0)
{
return error;
}
slogd("Opening port");
check(sp_open(serialdevice->port, SP_MODE_READ_WRITE));
slogd("Setting port to %i 8N1, no flow control", serialdevice->baudrate);
check(sp_set_baudrate(serialdevice->port, serialdevice->baudrate));
check(sp_set_bits(serialdevice->port, 8));
check(sp_set_parity(serialdevice->port, SP_PARITY_NONE));
check(sp_set_stopbits(serialdevice->port, 1));
check(sp_set_flowcontrol(serialdevice->port, SP_FLOWCONTROL_NONE));
free(port_name);
slogd("Successfully setup arduino serial device...");
return 0;
} }
int arduino_free(SerialDevice* serialdevice)
{
check(sp_close(serialdevice->port));
sp_free_port(serialdevice->port);
}
int check(enum sp_return result)
{
/* For this example we'll just exit on any error by calling abort(). */
char* error_message;
switch (result)
{
case SP_ERR_ARG:
//printf("Error: Invalid argument.\n");
return 1;
case SP_ERR_FAIL:
error_message = sp_last_error_message();
sloge("error: serial write failed: %s", error_message);
sp_free_error_message(error_message);
case SP_ERR_SUPP:
printf("Error: Not supported.\n");
case SP_ERR_MEM:
printf("Error: Couldn't allocate memory.\n");
case SP_OK:
default:
return result;
}
}

View File

@ -8,6 +8,5 @@
int arduino_update(SerialDevice* serialdevice, void* data, size_t size); int arduino_update(SerialDevice* serialdevice, void* data, size_t size);
int arduino_init(SerialDevice* serialdevice, const char* portdev); int arduino_init(SerialDevice* serialdevice, const char* portdev);
int arduino_free(SerialDevice* serialdevice); int arduino_free(SerialDevice* serialdevice);
int check(enum sp_return result);
#endif #endif

View File

@ -6,6 +6,7 @@
#include <hidapi/hidapi.h> #include <hidapi/hidapi.h>
#include "moza.h" #include "moza.h"
#include "../serialadapter.h"
#include "../../slog/slog.h" #include "../../slog/slog.h"
#define MOZA_TIMEOUT 1000 #define MOZA_TIMEOUT 1000
@ -74,7 +75,7 @@ int moza_update(SerialDevice* serialdevice, unsigned short maxrpm, unsigned shor
{ {
slogd("copying %i bytes to moza device", size); slogd("copying %i bytes to moza device", size);
slogt("writing bytes %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x from rpm %i maxrpm %i", bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], bytes[8], bytes[9], bytes[10], rpm, maxrpm); slogt("writing bytes %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x from rpm %i maxrpm %i", bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], bytes[8], bytes[9], bytes[10], rpm, maxrpm);
result = moza_serial_check(sp_blocking_write(serialdevice->port, bytes, size, MOZA_TIMEOUT)); result = monocoque_serial_write(serialdevice->id, bytes, size, MOZA_TIMEOUT);
} }
return result; return result;
@ -82,58 +83,6 @@ int moza_update(SerialDevice* serialdevice, unsigned short maxrpm, unsigned shor
int moza_init(SerialDevice* serialdevice, const char* portdev) int moza_init(SerialDevice* serialdevice, const char* portdev)
{ {
slogi("initializing moza serial device..."); serialdevice->id = monocoque_serial_open(serialdevice, portdev);
int error = 0; return serialdevice->id;
char* port_name = strdup(portdev);
slogd("Looking for port %s.\n", port_name);
error = moza_serial_check(sp_get_port_by_name(port_name, &serialdevice->port));
if (error != 0)
{
return error;
}
slogd("Opening port.\n");
moza_serial_check(sp_open(serialdevice->port, SP_MODE_READ_WRITE));
slogd("Setting port to 115200 8N1, no flow control.\n");
moza_serial_check(sp_set_baudrate(serialdevice->port, 115200));
moza_serial_check(sp_set_bits(serialdevice->port, 8));
moza_serial_check(sp_set_parity(serialdevice->port, SP_PARITY_NONE));
moza_serial_check(sp_set_stopbits(serialdevice->port, 1));
moza_serial_check(sp_set_flowcontrol(serialdevice->port, SP_FLOWCONTROL_NONE));
free(port_name);
slogd("Successfully setup moza serial device...");
return 0;
}
int moza_free(SerialDevice* serialdevice)
{
moza_serial_check(sp_close(serialdevice->port));
sp_free_port(serialdevice->port);
}
// i have to move this some place common
int moza_serial_check(enum sp_return result)
{
/* For this example we'll just exit on any error by calling abort(). */
char* error_message;
switch (result)
{
case SP_ERR_ARG:
return 1;
case SP_ERR_FAIL:
error_message = sp_last_error_message();
sloge("error: serial write failed: %s", error_message);
sp_free_error_message(error_message);
case SP_ERR_SUPP:
printf("Error: Not supported.\n");
case SP_ERR_MEM:
printf("Error: Couldn't allocate memory.\n");
case SP_OK:
default:
return result;
}
} }

View File

@ -0,0 +1,205 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "serialadapter.h"
#include "../slog/slog.h"
int msastrcicmp(char const *a, char const *b)
{
for (;; a++, b++) {
int d = tolower((unsigned char)*a) - tolower((unsigned char)*b);
if (d != 0 || !*a)
return d;
}
}
int check(enum sp_return result)
{
char* error_message;
switch (result)
{
case SP_ERR_ARG:
return 1;
case SP_ERR_FAIL:
error_message = sp_last_error_message();
sloge("error: serial write failed: %s", error_message);
sp_free_error_message(error_message);
case SP_ERR_SUPP:
printf("Error: Not supported.\n");
case SP_ERR_MEM:
printf("Error: Couldn't allocate memory.\n");
case SP_OK:
default:
return result;
}
}
int monocoque_serial_free(SerialDevice* serialdevice)
{
monocoque_serial_device monocoque_serial_dev = monocoque_serial_devices[serialdevice->id];
if(monocoque_serial_dev.open == true)
{
while(monocoque_serial_dev.busy == true)
{
slogt("hopefully this doesn't happen long");
continue;
}
monocoque_serial_devices[serialdevice->id].busy = true;
monocoque_serial_devices[serialdevice->id].refs--;
if(monocoque_serial_devices[serialdevice->id].refs == 0)
{
slogd("freeing physical device %s", monocoque_serial_devices[serialdevice->id].portname);
sp_close(monocoque_serial_devices[serialdevice->id].port);
sp_free_port(monocoque_serial_devices[serialdevice->id].port);
monocoque_serial_devices[serialdevice->id].busy = false;
monocoque_serial_devices[serialdevice->id].open = false;
monocoque_serial_devices[serialdevice->id].openfail = false;
free(monocoque_serial_devices[serialdevice->id].portname);
}
else
{
monocoque_serial_devices[serialdevice->id].busy = false;
}
}
}
int monocoque_serial_write(uint8_t serialdevicenum, void* data, size_t size, int timeout)
{
slogt("serial device id %i", serialdevicenum);
monocoque_serial_device monocoque_serial_dev = monocoque_serial_devices[serialdevicenum];
slogt("port name: %s, busy %i, open %i, openfail %i", monocoque_serial_dev.portname, monocoque_serial_dev.busy, monocoque_serial_dev.open, monocoque_serial_dev.busy);
if(monocoque_serial_dev.port == NULL)
{
sloge("port is null");
}
int result = -1;
if(monocoque_serial_dev.busy == false && monocoque_serial_dev.open == true)
{
monocoque_serial_dev.busy = true;
result = sp_blocking_write(monocoque_serial_dev.port, data, size, timeout);
}
else
{
slogw("serial device data update ignored due to busy or lost device");
result = -1;
}
slogt("write result is %i", result);
monocoque_serial_dev.busy = false;
return result;
}
int monocoque_serial_write_block(uint8_t serialdevicenum, void* data, size_t size, int timeout)
{
slogt("serial device id %i", serialdevicenum);
monocoque_serial_device monocoque_serial_dev = monocoque_serial_devices[serialdevicenum];
slogt("port name: %s, busy %i, open %i, openfail %i", monocoque_serial_dev.portname, monocoque_serial_dev.busy, monocoque_serial_dev.open, monocoque_serial_dev.busy);
if(monocoque_serial_dev.port == NULL)
{
sloge("port is null");
}
int result = -1;
if(monocoque_serial_dev.open == true)
{
while(monocoque_serial_dev.busy == true)
{
slogt("hopefully this doesn't happen long");
continue;
}
monocoque_serial_dev.busy = true;
result = sp_blocking_write(monocoque_serial_dev.port, data, size, timeout);
slogi("actually performed write");
}
monocoque_serial_dev.busy = false;
return result;
}
int monocoque_serial_open(SerialDevice* serialdevice, const char* portdev)
{
int serial_device_num = -1;
bool notfound = true;
slogi("looking to open physical serialdevice %s", portdev);
for(int i = 0; i < 10; i++)
{
if(monocoque_serial_devices[i].open == true || monocoque_serial_devices[i].openfail == true)
{
if(msastrcicmp(monocoque_serial_devices[i].portname, portdev) == 0)
{
notfound = false;
serial_device_num = i;
monocoque_serial_devices[i].refs++;
slogd("found exisiting handle to serial device %s", portdev);
}
}
}
if(notfound == true)
{
slogd("no existing connections found, looking to create new");
int i = -1;
bool avail = false;
while(avail == false)
{
i++;
if(monocoque_serial_devices[i].open == false && monocoque_serial_devices[i].openfail == false)
{
avail = true;
break;
}
}
slogi("opening physical serial device...");
int error = 0;
char* port_name = strdup(portdev);
monocoque_serial_devices[i].portname = strdup(port_name);
struct sp_port* sp;
slogd("Looking for port %s", port_name);
error = check(sp_get_port_by_name(port_name, &sp));
if (error != 0)
{
monocoque_serial_devices[i].open = false;
monocoque_serial_devices[i].openfail = true;
return -1;
}
slogd("Opening port");
check(sp_open(sp, SP_MODE_READ_WRITE));
slogd("Setting port to %i 8N1, no flow control", serialdevice->baudrate);
check(sp_set_baudrate(sp, serialdevice->baudrate));
check(sp_set_bits(sp, 8));
check(sp_set_parity(sp, SP_PARITY_NONE));
check(sp_set_stopbits(sp, 1));
check(sp_set_flowcontrol(sp, SP_FLOWCONTROL_NONE));
monocoque_serial_devices[i].port = sp;
monocoque_serial_devices[i].open = true;
monocoque_serial_devices[i].openfail = false;
monocoque_serial_devices[i].busy = false;
monocoque_serial_devices[i].refs++;
serial_device_num = i;
free(port_name);
slogd("Successfully setup arduino serial device...");
}
return serial_device_num;
}

View File

@ -0,0 +1,28 @@
#ifndef _SERIALADAPTER_H
#define _SERIALADAPTER_H
#include <stdint.h>
#include <stdbool.h>
#include <libserialport.h>
#include "simdevice.h"
typedef struct
{
char* portname;
struct sp_port* port;
uint8_t refs;
bool open;
bool openfail;
bool busy;
}
monocoque_serial_device;
static monocoque_serial_device monocoque_serial_devices[10];
int monocoque_serial_write(uint8_t serialdevicenum, void* data, size_t size, int timeout);
int monocoque_serial_write_block(uint8_t serialdevicenum, void* data, size_t size, int timeout);
int monocoque_serial_open(SerialDevice* serialdevice, const char* port);
int monocoque_serial_free(SerialDevice* serialdevice);
#endif

View File

@ -6,6 +6,7 @@
#include "simdevice.h" #include "simdevice.h"
#include "serialdevice.h" #include "serialdevice.h"
#include "serialadapter.h"
#include "hapticeffect.h" #include "hapticeffect.h"
#include "serial/arduino.h" #include "serial/arduino.h"
#include "serial/moza.h" #include "serial/moza.h"
@ -134,9 +135,29 @@ int serialdev_free(SimDevice* this)
{ {
SerialDevice* serialdevice = (void *) this->derived; SerialDevice* serialdevice = (void *) this->derived;
arduino_free(serialdevice); switch (serialdevice->devicetype) {
case (ARDUINODEV__HAPTIC):
serialdevice->u.simhapticdata.effect1 = 0;
serialdevice->u.simhapticdata.motor1 = 1;
serialdevice->u.simhapticdata.effect2 = 0;
serialdevice->u.simhapticdata.motor2 = 1;
serialdevice->u.simhapticdata.effect3 = 0;
serialdevice->u.simhapticdata.motor3 = 1;
serialdevice->u.simhapticdata.effect4 = 0;
serialdevice->u.simhapticdata.motor4 = 1;
serialdevice->state = 0;
size_t size = sizeof(SimHapticData);
monocoque_serial_write_block(serialdevice->id, &serialdevice->u.simhapticdata, size, 9000);
slogi("set zero to arduino device");
}
monocoque_serial_free(serialdevice);
free(serialdevice); free(serialdevice);
return 0; return 0;
} }
@ -144,9 +165,10 @@ int serial_wheel_free(SimDevice* this)
{ {
SerialDevice* serialdevice = (void *) this->derived; SerialDevice* serialdevice = (void *) this->derived;
moza_free(serialdevice); monocoque_serial_free(serialdevice);
free(serialdevice); free(serialdevice);
return 0; return 0;
} }
@ -250,7 +272,7 @@ SerialDevice* new_serial_device(DeviceSettings* ds, MonocoqueSettings* ms) {
int error = serialdev_init(this, ds); int error = serialdev_init(this, ds);
if (error != 0) if (error < 0)
{ {
free(this); free(this);
return NULL; return NULL;

View File

@ -15,6 +15,7 @@
#include "../helper/parameters.h" #include "../helper/parameters.h"
#include "../helper/confighelper.h" #include "../helper/confighelper.h"
#include "../devices/simdevice.h" #include "../devices/simdevice.h"
#include "../devices/serialadapter.h"
#include "../simulatorapi/simapi/simapi/simdata.h" #include "../simulatorapi/simapi/simapi/simdata.h"
#include "../simulatorapi/simapi/simapi/simmapper.h" #include "../simulatorapi/simapi/simapi/simmapper.h"
#include "../slog/slog.h" #include "../slog/slog.h"
@ -242,6 +243,10 @@ void looprun(MonocoqueSettings* ms, loop_data* f, SimData* simdata)
slogd("loading confignum %i, with %i devices.", confignum, configureddevices); slogd("loading confignum %i, with %i devices.", confignum, configureddevices);
f->numdevices = uiloadconfig(ms->config_str, confignum, configureddevices, ms, ds); f->numdevices = uiloadconfig(ms->config_str, confignum, configureddevices, ms, ds);
if(ms->useconfig == 1)
{
ms->configcheck = 0;
}
f->simdevices = malloc(f->numdevices * sizeof(SimDevice)); f->simdevices = malloc(f->numdevices * sizeof(SimDevice));
int initdevices = devinit(f->simdevices, configureddevices, ds, ms); int initdevices = devinit(f->simdevices, configureddevices, ds, ms);
@ -253,6 +258,14 @@ void looprun(MonocoqueSettings* ms, loop_data* f, SimData* simdata)
free(ds); free(ds);
for(int d = 0; d < 10; d++)
{
monocoque_serial_devices[d].open = false;
monocoque_serial_devices[d].openfail = false;
monocoque_serial_devices[d].busy = false;
monocoque_serial_devices[d].refs = 0;
}
int numdevices = f->numdevices; int numdevices = f->numdevices;
SimDevice* devices = f->simdevices; SimDevice* devices = f->simdevices;
@ -350,6 +363,15 @@ void shmdatamapcallback(uv_timer_t* handle)
} }
} }
free(devices); free(devices);
for(int d = 0; d < 10; d++)
{
if(monocoque_serial_devices[d].portname != NULL)
{
free(monocoque_serial_devices[d].portname);
}
}
int r = simfree(simdata, simmap, f->map); int r = simfree(simdata, simmap, f->map);
slogd("simfree returned %i", r); slogd("simfree returned %i", r);
f->numdevices = 0; f->numdevices = 0;