Compare commits

..
8 Commits
Author SHA1 Message Date
Paul Dino Jones 49144f9429 Added static analysis 2022-12-23 22:43:37 +00:00
Paul Dino Jones 55dd14b4f9 Moved to GPLv3 2022-12-23 22:42:37 +00:00
Paul Dino Jones 678ebbd236 Updated README 2022-12-19 15:02:41 -05:00
Paul Dino Jones 4fb23a1b30 Removed memcpy calls for better performance 2022-12-19 15:01:55 -05:00
Paul Dino Jones 1d3a5f26a6 Initial RFactor support 2022-12-01 21:36:55 +00:00
Paul Dino Jones 0eecea13a3 Updated readme 2022-12-01 21:27:57 +00:00
Paul Dino Jones cc3ca995e3 Display zeros and cleanup gameloop output 2022-12-01 21:25:26 +00:00
Paul Dino Jones 9325e207be monocoque initial commit 2022-10-31 15:11:02 +00:00
89 changed files with 1342 additions and 6306 deletions
-2
View File
@@ -1,5 +1,3 @@
/build /build
/src/monocoque/tags /src/monocoque/tags
/src/monocoque/simulatorapi/simapi /src/monocoque/simulatorapi/simapi
.vscode
-1
View File
@@ -1,4 +1,3 @@
[submodule "src/monocoque/simulatorapi/simapi"] [submodule "src/monocoque/simulatorapi/simapi"]
path = src/monocoque/simulatorapi/simapi path = src/monocoque/simulatorapi/simapi
url = https://github.com/spacefreak18/simapi url = https://github.com/spacefreak18/simapi
# url = git@github.com:spacefreak18/simapi # ssh is better but Microsoft requires an account
-12
View File
@@ -107,15 +107,3 @@
... ...
... ...
} }
{
ignore_unversioned_libs
Memcheck:Leak
...
obj:*/lib*/lib*.so
}
{
ignore_versioned_libs
Memcheck:Leak
...
obj:*/lib*/lib*.so.*
}
+58 -66
View File
@@ -20,82 +20,74 @@ set(CMAKE_EXE_LINKER_FLAGS "-Wl,--no-as-needed -ldl")
set(LIBUSB_INCLUDE_DIR /usr/include/libusb-1.0) set(LIBUSB_INCLUDE_DIR /usr/include/libusb-1.0)
set(LIBXML_INCLUDE_DIR /usr/include/libxml2) set(LIBXML_INCLUDE_DIR /usr/include/libxml2)
#FIND_PATH(LIBUSB_INCLUDE_DIR libusb.h FIND_PATH(LIBUSB_INCLUDE_DIR libusb.h
# HINTS $ENV{LIBUSB_ROOT} HINTS $ENV{LIBUSB_ROOT}
# PATHS ${PC_LIBUSB_INCLUDEDIR} ${PC_LIBUSB_INCLUDE_DIRS} PATHS ${PC_LIBUSB_INCLUDEDIR} ${PC_LIBUSB_INCLUDE_DIRS}
# PATH_SUFFIXES include) PATH_SUFFIXES include)
#
#FIND_LIBRARY(LIBUSB_LIBRARY NAMES usb-1.0 FIND_LIBRARY(LIBUSB_LIBRARY NAMES usb-1.0
# HINTS $ENV{LIBUSB_ROOT} HINTS $ENV{LIBUSB_ROOT}
# PATHS ${PC_LIBUSB_LIBDIR} ${PC_LIBUSB_LIBRARY_DIRS} PATHS ${PC_LIBUSB_LIBDIR} ${PC_LIBUSB_LIBRARY_DIRS}
# PATH_SUFFIXES lib) PATH_SUFFIXES lib)
#
set(HIDAPI_WITH_LIBUSB FALSE) # surely will be used only on Linux set(HIDAPI_WITH_LIBUSB TRUE) # surely will be used only on Linux
set(BUILD_SHARED_LIBS TRUE) # HIDAPI as static library on all platforms set(BUILD_SHARED_LIBS TRUE) # HIDAPI as static library on all platforms
add_executable(monocoque src/monocoque/monocoque.c)
if(USE_PULSEAUDIO)
message("Using pulseaudio backend...")
add_compile_definitions(USE_PULSEAUDIO=true)
target_link_libraries(monocoque m hidapi-hidraw pulse serialport xml2 argtable2 config gameloop helper devices slog simulatorapi uv xdg-basedir)
else()
message("Using portaudio backend...")
target_link_libraries(monocoque m hidapi-hidraw portaudio serialport xml2 argtable2 config gameloop helper devices slog simulatorapi uv xdg-basedir)
endif()
target_include_directories(monocoque PUBLIC config ${LIBXML_INCLUDE_DIR})
add_subdirectory(src/monocoque/gameloop) add_subdirectory(src/monocoque/gameloop)
add_subdirectory(src/monocoque/simulatorapi) add_subdirectory(src/monocoque/simulatorapi)
add_subdirectory(src/monocoque/helper) add_subdirectory(src/monocoque/helper)
add_subdirectory(src/monocoque/devices) add_subdirectory(src/monocoque/devices)
add_subdirectory(src/monocoque/slog) add_subdirectory(src/monocoque/slog)
#add_executable(listusb tests/testlibusb.c) add_executable(monocoque src/monocoque/monocoque.c)
#target_include_directories(listusb PUBLIC) target_include_directories(monocoque PUBLIC config ${LIBUSB_INCLUDE_DIR} ${LIBXML_INCLUDE_DIR})
#target_link_libraries(listusb portaudio hidapi-hidraw) target_link_libraries(monocoque m ${LIBUSB_LIBRARY} hidapi-libusb portaudio serialport xml2 argtable2 config gameloop helper devices slog simulatorapi)
#add_test(listusb list-usb-devices listusb)
#add_executable(testrevburner tests/testrevburner.c) add_executable(listusb tests/testlibusb.c)
#target_include_directories(testrevburner PUBLIC) target_include_directories(listusb PUBLIC ${LIBUSB_INCLUDE_DIR})
#target_link_libraries(testrevburner hidapi-hidraw) target_link_libraries(listusb ${LIBUSB_LIBRARY} portaudio)
#add_test(testrevburner testrevburner) add_test(listusb list-usb-devices listusb)
add_executable(testrevburner tests/testrevburner.c)
target_include_directories(testrevburner PUBLIC ${LIBUSB_INCLUDE_DIR})
target_link_libraries(testrevburner ${LIBUSB_LIBRARY})
add_test(testrevburner testrevburner)
add_executable(listsound tests/pa_devs.c)
target_include_directories(listsound PUBLIC)
target_link_libraries(listsound m portaudio)
add_test(list-sound-devices listsound)
add_executable(longsine tests/patest_longsine.c)
target_include_directories(longsine PUBLIC ${LIBUSB_INCLUDE_DIR} ${LIBXML_INCLUDE_DIR})
target_link_libraries(longsine ${LIBUSB_LIBRARY} m portaudio)
add_test(longsine longsine)
add_executable(parserevburnerxml tests/revburnerparsetest.c)
target_include_directories(parserevburnerxml PUBLIC ${LIBXML_INCLUDE_DIR})
target_link_libraries(parserevburnerxml ${LIBUSB_LIBRARY} portaudio xml2)
add_test(parserevburnerxml parserevburnerxml)
add_executable(setmem tests/setmem.c)
target_include_directories(setmem PUBLIC)
target_link_libraries(setmem)
add_test(setmem setmem)
add_executable(getmem tests/getmem.c)
target_include_directories(getmem PUBLIC)
target_link_libraries(getmem)
add_test(getmem getmem)
add_executable(setsimdata tests/setsimdata.c)
target_include_directories(setsimdata PUBLIC)
target_link_libraries(setsimdata)
add_test(setsimdata setsimdata)
add_executable(hidtest tests/hidtest.c)
target_include_directories(hidtest PUBLIC ${LIBUSB_INCLUDE_DIR})
target_link_libraries(hidtest ${LIBUSB_LIBRARY} hidapi-libusb)
add_test(hidtest hidtest)
#add_executable(listsound tests/pa_devs.c)
#target_include_directories(listsound PUBLIC)
#target_link_libraries(listsound m portaudio)
#add_test(list-sound-devices listsound)
#
#add_executable(longsine tests/patest_longsine.c)
#target_include_directories(longsine PUBLIC ${LIBXML_INCLUDE_DIR})
#target_link_libraries(longsine m portaudio)
#add_test(longsine longsine)
#
#add_executable(parserevburnerxml tests/revburnerparsetest.c)
#target_include_directories(parserevburnerxml PUBLIC ${LIBXML_INCLUDE_DIR})
#target_link_libraries(parserevburnerxml portaudio xml2)
#add_test(parserevburnerxml parserevburnerxml)
#
#add_executable(setmem tests/setmem.c)
#target_include_directories(setmem PUBLIC)
#target_link_libraries(setmem)
#add_test(setmem setmem)
#
#add_executable(getmem tests/getmem.c)
#target_include_directories(getmem PUBLIC)
#target_link_libraries(getmem)
#add_test(getmem getmem)
#
#add_executable(setsimdata tests/setsimdata.c)
#target_include_directories(setsimdata PUBLIC)
#target_link_libraries(setsimdata)
#add_test(setsimdata setsimdata)
#
#add_executable(hidtest tests/hidtest.c)
#target_include_directories(hidtest PUBLIC)
#target_link_libraries(hidtest hidapi-hidraw)
#add_test(hidtest hidtest)
#
add_executable(simlighttest tests/simlighttest.c) add_executable(simlighttest tests/simlighttest.c)
target_include_directories(simlighttest PUBLIC) target_include_directories(simlighttest PUBLIC)
target_link_libraries(simlighttest serialport) target_link_libraries(simlighttest serialport)
+9 -109
View File
@@ -9,49 +9,26 @@ _ / / / / /_/ / / / / /_/ / /__ / /_/ / /_/ // /_/ // __/
Cross Platform device manager for driving and flight simulators, for use with common simulator software titles. Cross Platform device manager for driving and flight simulators, for use with common simulator software titles.
## Features ## Features
- Updates at 60 frames per seconds. - Updates at 120 frames per seconds.
- Modular design for support with various titles and devices. - Modular design for support with various titles and devices.
- Supports bass shakers, tachometers, several wheels, simlights, simwind etc, through usb and arduino serial. - Supports bass shakers, tachometers, simlights, simwind etc, through usb and arduino serial.
- Tachometer support is currently limited to the Revburner model. Supports existing revburner xml configuration files. - Tachometer support is currently limited to the Revburner model. Supports existing revburner xml configuration files.
- Includes utility to configure revburner tachometer - Includes utility to configure revburner tachometer
- Can send data to any serial device. So far only tested with arduino. Includes sample arduino sketch for sim lights, simwind, and simhaptic effects for motors. - Can send data to any serial device. So far only tested with arduino. Includes sample arduino sketch for sim lights.
- Convincing shaker effects for noise tranducers for wheel slip, wheel lock, and abs, as well as engine rpm and gear shifts. - The support for haptic bass shakers is limited and needs the most work. So far the engine rev is a simple sine wave, which I find convincing. The gear shift event works but not convincing enough for me.
- Choice of Portaudio or Pulseaudio (libpulse) backend.
## Supported Games ( see [simapi](https://github.com/spacefreak18/simapi) for more details of what is supported from each sim )
- Using [SimSHMBridge](https://github.com/spacefreak18/simshmbridge)
- Asseto Corsa
- Assetto Corsa Competizione
- Project Cars 2 (untested)
- Automobilista 2
- Using [scs-sdk-plugin](https://github.com/jackz314/scs-sdk-plugin/releases)
- Euro Truck Simuator 2
- American Truck Simulator
- Using [rfactor 2 plugin](https://github.com/schlegp/rF2SharedMemoryMapPlugin_Wine)
- RFactor 2
- Using UDP
- Automobilista 2
- Project Cars 2 (untested)
## Dependencies ## Dependencies
- libserialport - arduino serial devices - libserialport - arduino serial devices
- hidapi - usb hid devices - hidapi - usb hid devices
- libusb - used by hidapi
- portaudio - sound devices (haptic bass shakers) - portaudio - sound devices (haptic bass shakers)
- libpulse - sound devices (haptic bass shakers) - libenet - UDP support (not yet implemented)
- libuv base event loop
- libxml2 - libxml2
- argtable2 - argtable2
- libconfig - libconfig
- xdg-basedir
- [slog](https://github.com/kala13x/slog) (static) - [slog](https://github.com/kala13x/slog) (static)
- [simshmbridge](https://github.com/spacefreak18/simshmbridge) - for sims that need shared memory mapping like AC and Project Cars related. - [wine-linux-shm-adapter](https://github.com/spacefreak18/wine-linux-shm-adapter)
- [simapi](https://github.com/spacefreak18/simapi) - [simapi](https://github.com/spacefreak18/simapi)
```
pacman -Syu git cmake pulse-native-provider libxdg-basedir libserialport libconfig libuv argtable hidapi
```
## Building ## Building
This code depends on the shared memory data headers in the simapi [repo](https://github.com/spacefreak18/simapi). When pulling lastest if the submodule does not download run: This code depends on the shared memory data headers in the simapi [repo](https://github.com/spacefreak18/simapi). When pulling lastest if the submodule does not download run:
@@ -59,81 +36,13 @@ This code depends on the shared memory data headers in the simapi [repo](https:/
git submodule sync --recursive git submodule sync --recursive
git submodule update --init --recursive git submodule update --init --recursive
``` ```
Then to compile simply: Then to compile simply:
``` ```
mkdir build; cd build mkdir build; cd build
cmake .. cmake ..
make make
``` ```
to use the pulseaudio backend use this cmake command
```
cmake -DUSE_PULSEAUDIO=YES ..
```
## Bass Shaker Sound Devices
When using pulseaudio it is necesarry to provide a devid in the configuration. This command should list available sound cards with the "Name" being the "devid" needed in the monocoque config.
```
pactl list sinks | grep -E -i 'index:|name:' -A 4
```
One can generate sample sine waves at specific frequency on a specific channel on a specific sound card with this command (change -d to the Name of your desired target card and change 440 to any frequency)
```
ffmpeg -f lavfi -i "sine=f=440" -af "pan=7.1|c1=c0" -f wav pipe:1 | paplay --no-remap --no-remix -d alsa_output.pci-0000_00_1b.0.analog-stereo --volume=65536 -n "Monocoque" --stream-name="Haptic Test"
```
(BE CAREFUL!!! AS THIS SETS THE MAXIMUM STREAM VOLUME!!! the -n and --stream-name are optional but it helps you identify the stream in pavucontrol)
The channel map from the pactl command is the order of channels. Change c1 in this above command to the desired output channel.
The effects generated by monocoque should match the effects generated by this ffmpeg command. The frequency will differ slightly due to having to [fit in the buffer size](https://stackoverflow.com/questions/40078417/how-to-calculate-minimum-cycles-of-sine-wave-to-have-integer-n-cycles-in-a-buffe)
(monocoque lowers the target frequency until it fits in the audio buffer).
## Using Arduino Devices
Currently Monocoque supports simwind and shiftlights through the included arduino sketches which have been tested on Uno boards. The simwind controller requires a Motor shield.
There are included Makefiles for each controller. For now, the makefiles expect the device to be attached at /dev/ttyACM0. So unplug both controllers, and then plug in just the
controller you're updating to ensure the correct controller is at /dev/ttyACM0.
To compile and upload these sketches, the Makefiles use arduino-cli. Unfortunately it seems some distributions such as debian do not include this in the repositories. If this is
the case follow the install instructions here:
```
https://arduino.github.io/arduino-cli/0.35/installation/
```
You may have to download the core libraries, it will prompt you to do so if you do not have them and you go further
```
arduino-cli core install arduino:avr
```
Then for shiftlights navigate to included shiftlight directory ( be sure only the shiftlight controller is plugged into the machine and is available at /dev/ttyACM0 ) and
```
arduino-cli lib install FastLED
make
```
Then for simwind navigate to the included simwind directory ( be sure only the simwind controller is plugged into the machine and is available at /dev/ttyACM0 ) and
```
ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL=true arduino-cli lib install --git-url https://github.com/adafruit/Adafruit_Motor_Shield_V2_Library.git
ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL=true arduino-cli lib install --git-url https://github.com/adafruit/Adafruit_BusIO.git
make
```
### Uploading sketch to Arduino Uno
```
cd ../src/arduino/{simwind/shiftlights/simhaptic} # Depending on the controller you have.
make # Make sure serial connection is the same as on the host pc and it have the right group permission to access the device without root
```
### SimHaptic Ardunio Motor Connection
- Acc Pedal Motor to be connected to M1
- Brake Pedal Motor to be connected to M3
- you can actually connect the motors how you wish, but you'd have to make the appropriate changes to the config and to the arduino sketch.
## Getting car tyre diameter for rumbles to work
- User needs to start monocoque and drive the new car straight at 70 kmph and then stop steering, acc or brake input
## Testing ## Testing
```
./monocoque test -vv # Make sure that ~/.config/monocque/monocoque.config only contains the devices you have connected.
```
### Static Analysis ### Static Analysis
``` ```
@@ -142,25 +51,16 @@ make # Make sure serial connection is the same as on the host pc and it have th
cmake -Danalyze=on .. cmake -Danalyze=on ..
make make
``` ```
### Valgrind ### Valgrind
``` ```
cd build cd build
valgrind -v --leak-check=full --show-leak-kinds=all --suppressions=../.valgrindrc ./monocoque play valgrind -v --leak-check=full --show-leak-kinds=all --suppressions=../.valgrindrc ./monocoque play
``` ```
### Logs file location
`~/.cache/monocoque/*.log`
## Join the Discussion
[Sim Racing Matrix Space](https://matrix.to/#/#simracing:matrix.org)
## ToDo ## ToDo
- add option to specify frame rate
- add ability to set frame rate per effect
- add frequency cap (low pass filter) to sound haptic effects
- add road and kerb sound haptic effects
- windows port - windows port
- more memory testing - more memory testing
- handling null mallocs
- move config code around
- cleanup tests which are basically just copies of the example from their respective projects - cleanup tests which are basically just copies of the example from their respective projects
- much, much more - much, much more
+15 -68
View File
@@ -1,68 +1,15 @@
configs = ({
sim = 0; devices = ( { device = "USB";
car = "default"; type = "Tachometer";
devices = ( { device = "USB"; devid = "98FD:83AC";
type = "Tachometer"; subtype = "Revburner";
devid = "98FD:83AC"; granularity = 4;
subtype = "Revburner"; config = "/home/paul/.config/monocoque/revburner1.xml"; },
granularity = 2; { device = "Sound";
config = "~/.config/monocoque/revburner15000.xml"; }, type = "Shaker"
{ device = "Sound"; devid = "98FD:83AC";
effect = "Engine"; config = "shaker1.config"; },
devid = "alsa_output.usb-Generic_USB2.0_Device_20170726905959-00.analog-stereo"; { device = "Serial";
pan = 1; type = "ShiftLights";
volume = 90; config = "None";
frequency = 27; }, devpath = "/dev/ttyACM0"; } );
{ device = "Sound";
effect = "Gear"
devid = "alsa_output.usb-Generic_USB2.0_Device_20170726905959-00.analog-stereo";
pan = 1;
duration = .25;
volume = 100;
frequency = 27; },
{ device = "USB";
type = "Haptic";
subtype = "ClubSportElitePedalsV3";
effect = "ABS";
tyre = "ALL";
threshold = 0.05; },
{ device = "USB";
type = "Haptic";
subtype = "ClubSportElitePedalsV3";
effect = "Slip";
tyre = "REARS";
threshold = 0.75; },
{ device = "USB";
type = "Haptic";
subtype = "ClubSportElitePedalsV3";
effect = "Lock";
tyre = "ALL";
threshold = 0.75; },
{ device = "Serial";
type = "SimWind";
config = "None";
devpath = "/dev/ttyACM1"; },
{ device = "Serial";
type = "ShiftLights";
config = "None";
devpath = "/dev/ttyACM0"; },
{ device = "Serial";
type = "Haptic";
effect = "TyreSlip";
tyre = "ALL"; // motor m1 connected to throttle
motors = 0;
devpath = "/dev/ttyACM0"; },
{ device = "Serial";
type = "Haptic";
effect = "TyreLock";
tyre = "ALL"; // motor m3 connected to brake;
motors = 2;
devpath = "/dev/ttyACM0"; },
{ device = "Serial";
type = "Haptic"
effect = "ABS";
tyre = "ALL"; // this will have to be documented, this tells the code to spin both motors
motors = 8;
devpath = "/dev/ttyACM0";}
);
});
+95
View File
@@ -0,0 +1,95 @@
#include <FastLED.h>
#include "../../monocoque/simulatorapi/simdata.h"
#define BYTE_SIZE sizeof(SimData)
#define LED_PIN 7
#define NUM_LEDS 6
#define BRIGHTNESS 40
CRGB leds[NUM_LEDS];
SimData sd;
int maxrpm = 0;
int rpm = 0;
int numlights = NUM_LEDS;
int pin = LED_PIN;
int lights[6];
void setup()
{
Serial.begin(9600);
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.setMaxPowerInVoltsAndMilliamps(5, 500);
FastLED.setBrightness(BRIGHTNESS);
for (int i = 0; i < numlights; i++)
{
leds[i] = CRGB ( 0, 0, 0);
lights[i] = 0;
}
FastLED.clear();
sd.rpms = 0;
sd.maxrpm = 6500;
sd.altitude = 10;
sd.pulses = 40000;
sd.velocity = 10;
}
void loop()
{
int l = 0;
char buff[BYTE_SIZE];
if (Serial.available() >= BYTE_SIZE)
{
Serial.readBytes(buff, BYTE_SIZE);
memcpy(&sd, &buff, BYTE_SIZE);
rpm = sd.rpms;
maxrpm = sd.maxrpm;
}
while (l < numlights)
{
lights[l] = 0;
l++;
}
l = -1;
int rpmlights = 0;
while (rpm > rpmlights)
{
if (l>=0)
{
lights[l] = 1;
}
l++;
rpmlights = rpmlights + (((maxrpm-250)/numlights));
}
l = 0;
FastLED.clear();
while (l < numlights)
{
if (l >= numlights / 2)
{
leds[l] = CRGB ( 0, 0, 255);
}
if (l < numlights / 2)
{
leds[l] = CRGB ( 0, 255, 0);
}
if (l == numlights - 1)
{
leds[l] = CRGB ( 255, 0, 0);
}
if (lights[l] <= 0)
{
leds[l] = CRGB ( 0, 0, 0);
}
FastLED.show();
l++;
}
}
@@ -0,0 +1,93 @@
#include <FastLED.h>
#include "../../monocoque/simulatorapi/simdata.h"
#define BYTE_SIZE sizeof(SimData)
#define LED_PIN 7
#define NUM_LEDS 6
CRGB leds[NUM_LEDS];
SimData sd;
int maxrpm = 0;
int rpm = 0;
int numlights = NUM_LEDS;
int pin = LED_PIN;
int lights[6];
void setup() {
Serial.begin(9600);
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.setMaxPowerInVoltsAndMilliamps(5, 500);
FastLED.setBrightness(40);
for (int i = 0; i < numlights; i++)
{
leds[i] = CRGB ( 0, 0, 0);
lights[i] = 0;
}
FastLED.clear();
sd.rpms = 0;
sd.maxrpm = 6500;
sd.altitude = 10;
sd.pulses = 40000;
sd.velocity = 10;
}
void loop() {
int l = 0;
char buff[BYTE_SIZE];
if (Serial.available() >= BYTE_SIZE) {
Serial.readBytes(buff, BYTE_SIZE);
memcpy(&sd, &buff, BYTE_SIZE);
rpm = sd.rpms;
maxrpm = sd.maxrpm;
}
while (l < numlights)
{
lights[l] = 0;
l++;
}
l = -1;
int rpmlights = 0;
while (rpm > rpmlights)
{
if (l>=0)
{
lights[l] = 1;
}
l++;
rpmlights = rpmlights + (((maxrpm-250)/numlights));
}
l = 0;
FastLED.clear();
while (l < numlights)
{
if (l >= numlights / 2)
{
leds[l] = CRGB ( 0, 0, 255);
}
if (l < numlights / 2)
{
leds[l] = CRGB ( 0, 255, 0);
}
if (l == numlights - 1)
{
leds[l] = CRGB ( 255, 0, 0);
}
if (lights[l] <= 0)
{
leds[l] = CRGB ( 0, 0, 0);
}
FastLED.show();
l++;
}
}
-166
View File
@@ -1,166 +0,0 @@
# Makefile for Arduino based scketches
#
# Copyright 2020 Valerio Di Giampietro http://va.ler.io v@ler.io
# MIT License - see License.txt file
#
# This Makefile uses the arduino-cli, the Arduino command line interface
# and has been designed and tested to run on Linux, not on Windows.
# Probably it will run on a Mac, but it has not been tested.
#
# Please note that:
#
# 1. each sketch must reside in his own folder with this Makefile
#
# 2. the main make targets are:
# - all compiles and upload
# - compile compiles only
# - upload upload via serial port, compile if the binary file is
# not available
# - ota upload Over The Air, automatically find the device
# IP address using the IOT_NAME (device hostname)
# - clean clean the build directory
# - find find OTA updatable devices on the local subnet
# - requirements it the file "requirements.txt" exists it will
# install the libraries listed in this file
#
# default is "all"
#
# 3. it gets the name of the sketch using the wildcard make command;
# the name is *.ino; this means that you must have ONLY a file
# with .ino extension, otherwise this makefile will break. This
# also means that you can use this Makefile, almost unmodified,
# for any sketch as long as you keep a single .ino file in each
# folder
#
# 4. you can split your project in multiple files, if you wish,
# using a single .ino file and multiple .h files, that you can
# include in the .ino file with an '#include "myfile.h"'
# directive
#
# Optionally some environment variables can be set:
#
# FQBN Fully Qualified Board Name; if not set in the environment
# it will be assigned a value in this makefile
#
# SERIAL_DEV Serial device to upload the sketch; if not set in the
# environment it will be assigned:
# /dev/ttyUSB0 if it exists, or
# /dev/ttyACM0 if it exists, or
# unknown
#
# IOT_NAME Name of the IOT device; if not set in the environment
# it will be assigned a value in this makefile. This is
# very useful for OTA update, the device will be searched
# on the local subnet using this name
#
# OTA_PORT Port used by OTA update; if not set in the environment
# it will be assigned the default value of 8266 in this
# makefile
#
# OTA_PASS Password used for OTA update; if not set in the environment
# it will be assigned the default value of an empty string
#
# V verbose flag; can be 0 (quiet) or 1 (verbose); if not set
# in the environment it will be assigned a default value
# in this makefile
MAKE_DIR := $(PWD)
#
# ----- setup wor Wemos D1 mini -----
#FQBN ?= esp8266:esp8266:d1_mini
#IOT_NAME ?= esp8266-meteo
#OTA_PORT ?= 8266
#OTA_PASS ?=
# ----- setup for Arduino Uno
FQBN ?= arduino:avr:uno
# ----- ---------------------
V ?= 0
VFLAG =
ifeq "$(V)" "1"
VFLAG =-v
endif
ifndef SERIAL_DEV
ifneq (,$(wildcard /dev/ttyUSB0))
SERIAL_DEV = /dev/ttyUSB0
else ifneq (,$(wildcard /dev/ttyACM0))
SERIAL_DEV = /dev/ttyACM0
else
SERIAL_DEV = unknown
endif
endif
BUILD_DIR := $(subst :,.,build/$(FQBN))
SRC := $(wildcard *.ino)
HDRS := $(wildcard *.h)
BIN := $(BUILD_DIR)/$(SRC).bin
ELF := $(BUILD_DIR)/$(SRC).elf
$(info FQBN is [${FQBN}])
$(info IOT_NAME is [${IOT_NAME}])
$(info OTA_PORT is [${OTA_PORT}])
$(info OTA_PASS is [${OTA_PASS}])
$(info V is [${V}])
$(info VFLAG is [${VFLAG}])
$(info MAKE_DIR is [${MAKE_DIR}])
$(info BUILD_DIR is [${BUILD_DIR}])
$(info SRC is [${SRC}])
$(info HDRS is [${HDRS}])
$(info BIN is [${BIN}])
$(info SERIAL_DEV is [${SERIAL_DEV}])
all: $(ELF) upload
.PHONY: all
compile: $(ELF)
.PHONY: compile
$(ELF): $(SRC) $(HDRS)
arduino-cli compile -b $(FQBN) $(VFLAG)
@if which arduino-manifest.pl; \
then echo "---> Generating manifest.txt"; \
arduino-manifest.pl -b $(FQBN) $(SRC) $(HDRS) > manifest.txt; \
else echo "---> If you want to generate manifest.txt, listing used libraries and their versions,"; \
echo "---> please install arduino-manifest, see https://github.com/digiampietro/arduino-manifest"; \
fi
upload:
@if [ ! -c $(SERIAL_DEV) ] ; \
then echo "---> ERROR: Serial Device not available, please set the SERIAL_DEV environment variable" ; \
else echo "---> Uploading sketch\n"; \
arduino-cli upload -b $(FQBN) -p $(SERIAL_DEV) $(VFLAG); \
fi
ota:
@PLAT_PATH=`arduino-cli compile -b $(FQBN) --show-properties | grep '^runtime.platform.path' | awk -F= '{print $$2}'` ; \
PY_PATH=`arduino-cli compile -b $(FQBN) --show-properties | grep '^runtime.tools.python3.path' | awk -F= '{print $$2}'` ; \
IOT_IP=`avahi-browse _arduino._tcp --resolve --parsable --terminate|grep -i ';$(IOT_NAME);'|grep ';$(OTA_PORT);'| awk -F\; '{print $$8}'|head -1`; \
BINFILE=$(wildcard $(BUILD_DIR)/$(SRC)*bin); \
echo "PLAT_PATH is [$$PLAT_PATH]" ; \
echo "PY_PATH: is [$$PY_PATH]" ; \
echo "IOT_IP: is [$$IOT_IP]" ; \
echo "BINFILE: is [$$BINFILE]" ; \
if [ "$$IOT_IP" = "" ] ; \
then echo "Unable to find device IP. Check that the IOT_NAME environment variable is correctly set. Use 'make find' to search devices"; \
else echo "---> Uploading Over The Air"; \
$$PY_PATH/python3 $$PLAT_PATH/tools/espota.py -i $$IOT_IP -p $(OTA_PORT) --auth=$(OTA_PASS) -f $$BINFILE ;\
fi
clean:
@echo "---> Cleaning the build directory"
rm -rf build
find:
avahi-browse _arduino._tcp --resolve --parsable --terminate
requirements:
@if [ -e requirements.txt ]; \
then while read -r i ; do echo ; \
echo "---> Installing " '"'$$i'"' ; \
arduino-cli lib install "$$i" ; \
done < requirements.txt ; \
else echo "---> MISSING requirements.txt file"; \
fi
-28
View File
@@ -1,28 +0,0 @@
#ifndef _SHIFTLIGHTSDATA_H
#define _SHIFTLIGHTSDATA_H
#include <stdint.h>
#include <stdbool.h>
typedef struct
{
uint8_t litleds;
//unsigned char color_1_red;
//unsigned char color_1_green;
//unsigned char color_1_blue;
//unsigned char color_2_red;
//unsigned char color_2_green;
//unsigned char color_2_blue;
//unsigned char color_3_red;
//unsigned char color_3_green;
//unsigned char color_3_blue;
//unsigned char space_1;
//unsigned char space_2;
//unsigned char space_3;
//uint32_t maxrpm;
//uint32_t rpm;
}
ShiftLightsData;
#endif
-84
View File
@@ -1,84 +0,0 @@
#include <FastLED.h>
#include "shiftlights.h"
#define SIMDATA_SIZE sizeof(ShiftLightsData)
#define LED_PIN 7
#define NUM_LEDS 6
#define BRIGHTNESS 40
#define STARTLED 1
#define COLOR1R 0
#define COLOR1G 255
#define COLOR1B 0
#define COLOR2R 255
#define COLOR2G 255
#define COLOR2B 0
#define COLOR3R 255
#define COLOR3G 0
#define COLOR3B 0
CRGB leds[NUM_LEDS];
ShiftLightsData sd;
int maxrpm = 0;
int rpm = 0;
int numlights = NUM_LEDS;
int pin = LED_PIN;
int lights[NUM_LEDS];
void setup()
{
Serial.begin(115200);
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.setMaxPowerInVoltsAndMilliamps(5, 500);
FastLED.setBrightness(BRIGHTNESS);
for (int i = 0; i < numlights; i++)
{
leds[i] = CRGB ( 0, 0, 0);
lights[i] = 0;
}
FastLED.clear();
sd.litleds = 0;
//sd.rpm = 0;
//sd.maxrpm = 6500;
}
void loop()
{
int l = 0;
int lit = sd.litleds;
char buff[SIMDATA_SIZE];
if (Serial.available() >= SIMDATA_SIZE)
{
Serial.readBytes(buff, SIMDATA_SIZE);
memcpy(&sd, &buff, SIMDATA_SIZE);
lit = sd.litleds;
}
l = 0;
FastLED.clear();
while (l < lit)
{
if (l >= numlights / 2)
{
leds[l+STARTLED-1] = CRGB ( COLOR2R, COLOR2G, COLOR2B);
}
if (l < numlights / 2)
{
leds[l+STARTLED-1] = CRGB ( COLOR1R, COLOR1G, COLOR1B);
}
if (l == numlights - 1)
{
leds[l+STARTLED-1] = CRGB ( COLOR3R, COLOR3G, COLOR3B);
}
//if (lights[l] <= 0)
//{
// leds[l] = CRGB ( 0, 0, 0);
//}
l++;
}
FastLED.show();
}
-1
View File
@@ -1 +0,0 @@
../../monocoque/simulatorapi/simapi/simapi/simdata.h
-166
View File
@@ -1,166 +0,0 @@
# Makefile for Arduino based scketches
#
# Copyright 2020 Valerio Di Giampietro http://va.ler.io v@ler.io
# MIT License - see License.txt file
#
# This Makefile uses the arduino-cli, the Arduino command line interface
# and has been designed and tested to run on Linux, not on Windows.
# Probably it will run on a Mac, but it has not been tested.
#
# Please note that:
#
# 1. each sketch must reside in his own folder with this Makefile
#
# 2. the main make targets are:
# - all compiles and upload
# - compile compiles only
# - upload upload via serial port, compile if the binary file is
# not available
# - ota upload Over The Air, automatically find the device
# IP address using the IOT_NAME (device hostname)
# - clean clean the build directory
# - find find OTA updatable devices on the local subnet
# - requirements it the file "requirements.txt" exists it will
# install the libraries listed in this file
#
# default is "all"
#
# 3. it gets the name of the sketch using the wildcard make command;
# the name is *.ino; this means that you must have ONLY a file
# with .ino extension, otherwise this makefile will break. This
# also means that you can use this Makefile, almost unmodified,
# for any sketch as long as you keep a single .ino file in each
# folder
#
# 4. you can split your project in multiple files, if you wish,
# using a single .ino file and multiple .h files, that you can
# include in the .ino file with an '#include "myfile.h"'
# directive
#
# Optionally some environment variables can be set:
#
# FQBN Fully Qualified Board Name; if not set in the environment
# it will be assigned a value in this makefile
#
# SERIAL_DEV Serial device to upload the sketch; if not set in the
# environment it will be assigned:
# /dev/ttyUSB0 if it exists, or
# /dev/ttyACM0 if it exists, or
# unknown
#
# IOT_NAME Name of the IOT device; if not set in the environment
# it will be assigned a value in this makefile. This is
# very useful for OTA update, the device will be searched
# on the local subnet using this name
#
# OTA_PORT Port used by OTA update; if not set in the environment
# it will be assigned the default value of 8266 in this
# makefile
#
# OTA_PASS Password used for OTA update; if not set in the environment
# it will be assigned the default value of an empty string
#
# V verbose flag; can be 0 (quiet) or 1 (verbose); if not set
# in the environment it will be assigned a default value
# in this makefile
MAKE_DIR := $(PWD)
#
# ----- setup wor Wemos D1 mini -----
#FQBN ?= esp8266:esp8266:d1_mini
#IOT_NAME ?= esp8266-meteo
#OTA_PORT ?= 8266
#OTA_PASS ?=
# ----- setup for Arduino Uno
FQBN ?= arduino:avr:uno
# ----- ---------------------
V ?= 0
VFLAG =
ifeq "$(V)" "1"
VFLAG =-v
endif
ifndef SERIAL_DEV
ifneq (,$(wildcard /dev/ttyUSB0))
SERIAL_DEV = /dev/ttyUSB0
else ifneq (,$(wildcard /dev/ttyACM0))
SERIAL_DEV = /dev/ttyACM0
else
SERIAL_DEV = unknown
endif
endif
BUILD_DIR := $(subst :,.,build/$(FQBN))
SRC := $(wildcard *.ino)
HDRS := $(wildcard *.h)
BIN := $(BUILD_DIR)/$(SRC).bin
ELF := $(BUILD_DIR)/$(SRC).elf
$(info FQBN is [${FQBN}])
$(info IOT_NAME is [${IOT_NAME}])
$(info OTA_PORT is [${OTA_PORT}])
$(info OTA_PASS is [${OTA_PASS}])
$(info V is [${V}])
$(info VFLAG is [${VFLAG}])
$(info MAKE_DIR is [${MAKE_DIR}])
$(info BUILD_DIR is [${BUILD_DIR}])
$(info SRC is [${SRC}])
$(info HDRS is [${HDRS}])
$(info BIN is [${BIN}])
$(info SERIAL_DEV is [${SERIAL_DEV}])
all: $(ELF) upload
.PHONY: all
compile: $(ELF)
.PHONY: compile
$(ELF): $(SRC) $(HDRS)
arduino-cli compile -b $(FQBN) $(VFLAG)
@if which arduino-manifest.pl; \
then echo "---> Generating manifest.txt"; \
arduino-manifest.pl -b $(FQBN) $(SRC) $(HDRS) > manifest.txt; \
else echo "---> If you want to generate manifest.txt, listing used libraries and their versions,"; \
echo "---> please install arduino-manifest, see https://github.com/digiampietro/arduino-manifest"; \
fi
upload:
@if [ ! -c $(SERIAL_DEV) ] ; \
then echo "---> ERROR: Serial Device not available, please set the SERIAL_DEV environment variable" ; \
else echo "---> Uploading sketch\n"; \
arduino-cli upload -b $(FQBN) -p $(SERIAL_DEV) $(VFLAG); \
fi
ota:
@PLAT_PATH=`arduino-cli compile -b $(FQBN) --show-properties | grep '^runtime.platform.path' | awk -F= '{print $$2}'` ; \
PY_PATH=`arduino-cli compile -b $(FQBN) --show-properties | grep '^runtime.tools.python3.path' | awk -F= '{print $$2}'` ; \
IOT_IP=`avahi-browse _arduino._tcp --resolve --parsable --terminate|grep -i ';$(IOT_NAME);'|grep ';$(OTA_PORT);'| awk -F\; '{print $$8}'|head -1`; \
BINFILE=$(wildcard $(BUILD_DIR)/$(SRC)*bin); \
echo "PLAT_PATH is [$$PLAT_PATH]" ; \
echo "PY_PATH: is [$$PY_PATH]" ; \
echo "IOT_IP: is [$$IOT_IP]" ; \
echo "BINFILE: is [$$BINFILE]" ; \
if [ "$$IOT_IP" = "" ] ; \
then echo "Unable to find device IP. Check that the IOT_NAME environment variable is correctly set. Use 'make find' to search devices"; \
else echo "---> Uploading Over The Air"; \
$$PY_PATH/python3 $$PLAT_PATH/tools/espota.py -i $$IOT_IP -p $(OTA_PORT) --auth=$(OTA_PASS) -f $$BINFILE ;\
fi
clean:
@echo "---> Cleaning the build directory"
rm -rf build
find:
avahi-browse _arduino._tcp --resolve --parsable --terminate
requirements:
@if [ -e requirements.txt ]; \
then while read -r i ; do echo ; \
echo "---> Installing " '"'$$i'"' ; \
arduino-cli lib install "$$i" ; \
done < requirements.txt ; \
else echo "---> MISSING requirements.txt file"; \
fi
-1
View File
@@ -1 +0,0 @@
../../monocoque/simulatorapi/simapi/simapi/simdata.h
-21
View File
@@ -1,21 +0,0 @@
#ifndef _SIMHAPTICDATA_H
#define _SIMHAPTICDATA_H
#include <stdint.h>
#include <stdbool.h>
typedef struct
{
uint8_t motor1;
uint8_t effect1;
uint8_t motor2;
uint8_t effect2;
uint8_t motor3;
uint8_t effect3;
uint8_t motor4;
uint8_t effect4;
}
SimHapticData;
#endif
-81
View File
@@ -1,81 +0,0 @@
#include <Adafruit_MotorShield.h>
#include "simhaptic.h"
#define BYTE_SIZE sizeof(SimHapticData)
#define POWER .6
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *myMotor1 = AFMS.getMotor(1);
//Adafruit_DCMotor *myMotor2 = AFMS.getMotor(2);
Adafruit_DCMotor *myMotor3 = AFMS.getMotor(3);
//Adafruit_DCMotor *myMotor4 = AFMS.getMotor(4);
SimHapticData sd;
int motor1 = 0;
int motor2 = 0;
int motor3 = 0;
int motor4 = 0;
int effect1 = 0;
int effect2 = 0;
int effect3 = 0;
int effect4 = 0;
void setup() {
Serial.begin(9600);
if (!AFMS.begin()) {
Serial.println("Could not find Motor Shield. Check wiring.");
while (1);
}
sd.motor1 = 0;
sd.motor2 = 0;
sd.motor3 = 0;
sd.motor4 = 0;
myMotor1->setSpeed(0);
myMotor1->run(FORWARD);
//myMotor2->setSpeed(0);
//myMotor2->run(FORWARD);
myMotor3->setSpeed(0);
myMotor3->run(FORWARD);
//myMotor4->setSpeed(0);
//myMotor4->run(FORWARD);
}
void loop() {
char buff[BYTE_SIZE];
if (Serial.available() >= BYTE_SIZE)
{
Serial.readBytes(buff, BYTE_SIZE);
memcpy(&sd, &buff, BYTE_SIZE);
motor1 = sd.motor1;
motor2 = sd.motor2;
motor3 = sd.motor3;
motor4 = sd.motor4;
effect1 = sd.effect1;
effect2 = sd.effect2;
effect3 = sd.effect3;
effect4 = sd.effect4;
}
if (motor1 >= 1)
{
myMotor1->setSpeed(effect1);
}
//if (motor2 >= 1)
//{
// myMotor2->setSpeed(effect2);
//}
if (motor3 >= 1)
{
myMotor3->setSpeed(effect3);
}
//if (motor4 >= 1)
//{
// myMotor4->setSpeed(effect4);
//}
}
-166
View File
@@ -1,166 +0,0 @@
# Makefile for Arduino based scketches
#
# Copyright 2020 Valerio Di Giampietro http://va.ler.io v@ler.io
# MIT License - see License.txt file
#
# This Makefile uses the arduino-cli, the Arduino command line interface
# and has been designed and tested to run on Linux, not on Windows.
# Probably it will run on a Mac, but it has not been tested.
#
# Please note that:
#
# 1. each sketch must reside in his own folder with this Makefile
#
# 2. the main make targets are:
# - all compiles and upload
# - compile compiles only
# - upload upload via serial port, compile if the binary file is
# not available
# - ota upload Over The Air, automatically find the device
# IP address using the IOT_NAME (device hostname)
# - clean clean the build directory
# - find find OTA updatable devices on the local subnet
# - requirements it the file "requirements.txt" exists it will
# install the libraries listed in this file
#
# default is "all"
#
# 3. it gets the name of the sketch using the wildcard make command;
# the name is *.ino; this means that you must have ONLY a file
# with .ino extension, otherwise this makefile will break. This
# also means that you can use this Makefile, almost unmodified,
# for any sketch as long as you keep a single .ino file in each
# folder
#
# 4. you can split your project in multiple files, if you wish,
# using a single .ino file and multiple .h files, that you can
# include in the .ino file with an '#include "myfile.h"'
# directive
#
# Optionally some environment variables can be set:
#
# FQBN Fully Qualified Board Name; if not set in the environment
# it will be assigned a value in this makefile
#
# SERIAL_DEV Serial device to upload the sketch; if not set in the
# environment it will be assigned:
# /dev/ttyUSB0 if it exists, or
# /dev/ttyACM0 if it exists, or
# unknown
#
# IOT_NAME Name of the IOT device; if not set in the environment
# it will be assigned a value in this makefile. This is
# very useful for OTA update, the device will be searched
# on the local subnet using this name
#
# OTA_PORT Port used by OTA update; if not set in the environment
# it will be assigned the default value of 8266 in this
# makefile
#
# OTA_PASS Password used for OTA update; if not set in the environment
# it will be assigned the default value of an empty string
#
# V verbose flag; can be 0 (quiet) or 1 (verbose); if not set
# in the environment it will be assigned a default value
# in this makefile
MAKE_DIR := $(PWD)
#
# ----- setup wor Wemos D1 mini -----
#FQBN ?= esp8266:esp8266:d1_mini
#IOT_NAME ?= esp8266-meteo
#OTA_PORT ?= 8266
#OTA_PASS ?=
# ----- setup for Arduino Uno
FQBN ?= arduino:avr:uno
# ----- ---------------------
V ?= 0
VFLAG =
ifeq "$(V)" "1"
VFLAG =-v
endif
ifndef SERIAL_DEV
ifneq (,$(wildcard /dev/ttyUSB0))
SERIAL_DEV = /dev/ttyUSB0
else ifneq (,$(wildcard /dev/ttyACM0))
SERIAL_DEV = /dev/ttyACM0
else
SERIAL_DEV = unknown
endif
endif
BUILD_DIR := $(subst :,.,build/$(FQBN))
SRC := $(wildcard *.ino)
HDRS := $(wildcard *.h)
BIN := $(BUILD_DIR)/$(SRC).bin
ELF := $(BUILD_DIR)/$(SRC).elf
$(info FQBN is [${FQBN}])
$(info IOT_NAME is [${IOT_NAME}])
$(info OTA_PORT is [${OTA_PORT}])
$(info OTA_PASS is [${OTA_PASS}])
$(info V is [${V}])
$(info VFLAG is [${VFLAG}])
$(info MAKE_DIR is [${MAKE_DIR}])
$(info BUILD_DIR is [${BUILD_DIR}])
$(info SRC is [${SRC}])
$(info HDRS is [${HDRS}])
$(info BIN is [${BIN}])
$(info SERIAL_DEV is [${SERIAL_DEV}])
all: $(ELF) upload
.PHONY: all
compile: $(ELF)
.PHONY: compile
$(ELF): $(SRC) $(HDRS)
arduino-cli compile -b $(FQBN) $(VFLAG)
@if which arduino-manifest.pl; \
then echo "---> Generating manifest.txt"; \
arduino-manifest.pl -b $(FQBN) $(SRC) $(HDRS) > manifest.txt; \
else echo "---> If you want to generate manifest.txt, listing used libraries and their versions,"; \
echo "---> please install arduino-manifest, see https://github.com/digiampietro/arduino-manifest"; \
fi
upload:
@if [ ! -c $(SERIAL_DEV) ] ; \
then echo "---> ERROR: Serial Device not available, please set the SERIAL_DEV environment variable" ; \
else echo "---> Uploading sketch\n"; \
arduino-cli upload -b $(FQBN) -p $(SERIAL_DEV) $(VFLAG); \
fi
ota:
@PLAT_PATH=`arduino-cli compile -b $(FQBN) --show-properties | grep '^runtime.platform.path' | awk -F= '{print $$2}'` ; \
PY_PATH=`arduino-cli compile -b $(FQBN) --show-properties | grep '^runtime.tools.python3.path' | awk -F= '{print $$2}'` ; \
IOT_IP=`avahi-browse _arduino._tcp --resolve --parsable --terminate|grep -i ';$(IOT_NAME);'|grep ';$(OTA_PORT);'| awk -F\; '{print $$8}'|head -1`; \
BINFILE=$(wildcard $(BUILD_DIR)/$(SRC)*bin); \
echo "PLAT_PATH is [$$PLAT_PATH]" ; \
echo "PY_PATH: is [$$PY_PATH]" ; \
echo "IOT_IP: is [$$IOT_IP]" ; \
echo "BINFILE: is [$$BINFILE]" ; \
if [ "$$IOT_IP" = "" ] ; \
then echo "Unable to find device IP. Check that the IOT_NAME environment variable is correctly set. Use 'make find' to search devices"; \
else echo "---> Uploading Over The Air"; \
$$PY_PATH/python3 $$PLAT_PATH/tools/espota.py -i $$IOT_IP -p $(OTA_PORT) --auth=$(OTA_PASS) -f $$BINFILE ;\
fi
clean:
@echo "---> Cleaning the build directory"
rm -rf build
find:
avahi-browse _arduino._tcp --resolve --parsable --terminate
requirements:
@if [ -e requirements.txt ]; \
then while read -r i ; do echo ; \
echo "---> Installing " '"'$$i'"' ; \
arduino-cli lib install "$$i" ; \
done < requirements.txt ; \
else echo "---> MISSING requirements.txt file"; \
fi
-1
View File
@@ -1 +0,0 @@
../../monocoque/simulatorapi/simapi/simapi/simdata.h
-15
View File
@@ -1,15 +0,0 @@
#ifndef _SIMWINDDATA_H
#define _SIMWINDDATA_H
#include <stdint.h>
#include <stdbool.h>
typedef struct
{
uint8_t velocity;
uint8_t fanpower;
}
SimWindData;
#endif
-43
View File
@@ -1,43 +0,0 @@
#include <Adafruit_MotorShield.h>
#include "simwind.h"
#define BYTE_SIZE sizeof(SimWindData)
#define KPHTOMPH .621317
#define FANPOWER .6
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *myMotor1 = AFMS.getMotor(1);
Adafruit_DCMotor *myMotor2 = AFMS.getMotor(3);
SimWindData sd;
int velocity = 0;
void setup() {
Serial.begin(9600);
if (!AFMS.begin()) {
Serial.println("Could not find Motor Shield. Check wiring.");
while (1);
}
sd.velocity = 10;
myMotor1->setSpeed(0);
myMotor1->run(FORWARD);
myMotor2->setSpeed(0);
myMotor2->run(FORWARD);
}
void loop() {
char buff[BYTE_SIZE];
if (Serial.available() >= BYTE_SIZE)
{
Serial.readBytes(buff, BYTE_SIZE);
memcpy(&sd, &buff, BYTE_SIZE);
velocity = sd.velocity;
}
myMotor1->setSpeed(velocity*FANPOWER);
myMotor2->setSpeed(velocity*FANPOWER);
}
-21
View File
@@ -7,35 +7,14 @@ 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.c
usbhapticdevice.h
usbhapticdevice.c
hapticeffect.h
hapticeffect.c
sound.h
sound.c
usb/revburner.h usb/revburner.h
usb/revburner.c usb/revburner.c
usb/cslelitev3.h
usb/cslelitev3.c
usb/simagicp1000.h
usb/simagicp1000.c
usb/wheels/cammusc5.h
usb/wheels/cammusc5.c
usb/wheels/cammusc12.h
usb/wheels/cammusc12.c
sound/usb_generic_shaker.h sound/usb_generic_shaker.h
sound/usb_generic_shaker.c sound/usb_generic_shaker.c
sound/usb_generic_shaker_pulse.c
serial/arduino.h serial/arduino.h
serial/arduino.c serial/arduino.c
serial/moza.h
serial/moza.c
) )
include_directories("." "usb" "sound" "serial") include_directories("." "usb" "sound" "serial")
-393
View File
@@ -1,393 +0,0 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <math.h>
#include "usbhapticdevice.h"
#include "../../helper/confighelper.h"
#include "../../simulatorapi/simapi/simapi/simdata.h"
#include "../../simulatorapi/simapi/simapi/simmapper.h"
#include "../../slog/slog.h"
#define kmhtoms 0.277778
#define minspeedinms 0.5
#define minvelocity 50
#define maxbrake 0
#define maxthrottle 0
#define maxXvelocity 0.001
bool hasTyreDiameter(SimData* simdata)
{
if (simdata->tyrediameter[0] == -1 || simdata->tyrediameter[1] == -1 || simdata->tyrediameter[2] == -1 || simdata->tyrediameter[3] == -1)
{
slogt("failed to find tyre diameter data");
return false;
}
slogt("tyre diameter data found");
return true;
}
int loadtyreconfig(SimData* simdata, char* configfile)
{
config_t cfg;
config_init(&cfg);
config_setting_t* config_cars = NULL;
if (!config_read_file(&cfg, configfile))
{
slogw("Could not open diameters save file.");
config_destroy(&cfg);
return 1;
}
config_cars = config_lookup(&cfg, "cars");
if(config_cars == NULL)
{
slogd("diameters config file corrupted");
config_destroy(&cfg);
return 1;
}
slogt("parsing diameters config file");
int cars = config_setting_length(config_cars);
int i = 0;
while (i<cars)
{
DeviceSettings settings;
config_setting_t* config_car = config_setting_get_elem(config_cars, i);
if(config_car != NULL)
{
const char* car;
const char* simstr;
int sim = 0;
double tyre0;
double tyre1;
double tyre2;
double tyre3;
config_setting_lookup_string(config_car, "car", &car);
config_setting_lookup_float(config_car, "tyre0", &tyre0);
config_setting_lookup_float(config_car, "tyre1", &tyre1);
config_setting_lookup_float(config_car, "tyre2", &tyre2);
config_setting_lookup_float(config_car, "tyre3", &tyre3);
int found = config_setting_lookup_string(config_car, "sim", &simstr);
if(found == 0)
{
int found = config_setting_lookup_int(config_car, "sim", &sim);
}
else
{
sim = simapi_strtogame(simstr);
}
if(simdata->car != NULL && car != NULL)
{
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)
{
slogi("found saved car %s with tyre diameters %f %f %f %f", car, tyre0, tyre1, tyre2, tyre3);
simdata->tyrediameter[0] = tyre0;
simdata->tyrediameter[1] = tyre1;
simdata->tyrediameter[2] = tyre2;
simdata->tyrediameter[3] = tyre3;
break;
}
}
}
}
else
{
slogw("Possible corruption in config file on entry %i attempting to continue", i+1);
}
i++;
}
config_destroy(&cfg);
return 0;
}
int savetyreconfig(SimData* simdata, char* configfile)
{
config_t cfg;
config_setting_t* root;
config_setting_t* array;
config_setting_t* carobject;
config_setting_t* setting;
config_init(&cfg);
if (!config_read_file(&cfg, configfile))
{
slogw("Could not open diameters save file, creating new.");
root = config_root_setting(&cfg);
array = config_setting_add(root, "cars", CONFIG_TYPE_LIST);
}
else
{
array = config_lookup(&cfg, "cars");
}
// TODO add check to not add same car-sim combination twice
carobject = config_setting_add(array, "cars", CONFIG_TYPE_GROUP);
setting = config_setting_add(carobject, "car", CONFIG_TYPE_STRING);
config_setting_set_string(setting, simdata->car);
setting = config_setting_add(carobject, "sim", CONFIG_TYPE_INT);
config_setting_set_string(setting, simapi_gametostr(simdata->simexe));
setting = config_setting_add(carobject, "tyre0", CONFIG_TYPE_FLOAT);
config_setting_set_float(setting, simdata->tyrediameter[0]);
setting = config_setting_add(carobject, "tyre1", CONFIG_TYPE_FLOAT);
config_setting_set_float(setting, simdata->tyrediameter[1]);
setting = config_setting_add(carobject, "tyre2", CONFIG_TYPE_FLOAT);
config_setting_set_float(setting, simdata->tyrediameter[2]);
setting = config_setting_add(carobject, "tyre3", CONFIG_TYPE_FLOAT);
config_setting_set_float(setting, simdata->tyrediameter[3]);
/* Write out the new configuration. */
if(! config_write_file(&cfg, configfile))
{
slogi("Error while writing file.");
config_destroy(&cfg);
}
slogi("New configuration successfully written to: %s\n", configfile);
config_destroy(&cfg);
return 0;
}
void getTyreDiameter(SimData* simdata)
{
if(simdata->velocity > minvelocity && simdata->brake <= maxbrake && simdata->gas <= maxthrottle)
{
double Speedms = kmhtoms * simdata->velocity;
if (simdata->Xvelocity/Speedms < maxXvelocity)
{
for(int i = 0; i < 4; i++)
{
simdata->tyrediameter[i] = Speedms / simdata->tyreRPS[i] * 2;
}
slogi("Successfully set tyre diameters for wheel slip effects.");
}
}
}
double slipeffect(SimData* simdata, int effecttype, int tyre, double threshold, int useconfig, int* configcheck, char* configfile)
{
double play = 0;
double wheelslip[4];
wheelslip[0] = 0;
wheelslip[1] = 0;
wheelslip[2] = 0;
wheelslip[3] = 0;
if(simdata->car == NULL)
{
slogw("sim is not compatible with wheel and tyre effects, or car and session not loaded.");
return 0;
}
if(simdata->car[0] == '\0')
{
slogw("sim is not compatible with wheel and tyre effects, or car not loaded.");
return 0;
}
slogt("wheel vibration calculation with wheel config set to %i configchecked %i configfile %s car %s", useconfig, *configcheck, configfile, simdata->car);
switch (effecttype)
{
case (EFFECT_TYRESLIP):
case (EFFECT_TYRELOCK):
case (EFFECT_ABSBRAKES):
if(useconfig == 1 && configfile != NULL)
{
// check for saved tyre diameter in config file
// if not saved version exists get tyre diameter and save it
// use config check variable to track if the config check has been performed
// avoid many opens of the same file
int error = 0;
if(hasTyreDiameter(simdata)==false && *configcheck == 0)
{
slogi("attempting load of tyre diameter config");
error = loadtyreconfig(simdata, configfile);
*configcheck = 1;
}
if(hasTyreDiameter(simdata)==false)
{
slogt("could not find tyre diameter in config file, attempting to calculate new");
getTyreDiameter(simdata);
if(hasTyreDiameter(simdata)==true)
{
slogi("saving tyre config");
error = savetyreconfig(simdata, configfile);
}
}
}
if(hasTyreDiameter(simdata)==true)
{
double Speedms = kmhtoms * simdata->velocity;
slogt("attempting wheel slip calculation");
if (Speedms > minspeedinms)
{
for(int i = 0; i < 4; i++)
{
wheelslip[i] = (Speedms - simdata->tyrediameter[i] * simdata->tyreRPS[i] / 2) / Speedms;
}
}
else
{
for(int i = 0; i < 4; i++)
{
wheelslip[i] = 0;
}
}
slogt("wheelslip values are %f %f %f %f", wheelslip[0], wheelslip[1], wheelslip[2], wheelslip[3]);
slogt("velocities (x,y,z) are %f %f %f", simdata->Xvelocity, simdata->Yvelocity, simdata->Zvelocity);
}
break;
default:
slogd("Unknown effect type");
}
if(simdata->Yvelocity <= 0)
{
return 0;
}
if(simdata->Zvelocity > 1 || simdata->Zvelocity < -1)
{
return 0;
}
switch (effecttype)
{
case (EFFECT_TYRESLIP):
if (tyre == FRONTLEFT || tyre == FRONTS || tyre == ALLFOUR)
{
if(wheelslip[0] < -threshold)
{
play += fabs(wheelslip[0]) - fabs(threshold);
slogt("slip is %f", play);
}
}
if (tyre == FRONTRIGHT || tyre == FRONTS || tyre == ALLFOUR)
{
if(wheelslip[1] < -threshold)
{
play += fabs(wheelslip[1]) - fabs(threshold);
slogt("slip is %f", play);
}
}
if (tyre == REARLEFT || tyre == REARS || tyre == ALLFOUR)
{
if(wheelslip[2] < -threshold)
{
play += fabs(wheelslip[2]) - fabs(threshold);
slogt("slip is %f", play);
}
}
if (tyre == REARRIGHT || tyre == REARS || tyre == ALLFOUR)
{
if(wheelslip[3] < -threshold)
{
play += fabs(wheelslip[3]) - fabs(threshold);
slogt("slip is %f", play);
}
}
break;
case (EFFECT_TYRELOCK):
if (tyre == FRONTLEFT || tyre == FRONTS || tyre == ALLFOUR)
{
if(wheelslip[0] > threshold)
{
play += wheelslip[0] - threshold;
slogt("lock is %f", play);
}
}
if (tyre == FRONTRIGHT || tyre == FRONTS || tyre == ALLFOUR)
{
if(wheelslip[1] > threshold)
{
play += wheelslip[1] - threshold;
slogt("lock is %f", play);
}
}
if (tyre == REARLEFT || tyre == REARS || tyre == ALLFOUR)
{
if(wheelslip[2] > threshold)
{
play += wheelslip[2] - threshold;
slogt("lock is %f", play);
}
}
if (tyre == REARRIGHT || tyre == REARS || tyre == ALLFOUR)
{
if(wheelslip[3] > threshold)
{
play += wheelslip[3] - threshold;
slogt("lock is %f", play);
}
}
break;
case (EFFECT_ABSBRAKES):
threshold = simdata->abs + threshold;
if (tyre == FRONTLEFT || tyre == FRONTS || tyre == ALLFOUR)
{
if(wheelslip[0] > threshold)
{
play += wheelslip[0] - threshold;
slogt("abs is %f", play);
}
}
if (tyre == FRONTRIGHT || tyre == FRONTS || tyre == ALLFOUR)
{
if(wheelslip[1] > threshold)
{
play += wheelslip[1] - threshold;
slogt("abs is %f", play);
}
}
if (tyre == REARLEFT || tyre == REARS || tyre == ALLFOUR)
{
if(wheelslip[2] > threshold)
{
play += wheelslip[2] - threshold;
slogt("abs is %f", play);
}
}
if (tyre == REARRIGHT || tyre == REARS || tyre == ALLFOUR)
{
if(wheelslip[3] > threshold)
{
play += wheelslip[3] - threshold;
slogt("abs is %f", play);
}
}
if(simdata->abs <= 0)
{
play = 0;
}
break;
}
return play;
}
-21
View File
@@ -1,21 +0,0 @@
#ifndef _HAPTICEFFECT_H
#define _HAPTICEFFECT_H
#include <stdio.h>
#include "../helper/confighelper.h"
#include "../simulatorapi/simapi/simapi/simdata.h"
typedef struct
{
double threshold;
VibrationEffectType effecttype;
MonocoqueTyreIdentifier tyre;
int useconfig;
int* configcheck;
char* tyrediameterconfig;
}
HapticEffect;
double slipeffect(SimData* simdata, int effecttype, int tyre, double threshold, int useconfig, int* configcheck, char* configfile);
#endif
+64 -10
View File
@@ -1,25 +1,79 @@
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.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 2000
int arduino_update(SerialDevice* serialdevice, void* data, size_t size) int arduino_update(SerialDevice* serialdevice, SimData* simdata)
{ {
int result = 1; int result = 1;
slogt("copying %i bytes to arduino device", size); if (serialdevice->port)
result = monocoque_serial_write(serialdevice->id, data, size, arduino_timeout); {
result = check(sp_blocking_write(serialdevice->port, simdata, sizeof(SimData), arduino_timeout));
}
return result; return result;
} }
int arduino_init(SerialDevice* serialdevice, const char* portdev) int arduino_init(SerialDevice* serialdevice)
{ {
serialdevice->id = monocoque_serial_open(serialdevice, portdev); slogi("initializing arduino serial device...");
return serialdevice->id; int error = 0;
char* port_name = "/dev/ttyACM0";
slogd("Looking for port %s.\n", port_name);
error = check(sp_get_port_by_name(port_name, &serialdevice->port));
if (error != 0)
{
return error;
}
slogd("Opening port.\n");
check(sp_open(serialdevice->port, SP_MODE_READ_WRITE));
slogd("Setting port to 9600 8N1, no flow control.\n");
check(sp_set_baudrate(serialdevice->port, 9600));
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));
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;
//abort();
case SP_ERR_FAIL:
error_message = sp_last_error_message();
printf("Error: Failed: %s\n", error_message);
sp_free_error_message(error_message);
abort();
case SP_ERR_SUPP:
printf("Error: Not supported.\n");
abort();
case SP_ERR_MEM:
printf("Error: Couldn't allocate memory.\n");
abort();
case SP_OK:
default:
return result;
}
} }
+3 -4
View File
@@ -1,12 +1,11 @@
#ifndef _ARDUINO_H #ifndef _ARDUINO_H
#define _ARDUINO_H #define _ARDUINO_H
#include "../simdevice.h"
#include "../serialdevice.h" #include "../serialdevice.h"
int arduino_update(SerialDevice* serialdevice, SimData* simdata);
int arduino_update(SerialDevice* serialdevice, void* data, size_t size); int arduino_init(SerialDevice* serialdevice);
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
-88
View File
@@ -1,88 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <hidapi/hidapi.h>
#include "moza.h"
#include "../serialadapter.h"
#include "../../slog/slog.h"
#define MOZA_TIMEOUT 1000
#define MOZA_SERIAL_TEMPLATE {0x7e, 0x06, 0x41, 0x17, 0xfd, 0xde, 0x0, 0x0, 0x0, 0x0, 0x0}
#define MOZA_NUM_AVAILABLE_LEDS 10
#define MOZA_BLINKING_BIT 7
#define MOZA_MAGIC_VALUE 0x0d
#define BIT(nr) (1UL << (nr))
unsigned char moza_checksum(unsigned char *data)
{
unsigned char ret = MOZA_MAGIC_VALUE;
for (short i = 0; i < sizeof(data)/sizeof(data[0]); i++)
{
ret += data[i];
}
return ret;
}
int moza_update(SerialDevice* serialdevice, unsigned short maxrpm, unsigned short rpm)
{
unsigned char bytes[] = MOZA_SERIAL_TEMPLATE;
int size = sizeof(bytes)/sizeof(bytes[0]);
float perct = (float)rpm/(float)maxrpm;
if (perct >= 0.8)
bytes[9] |= BIT(0);
if (perct >= 0.83)
bytes[9] |= BIT(1);
if (perct >= 0.86)
bytes[9] |= BIT(2);
if (perct >= 0.89)
bytes[9] |= BIT(3);
if (perct >= 0.91)
bytes[8] |= BIT(4);
if (perct >= 0.92)
bytes[8] |= BIT(5);
if (perct >= 0.93)
bytes[8] |= BIT(6);
if (perct >= 0.94)
bytes[8] |= BIT(7);
if (perct >= 0.96)
bytes[8] |= BIT(0);
if (perct >= 0.96)
bytes[8] |= BIT(1);
// blinking
if (perct >= 0.97)
bytes[9] |= BIT(MOZA_BLINKING_BIT);
bytes[10] = moza_checksum(bytes);
int result = 1;
if (serialdevice->port)
{
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);
result = monocoque_serial_write(serialdevice->id, bytes, size, MOZA_TIMEOUT);
}
return result;
}
int moza_init(SerialDevice* serialdevice, const char* portdev)
{
serialdevice->id = monocoque_serial_open(serialdevice, portdev);
return serialdevice->id;
}
-13
View File
@@ -1,13 +0,0 @@
#ifndef _MOZA_H
#define _MOZA_H
#include "../serialdevice.h"
#include "../simdevice.h"
int moza_update(SerialDevice* serialdevice, unsigned short maxrpm, unsigned short rpm);
int moza_init(SerialDevice* serialdevice, const char* portdev);
int moza_free(SerialDevice* serialdevice);
int moza_serial_check(enum sp_return result);
#endif
-205
View File
@@ -1,205 +0,0 @@
#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;
}
-28
View File
@@ -1,28 +0,0 @@
#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
+10 -351
View File
@@ -2,375 +2,34 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <math.h>
#include "simdevice.h"
#include "serialdevice.h" #include "serialdevice.h"
#include "serialadapter.h"
#include "hapticeffect.h"
#include "serial/arduino.h" #include "serial/arduino.h"
#include "serial/moza.h"
#include "../helper/parameters.h" #include "../helper/parameters.h"
#include "../simulatorapi/simapi/simapi/simdata.h" #include "../simulatorapi/simdata.h"
#include "../slog/slog.h" #include "../slog/slog.h"
#define KPHTOMPH .621317 int serialdev_update(SerialDevice* serialdevice, SimData* simdata)
int serial_wheel_update(SimDevice* this, SimData* simdata)
{ {
SerialDevice* serialdevice = (void *) this->derived; arduino_update(serialdevice, simdata);
moza_update(serialdevice, simdata->maxrpm, simdata->rpms);
return 0; return 0;
} }
int serialdev_update(SimDevice* this, SimData* simdata) int serialdev_free(SerialDevice* serialdevice)
{ {
SerialDevice* serialdevice = (void *) this->derived; arduino_free(serialdevice);
arduino_update(serialdevice, simdata, sizeof(SimData));
return 0; return 0;
} }
int arduino_shiftlights_update(SimDevice* this, SimData* simdata) int serialdev_init(SerialDevice* serialdevice)
{ {
SerialDevice* serialdevice = (void *) this->derived; slogi("initializing serial device...");
int result = 1;
int num_avail_leds = serialdevice->numlights;
int rpm = simdata->rpms;
int maxrpm = simdata->maxrpm;
int litleds = 0;
if(rpm > 0 && maxrpm > 0)
{
int rpmmargin = ceil(.05*maxrpm);
int rpminterval = (maxrpm-rpmmargin) / (num_avail_leds);
for (int l = 1; l <= (num_avail_leds); l++)
{
if(rpm >= (rpminterval * l))
{
litleds = l;
}
}
}
serialdevice->u.shiftlightsdata.litleds = litleds;
//serialdevice->u.shiftlightsdata.rpm = simdata->rpms;
slogt("Updating arduino device lights to %i", serialdevice->u.shiftlightsdata.litleds);
// we can add configs to set all the colors
// i can move the size to the initialization since it should not change
size_t size = sizeof(ShiftLightsData);
arduino_update(serialdevice, &serialdevice->u.shiftlightsdata, size);
return result;
}
int arduino_simled_update(SimDevice* this, SimData* simdata)
{
SerialDevice* serialdevice = (void *) this->derived;
int result = 1;
int total_leds = serialdevice->numleds;
size_t bufsize = (total_leds * 3) + 14;
char bytes[bufsize];
int endled = serialdevice->endled;
int startled = serialdevice->startled;
if(endled == 0)
{
endled = total_leds;
}
int num_avail_leds = endled - startled + 1;
int rpm = simdata->rpms;
int maxrpm = simdata->maxrpm;
int litleds = 0;
if(rpm > 0 && maxrpm > 0)
{
int rpmmargin = ceil(.05*maxrpm);
int rpminterval = (maxrpm-rpmmargin) / (num_avail_leds);
for (int l = 1; l <= (num_avail_leds); l++)
{
if(rpm >= (rpminterval * l))
{
litleds = l;
}
}
for(int j = 0; j < bufsize; j++)
{
bytes[j] = 0x00;
}
bytes[0] = 0xff;
bytes[1] = 0xff;
bytes[2] = 0xff;
bytes[3] = 0xff;
bytes[4] = 0xff;
bytes[5] = 0xff;
bytes[6] = 0x73;
bytes[7] = 0x6c;
bytes[8] = 0x65;
bytes[9] = 0x64;
bytes[10] = 0x73;
bytes[bufsize-1] = 0xfd;
bytes[bufsize-2] = 0xfe;
bytes[bufsize-3] = 0xff;
for(int i = 0; i < litleds; i++)
{
if(i < ((num_avail_leds) / 2))
{
//green
bytes[11 + ((i + startled - 1) * 3) + 1] = 0xff;
}
else
{
if(i < num_avail_leds - 1)
{
//yellow
bytes[11 + ((i + startled - 1) * 3) + 0] = 0xff;
bytes[11 + ((i + startled - 1) * 3) + 1] = 0xff;
}
}
if(i == num_avail_leds - 1)
{
//red
bytes[11 + ((i + startled - 1) * 3) + 0] = 0xff;
}
}
}
slogt("Updating arduino device lights to %i", litleds);
// we can add configs to set all the colors
size_t size = sizeof(bytes);
arduino_update(serialdevice, &bytes, size);
return result;
}
int arduino_simwind_update(SimDevice* this, SimData* simdata)
{
SerialDevice* serialdevice = (void *) this->derived;
int result = 1;
// sending over as mph, when you consider 255mph to be a reasonable upper limit
serialdevice->u.simwinddata.velocity = ceil(simdata->velocity*KPHTOMPH);
slogt("Updating arduino device speed to %i", serialdevice->u.simwinddata.velocity);
// this can be added to the config, all config dependent can be added to init
serialdevice->u.simwinddata.fanpower = (int)0.6 * 255;
size_t size = sizeof(SimWindData);
arduino_update(serialdevice, &serialdevice->u.simwinddata, size);
return result;
}
int arduino_simhaptic_update(SimDevice* this, SimData* simdata)
{
SerialDevice* serialdevice = (void *) this->derived;
int result = 1;
slogt("arduino haptic device updating");
double play = slipeffect(simdata, this->hapticeffect.effecttype, this->hapticeffect.tyre, this->hapticeffect.threshold, this->hapticeffect.useconfig, this->hapticeffect.configcheck, this->hapticeffect.tyrediameterconfig);
double rplay = play;
play = play * serialdevice->ampfactor;
if(play > 1.0)
{
play = 1.0;
}
int effectspeed = ceil(255 * play);
int motor = serialdevice->motorsposition;
if (play != serialdevice->state)
{
if (motor == 0 || motor == 4 || motor == 7 || motor == 8 || motor == 10 || motor == 11 || motor == 13 || motor == 14)
{
serialdevice->u.simhapticdata.effect1 = effectspeed;
serialdevice->u.simhapticdata.motor1 = 1;
slogt("Updating arduino haptic device with effect type %i speed motor speed %i on motor %i from original effect %f with ampfactor %f", this->hapticeffect.effecttype, serialdevice->u.simhapticdata.effect3, serialdevice->motorsposition, rplay, serialdevice->ampfactor);
}
if (motor == 2 || motor == 6 || motor == 8 || motor == 9 || motor == 10 || motor == 11 || motor == 12 || motor == 14)
{
serialdevice->u.simhapticdata.effect3 = effectspeed;
serialdevice->u.simhapticdata.motor3 = 1;
slogt("Updating arduino haptic device with effect type %i speed motor speed %i on motor %i from original effect %f with ampfactor %f", this->hapticeffect.effecttype, serialdevice->u.simhapticdata.effect3, serialdevice->motorsposition, rplay, serialdevice->ampfactor);
}
serialdevice->state = play;
}
size_t size = sizeof(SimHapticData);
arduino_update(serialdevice, &serialdevice->u.simhapticdata, size);
return result;
}
int serialdev_free(SimDevice* this)
{
SerialDevice* serialdevice = (void *) this->derived;
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);
return 0;
}
int serial_wheel_free(SimDevice* this)
{
SerialDevice* serialdevice = (void *) this->derived;
monocoque_serial_free(serialdevice);
free(serialdevice);
return 0;
}
int serialdev_init(SerialDevice* serialdevice, DeviceSettings* ds)
{
slogi("initializing serial device on port %s to %i...", ds->serialdevsettings.portdev, ds->serialdevsettings.baud);
int error = 0; int error = 0;
serialdevice->type = SERIALDEV_UNKNOWN;
serialdevice->type = SERIALDEV_ARDUINO;
serialdevice->motorsposition = ds->serialdevsettings.motorsposition; error = arduino_init(serialdevice);
serialdevice->baudrate = ds->serialdevsettings.baud;
switch (serialdevice->type)
{
case SERIALDEV_WHEEL:
// the wheel stuff assumed it was a usb
//error = wheeldev_init(&serialdevice->u.wheeldevice, ds);
error = moza_init(serialdevice, ds->serialdevsettings.portdev);
break;
default:
error = arduino_init(serialdevice, ds->serialdevsettings.portdev );
break;
}
return error; return error;
} }
static const vtable serial_simdevice_vtable = { &serialdev_update, &serialdev_free };
static const vtable arduino_shiftlights_vtable = { &arduino_shiftlights_update, &serialdev_free };
static const vtable arduino_simled_vtable = { &arduino_simled_update, &serialdev_free };
static const vtable arduino_simwind_vtable = { &arduino_simwind_update, &serialdev_free };
static const vtable arduino_simhaptic_vtable = { &arduino_simhaptic_update, &serialdev_free };
static const vtable serialwheel_vtable = { &serial_wheel_update, &serial_wheel_free };
SerialDevice* new_serial_device(DeviceSettings* ds, MonocoqueSettings* ms) {
SerialDevice* this = (SerialDevice*) malloc(sizeof(SerialDevice));
this->m.update = &update;
this->m.free = &simdevfree;
this->m.derived = this;
this->m.vtable = &serial_simdevice_vtable;
this->type = SERIALDEV_ARDUINO;
slogt("Attempting to configure arduino device with subtype: %i", ds->dev_subtype);
switch (ds->dev_subtype) {
case (SIMDEVTYPE_SHIFTLIGHTS):
this->devicetype = ARDUINODEV__SHIFTLIGHTS;
this->numlights = ds->serialdevsettings.numlights;
this->m.vtable = &arduino_shiftlights_vtable;
slogi("Initializing arduino device for shiftlights.");
break;
case (SIMDEVTYPE_SIMLED):
this->devicetype = ARDUINODEV__SIMLED;
this->numleds = ds->serialdevsettings.numleds;
this->startled = ds->serialdevsettings.startled;
this->endled = ds->serialdevsettings.endled;
this->m.vtable = &arduino_simled_vtable;
slogi("Initializing arduino device for simled.");
break;
case (SIMDEVTYPE_SIMWIND):
this->devicetype = ARDUINODEV__SIMWIND;
this->m.vtable = &arduino_simwind_vtable;
slogi("Initializing arduino devices for sim wind.");
break;
case (SIMDEVTYPE_SERIALHAPTIC):
this->devicetype = ARDUINODEV__HAPTIC;
this->m.vtable = &arduino_simhaptic_vtable;
this->u.simhapticdata.motor1 = 0;
this->u.simhapticdata.motor2 = 0;
this->u.simhapticdata.motor3 = 0;
this->u.simhapticdata.motor4 = 0;
this->u.simhapticdata.effect1 = 0;
this->u.simhapticdata.effect2 = 0;
this->u.simhapticdata.effect3 = 0;
this->u.simhapticdata.effect4 = 0;
this->state = 0;
this->ampfactor = ds->serialdevsettings.ampfactor;
slogi("Initializing arduino device for haptic effects.");
break;
case (SIMDEVTYPE_SERIALWHEEL):
this->type = SERIALDEV_WHEEL;
slogi("Initializing serial wheel device.");
switch (ds->dev_subsubtype) {
case SIMDEVSUBTYPE_MOZAR5:
default:
//move this stuff to wheeldevice or it's own serial wheel device module
this->devicetype = SERIALDEV__MOZAR5;
this->m.vtable = &serialwheel_vtable;
break;
}
}
if(this->devicetype == ARDUINODEV__HAPTIC)
{
this->m.hapticeffect.threshold = ds->threshold;
this->m.hapticeffect.effecttype = ds->effect_type;
slogt("Haptic effect: %i %i", this->m.hapticeffect.effecttype, ds->effect_type);
this->m.hapticeffect.tyre = ds->tyre;
this->m.hapticeffect.useconfig = ms->useconfig;
this->m.hapticeffect.configcheck = &ms->configcheck;
this->m.hapticeffect.tyrediameterconfig = ms->tyre_diameter_config;
}
int error = serialdev_init(this, ds);
if (error < 0)
{
free(this);
return NULL;
}
return this;
}
+17 -7
View File
@@ -2,16 +2,26 @@
#define _SERIALDEVICE_H #define _SERIALDEVICE_H
#include <libserialport.h> #include <libserialport.h>
#include "wheeldevice.h" #include "../helper/parameters.h"
#include "../simulatorapi/simdata.h"
typedef enum typedef enum
{ {
ARDUINODEV__SHIFTLIGHTS = 0, SERIALDEV_UNKNOWN = 0,
ARDUINODEV__SIMWIND = 1, SERIALDEV_ARDUINO = 1
ARDUINODEV__HAPTIC = 2,
SERIALDEV__MOZAR5 = 3,
ARDUINODEV__SIMLED = 4
} }
SerialDeviceType; SerialType;
typedef struct
{
int id;
SerialType type;
struct sp_port* port;
}
SerialDevice;
int serialdev_update(SerialDevice* serialdevice, SimData* simdata);
int serialdev_init(SerialDevice* serialdevice);
int serialdev_free(SerialDevice* serialdevice);
#endif #endif
+66 -71
View File
@@ -1,90 +1,85 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include "simdevice.h" #include "simdevice.h"
#include "../helper/parameters.h" #include "../helper/parameters.h"
#include "../helper/confighelper.h" #include "../helper/confighelper.h"
#include "../simulatorapi/simapi/simapi/simdata.h" #include "../simulatorapi/simdata.h"
#include "../slog/slog.h" #include "../slog/slog.h"
int devupdate(SimDevice* simdevice, SimData* simdata)
int update(SimDevice* this, SimData* simdata)
{ {
((vtable*)this->vtable)->update(this, simdata); if (simdevice->initialized==false)
} {
return 0;
int simdevfree(SimDevice* this) }
{ switch ( simdevice->type )
((vtable*)this->vtable)->free(this); {
} case SIMDEV_USB :
usbdev_update(&simdevice->d.usbdevice, simdata);
int devupdate(SimDevice* this, SimData* simdata) break;
{ case SIMDEV_SOUND :
sounddev_update(&simdevice->d.sounddevice, simdata);
break;
case SIMDEV_SERIAL :
serialdev_update(&simdevice->d.serialdevice, simdata);
break;
}
return 0; return 0;
} }
int devinit(SimDevice* simdevices, int numdevices, DeviceSettings* ds, MonocoqueSettings* ms) int devfree(SimDevice* simdevice)
{ {
slogi("initializing simdevices...");
int devices = 0;
for (int j = 0; j < numdevices; j++) if (simdevice->initialized==false)
{ {
simdevices[j].initialized = false; slogw("Attempt to free an uninitialized device");
return MONOCOQUE_ERROR_INVALID_DEV;
}
switch ( simdevice->type )
{
case SIMDEV_USB :
usbdev_free(&simdevice->d.usbdevice);
break;
case SIMDEV_SOUND :
sounddev_free(&simdevice->d.sounddevice);
break;
case SIMDEV_SERIAL :
serialdev_free(&simdevice->d.serialdevice);
break;
}
return 0;
}
if (ds[j].dev_type == SIMDEV_USB) { int devinit(SimDevice* simdevice, DeviceSettings* ds)
USBDevice* sim = new_usb_device(&ds[j], ms); {
if (sim != NULL) slogi("initializing simdevice...");
{ simdevice->initialized = false;
simdevices[j] = sim->m; int err = 0;
simdevices[j].initialized = true;
simdevices[j].type = SIMDEV_USB;
simdevices[j].fps = ds[j].fps;
devices++;
}
else
{
slogw("Could not initialize USB Device");
}
}
if (ds[j].dev_type == SIMDEV_SOUND) { switch ( ds->dev_type )
{
SoundDevice* sim = new_sound_device(&ds[j], ms); case SIMDEV_USB :
if (sim != NULL) simdevice->type = SIMDEV_USB;
{ simdevice->d.usbdevice.type = USBDEV_UNKNOWN;
err = usbdev_init(&simdevice->d.usbdevice, ds);
simdevices[j] = sim->m; break;
simdevices[j].initialized = true; case SIMDEV_SOUND :
simdevices[j].type = SIMDEV_SOUND; simdevice->type = SIMDEV_SOUND;
simdevices[j].fps = ds[j].fps; err = sounddev_init(&simdevice->d.sounddevice);
devices++; break;
} case SIMDEV_SERIAL :
else simdevice->type = SIMDEV_SERIAL;
{ err = serialdev_init(&simdevice->d.serialdevice);
slogw("Could not initialize Sound Device"); break;
} default :
} sloge("Unknown device type");
err = MONOCOQUE_ERROR_UNKNOWN_DEV;
if (ds[j].dev_type == SIMDEV_SERIAL) { break;
SerialDevice* sim = new_serial_device(&ds[j], ms);
if (sim != NULL)
{
simdevices[j] = sim->m;
simdevices[j].initialized = true;
simdevices[j].type = SIMDEV_SERIAL;
simdevices[j].fps = ds[j].fps;
devices++;
}
else
{
slogw("Could not initialize Serial Device");
}
}
} }
return devices; if (err==0)
{
simdevice->initialized = true;
}
return err;
} }
+9 -120
View File
@@ -6,140 +6,29 @@
#include "usbdevice.h" #include "usbdevice.h"
#include "sounddevice.h" #include "sounddevice.h"
#include "serialdevice.h" #include "serialdevice.h"
#include "hapticeffect.h"
#include "../helper/confighelper.h" #include "../helper/confighelper.h"
#include "../simulatorapi/simapi/simapi/simdata.h" #include "../simulatorapi/simdata.h"
#include "../../arduino/simwind/simwind.h"
#include "../../arduino/simhaptic/simhaptic.h"
#include "../../arduino/shiftlights/shiftlights.h"
typedef struct SimDevice SimDevice; typedef struct
struct SimDevice
{ {
const void* vtable;
int (*update)(SimDevice*, SimData*);
int (*free)(SimDevice*);
void* derived;
int id; int id;
int fps;
bool initialized; bool initialized;
DeviceType type; DeviceType type;
HapticEffect hapticeffect;
};
typedef struct {
int (*update)(SimDevice*, SimData*);
int (*free)(SimDevice*);
} vtable;
/********* Serial Devices *****/
typedef enum
{
SERIALDEV_UNKNOWN = 0,
SERIALDEV_ARDUINO = 1,
SERIALDEV_WHEEL = 2,
}
SerialType;
typedef struct
{
SimDevice m;
int id;
SerialType type;
struct sp_port* port;
SerialDeviceType devicetype;
// move these two they only apply to the haptic device
int motorsposition;
int numlights;
int numleds;
int startled;
int endled;
int baudrate;
double ampfactor;
double state;
union union
{ {
SimWindData simwinddata; USBDevice usbdevice;
SimHapticData simhapticdata; SoundDevice sounddevice;
ShiftLightsData shiftlightsdata; SerialDevice serialdevice;
WheelDevice wheeldevice; } d;
} u;
} }
SerialDevice; SimDevice;
int arduino_shiftlights_update(SimDevice* this, SimData* simdata);
int arduino_simwind_update(SimDevice* this, SimData* simdata);
int arduino_simhaptic_update(SimDevice* this, SimData* simdata);
int serialdev_free(SimDevice* this);
SerialDevice* new_serial_device(DeviceSettings* ds, MonocoqueSettings* ms);
/********* USB HID Devices *****/
typedef enum
{
USBDEV_UNKNOWN = 0,
USBDEV_TACHOMETER = 1,
USBDEV_GENERICHAPTIC = 2,
USBDEV_WHEEL = 3
}
USBType;
typedef struct
{
SimDevice m;
int id;
USBType type;
union
{
TachDevice tachdevice;
WheelDevice wheeldevice;
USBGenericHapticDevice hapticdevice;
} u;
}
USBDevice;
int usbdev_update(SimDevice* this, SimData* simdata);
int usbdev_free(SimDevice* this);
USBDevice* new_usb_device(DeviceSettings* ds, MonocoqueSettings* ms);
/********* Sound Devices *****/
typedef struct
{
SimDevice m;
int id;
int configcheck;
SoundEffectModulationType modulationType;
SoundData sounddata;
#ifdef USE_PULSEAUDIO
pa_stream *stream;
#else
PaStreamParameters outputParameters;
PaStream* stream;
#endif
}
SoundDevice;
int sounddev_engine_update(SimDevice* this, SimData* simdata);
int sounddev_gearshift_update(SimDevice* this, SimData* simdata);
int sounddev_tyreslip_update(SimDevice* this, SimData* simdata);
int sounddev_free(SimDevice* this);
SoundDevice* new_sound_device(DeviceSettings* ds, MonocoqueSettings* ms);
/***** Generic Methods *********/
int update(SimDevice* simdevice, SimData* simdata);
int devupdate(SimDevice* simdevice, SimData* simdata); int devupdate(SimDevice* simdevice, SimData* simdata);
int devinit(SimDevice* simdevices, int numdevices, DeviceSettings* ds, MonocoqueSettings* ms); int devinit(SimDevice* simdevice, DeviceSettings* ds);
int devfree(SimDevice* simdevices, int numdevices); int devfree(SimDevice* simdevice);
int simdevfree(SimDevice* this);
#endif #endif
-79
View File
@@ -1,79 +0,0 @@
#include "sound.h"
#include "../slog/slog.h"
#ifdef USE_PULSEAUDIO
pa_threaded_mainloop* mainloop;
pa_context* context;
void context_state_cb(pa_context* context, void* mainloop) {
pa_threaded_mainloop_signal(mainloop, 0);
}
int setupsound()
{
pa_mainloop_api *mainloop_api;
slogi("connecting pulseaudio...");
// Get a mainloop and its context
mainloop = pa_threaded_mainloop_new();
assert(mainloop);
mainloop_api = pa_threaded_mainloop_get_api(mainloop);
context = pa_context_new(mainloop_api, "Monocoque");
assert(context);
pa_context_set_state_callback(context, &context_state_cb, mainloop);
// Lock the mainloop so that it does not run and crash before the context is ready
pa_threaded_mainloop_lock(mainloop);
// Start the mainloop
assert(pa_threaded_mainloop_start(mainloop) == 0);
assert(pa_context_connect(context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) == 0);
// Wait for the context to be ready
for(;;) {
pa_context_state_t context_state = pa_context_get_state(context);
assert(PA_CONTEXT_IS_GOOD(context_state));
if (context_state == PA_CONTEXT_READY) break;
pa_threaded_mainloop_wait(mainloop);
}
slogi("successfully connected pulseaudio...");
return 1;
}
int freesound()
{
if (mainloop) {
pa_threaded_mainloop_lock(mainloop);
}
if (context)
pa_context_unref(context);
if (mainloop) {
pa_signal_done();
pa_threaded_mainloop_unlock(mainloop);
pa_threaded_mainloop_free(mainloop);
}
}
#else
int setupsound()
{
slogi("connecting portaudio...");
}
int freesound()
{
}
#endif
-13
View File
@@ -1,13 +0,0 @@
#ifndef _SOUND_H
#define _SOUND_H
#include <pulse/pulseaudio.h>
extern pa_threaded_mainloop* mainloop;
extern pa_context* context;
int setupsound();
int freesound();
#endif
@@ -1,5 +1,3 @@
#ifndef USE_PULSEAUDIO
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
@@ -12,80 +10,63 @@
#define SAMPLE_RATE (48000) #define SAMPLE_RATE (48000)
#define DURATION 4.0
#define AMPLITUDE .5
#ifndef M_PI #ifndef M_PI
#define M_PI (3.14159265) #define M_PI (3.14159265)
#endif #endif
int patestCallbackEngineRPM(const void* inputBuffer,
int patestCallback(const void* inputBuffer,
void* outputBuffer, void* outputBuffer,
unsigned long framesPerBuffer, unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo, const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags, PaStreamCallbackFlags statusFlags,
void* userData) void* userData)
{ {
SoundData* data = (SoundData*)userData; PATestData* data = (PATestData*)userData;
float* out = (float*)outputBuffer; float* out = (float*)outputBuffer;
memset(out, 0, framesPerBuffer * 2 * sizeof(float)); memset(out, 0, framesPerBuffer * 2 * sizeof(float));
unsigned int i; unsigned int i;
unsigned int n; unsigned int n;
//n = data->n; n = data->n;
(void) inputBuffer; /* Prevent unused argument warning. */ (void) inputBuffer; /* Prevent unused argument warning. */
for( i=0; i<framesPerBuffer; i++,n++ ) for( i=0; i<framesPerBuffer; i++,n++ )
{ {
static double t = 0.0; float v = 0;
double sample = AMPLITUDE * 32767.0 * sin(2.0 * M_PI * data->curr_frequency * t); v = data->amp * sin (2 * M_PI * ((float) n) / (float) SAMPLE_RATE);
t += 1.0 / SAMPLE_RATE; if ( data->gear_sound_data > 0 )
if (t >= DURATION) {
t = 0.0;
}
*out++ = sample;
*out++ = sample;
}
return 0;
}
int patestCallbackGearShift(const void* inputBuffer,
void* outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void* userData)
{
SoundData* data = (SoundData*)userData;
float* out = (float*)outputBuffer;
memset(out, 0, framesPerBuffer * 2 * sizeof(float));
unsigned int i;
unsigned int n;
//n = data->n;
(void) inputBuffer; /* Prevent unused argument warning. */
for( i=0; i<framesPerBuffer; i++,n++ )
{
static double t = 0.0;
double sample = 0;
if (data->frequency>0)
{ {
sample = AMPLITUDE * 32767.0 * sin(2.0 * M_PI * data->curr_frequency * data->curr_duration); if (n>=1764)
{
n=0;
}
}
else
{
if (n>=data->table_size)
{
n=0;
}
} }
data->curr_duration += 1.0 / SAMPLE_RATE; if ( data->gear_sound_data > 0 )
if (data->curr_duration >= data->duration) { {
data->curr_duration = 0.0; // right channel only?
data->curr_frequency = 0; // i have my butt hooked up to right channel... make this configurable?
*out++ = v;
}
else
{
*out++ = v;
*out++ = v;
} }
*out++ = sample;
*out++ = sample;
} }
data->n=n;
return 0;
} }
int usb_generic_shaker_free(SoundDevice* sounddevice) int usb_generic_shaker_free(SoundDevice* sounddevice)
@@ -116,28 +97,14 @@ int usb_generic_shaker_init(SoundDevice* sounddevice)
sounddevice->outputParameters.suggestedLatency = Pa_GetDeviceInfo( sounddevice->outputParameters.device )->defaultLowOutputLatency; sounddevice->outputParameters.suggestedLatency = Pa_GetDeviceInfo( sounddevice->outputParameters.device )->defaultLowOutputLatency;
sounddevice->outputParameters.hostApiSpecificStreamInfo = NULL; sounddevice->outputParameters.hostApiSpecificStreamInfo = NULL;
if (sounddevice->m.hapticeffect.effecttype == EFFECT_GEARSHIFT) err = Pa_OpenStream( &sounddevice->stream,
{ NULL, /* No input. */
err = Pa_OpenStream( &sounddevice->stream, &sounddevice->outputParameters, /* As above. */
NULL, /* No input. */ SAMPLE_RATE,
&sounddevice->outputParameters, /* As above. */ 440, /* Frames per buffer. */
SAMPLE_RATE, paClipOff, /* No out of range samples expected. */
440, /* Frames per buffer. */ patestCallback,
paClipOff, /* No out of range samples expected. */ &sounddevice->sounddata );
patestCallbackGearShift,
&sounddevice->sounddata );
}
else
{
err = Pa_OpenStream( &sounddevice->stream,
NULL, /* No input. */
&sounddevice->outputParameters, /* As above. */
SAMPLE_RATE,
440, /* Frames per buffer. */
paClipOff, /* No out of range samples expected. */
patestCallbackEngineRPM,
&sounddevice->sounddata );
}
if( err != paNoError ) if( err != paNoError )
{ {
goto error; goto error;
@@ -154,7 +121,8 @@ int usb_generic_shaker_init(SoundDevice* sounddevice)
error: error:
Pa_Terminate(); Pa_Terminate();
//fprintf( stderr, "An error occured while using the portaudio stream\n" );
//fprintf( stderr, "Error number: %d\n", err );
//fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err; return err;
} }
#endif
@@ -1,14 +1,9 @@
#ifndef _USB_GENERIC_SHAKER_H #ifndef _USB_GENERIC_SHAKER_H
#define _USB_GENERIC_SHAKER_H #define _USB_GENERIC_SHAKER_H
#include "../simdevice.h" #include "../sounddevice.h"
#ifdef USE_PULSEAUDIO
int usb_generic_shaker_init(SoundDevice* sounddevice, pa_threaded_mainloop* mainloop, pa_context* context, const char* devname, int volume, int pan, int channels, const char* streamname);
int usb_generic_shaker_free(SoundDevice* sounddevice, pa_threaded_mainloop* mainloop);
#else
int usb_generic_shaker_init(SoundDevice* sounddevice); int usb_generic_shaker_init(SoundDevice* sounddevice);
int usb_generic_shaker_free(SoundDevice* sounddevice); int usb_generic_shaker_free(SoundDevice* sounddevice);
#endif
#endif #endif
@@ -1,197 +0,0 @@
#ifdef USE_PULSEAUDIO
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
#include "usb_generic_shaker.h"
#include "../sounddevice.h"
#define FORMAT PA_SAMPLE_S16LE
#define SAMPLE_RATE (44100)
#define AMPLITUDE .5
#define DURATION 1.0
#ifndef M_PI
#define M_PI (3.14159265)
#endif
void gear_sound_stream(pa_stream *s, size_t length, void *userdata) {
SoundData* data = (SoundData*)userdata;
size_t num_samples = length / sizeof(int16_t);
int16_t buffer[num_samples];
for (size_t i = 0; i < num_samples; i++) {
static double t = 0.0;
double sample = 0;
if (data->frequency>0)
{
sample = AMPLITUDE * 32767.0 * sin(2.0 * M_PI * data->curr_frequency * data->curr_duration);
}
buffer[i] = (int16_t)sample;
data->curr_duration += 1.0 / SAMPLE_RATE;
if (data->curr_duration >= data->duration) {
data->curr_duration = 0.0;
data->curr_frequency = 0;
}
}
pa_stream_write(s, buffer, length, NULL, 0LL, PA_SEEK_RELATIVE);
}
double get_closest_frequency(size_t num_samples, double input_frequency) {
double samples_per_cycle = SAMPLE_RATE / input_frequency;
double adjusted_frequency = SAMPLE_RATE / (num_samples / floor(num_samples/samples_per_cycle) );
return adjusted_frequency;
}
void engine_sound_stream(pa_stream *s, size_t length, void *userdata) {
SoundData* data = (SoundData*)userdata;
double freq = data->curr_frequency;
size_t num_samples = length / sizeof(int16_t);
freq = get_closest_frequency( num_samples, freq );
//size_t num_samples = (size_t) (DURATION * SAMPLE_RATE);
int16_t buffer[num_samples];
//double t = 0;
for (size_t i = 0; i < num_samples; i++) {
double t = data->phase;
double sample = AMPLITUDE * 32767.0 * sin( 2.0 * M_PI * freq * t );
buffer[i] = (int16_t)sample;
t += 1.0 / SAMPLE_RATE;
if (t >= SAMPLE_RATE) {
t = 0;
}
data->phase = t;
}
data->phase = round(data->phase);
pa_stream_write(s, buffer, length, NULL, 0LL, PA_SEEK_RELATIVE);
}
void stream_success_cb(pa_stream *stream, int success, void *userdata) {
return;
}
void stream_state_cb(pa_stream *s, void *mainloop) {
pa_threaded_mainloop_signal(mainloop, 0);
}
int usb_generic_shaker_free(SoundDevice* sounddevice, pa_threaded_mainloop* mainloop)
{
pa_threaded_mainloop_lock(mainloop);
int err = 0;
if (sounddevice->stream)
{
pa_stream_disconnect(sounddevice->stream);
pa_stream_unref(sounddevice->stream);
// why is this wrong
//pa_xfree(sounddevice->stream);
}
pa_threaded_mainloop_unlock(mainloop);
return err;
}
int usb_generic_shaker_init(SoundDevice* sounddevice, pa_threaded_mainloop* mainloop, pa_context* context, const char* devname, int volume, int pan, int channels, const char* streamname)
{
pa_threaded_mainloop_lock(mainloop);
pa_stream *stream;
// Create a playback stream
pa_sample_spec sample_specifications;
sample_specifications.format = FORMAT;
sample_specifications.rate = SAMPLE_RATE;
sample_specifications.channels = channels;
pa_channel_map channel_map;
pa_channel_map_init_auto(&channel_map, channels, PA_CHANNEL_MAP_DEFAULT);
//pa_channel_map_init_stereo(&channel_map);
// not sure about what to do here
if(channels == 2)
{
pa_channel_map_parse(&channel_map, "front-left,front-right");
}
if(channels == 4)
{
pa_channel_map_parse(&channel_map, "front-left,front-right,rear-left,rear-right");
}
if(channels == 6)
{
pa_channel_map_parse(&channel_map, "front-left,front-right,front-center,lfe,rear-left,rear-right");
}
if(channels == 8)
{
pa_channel_map_parse(&channel_map, "front-left,front-right,front-center,lfe,rear-left,rear-right,side-left,side-right");
}
stream = pa_stream_new(context, streamname, &sample_specifications, &channel_map);
pa_stream_set_state_callback(stream, stream_state_cb, mainloop);
if (sounddevice->m.hapticeffect.effecttype == EFFECT_GEARSHIFT)
{
pa_stream_set_write_callback(stream, gear_sound_stream, &sounddevice->sounddata);
}
else
{
pa_stream_set_write_callback(stream, engine_sound_stream, &sounddevice->sounddata);
}
// recommended settings, i.e. server uses sensible values
pa_buffer_attr buffer_attr;
buffer_attr.maxlength = (uint32_t) 32767;
buffer_attr.tlength = (uint32_t) -1;
buffer_attr.prebuf = (uint32_t) -1;
buffer_attr.minreq = (uint32_t) -1;
pa_cvolume cv;
pa_cvolume_mute(&cv, channels);
pa_volume_t channel_volume = PA_CLAMP_VOLUME((pa_volume_t)((volume/100.d)*PA_VOLUME_NORM));
pa_stream_flags_t stream_flags;
stream_flags = PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_NOT_MONOTONIC | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_ADJUST_LATENCY | PA_STREAM_START_CORKED;
// for now i'm only supporting playing on one specified channel which is the concept you should build your setups around
cv.values[pan] = channel_volume;
assert(pa_stream_connect_playback(stream, devname, &buffer_attr, stream_flags, &cv, NULL) == 0);
// Wait for the stream to be ready
for(;;) {
pa_stream_state_t stream_state = pa_stream_get_state(stream);
assert(PA_STREAM_IS_GOOD(stream_state));
if (stream_state == PA_STREAM_READY) break;
pa_threaded_mainloop_wait(mainloop);
}
// Uncork the stream so it will start playing
pa_stream_cork(stream, 0, stream_success_cb, mainloop);
sounddevice->stream = stream;
pa_threaded_mainloop_unlock(mainloop);
return 0;
}
#endif
+16 -259
View File
@@ -1,281 +1,38 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include "sound.h"
#include "simdevice.h"
#include "sounddevice.h" #include "sounddevice.h"
#include "hapticeffect.h"
#include "sound/usb_generic_shaker.h" #include "sound/usb_generic_shaker.h"
#include "../simulatorapi/simapi/simapi/simdata.h" #include "../simulatorapi/simdata.h"
#include "../helper/parameters.h" #include "../helper/parameters.h"
#include "../slog/slog.h" #include "../slog/slog.h"
int gear_sound_set(SoundDevice* sounddevice, SimData* simdata) int sounddev_update(SoundDevice* sounddevice, SimData* simdata)
{ {
if (sounddevice->sounddata.last_gear != simdata->gear && simdata->gear > 1) sounddevice->sounddata.table_size = 44100/(simdata->rpms/60);
sounddevice->sounddata.gear_sound_data = 0;
if (sounddevice->sounddata.last_gear != simdata->gear)
{ {
//sounddevice->sounddata.gear_sound_data = 3.14; sounddevice->sounddata.gear_sound_data = sounddevice->sounddata.amp;
sounddevice->sounddata.curr_frequency = sounddevice->sounddata.frequency;
sounddevice->sounddata.curr_duration = 0;
} }
sounddevice->sounddata.last_gear = simdata->gear; sounddevice->sounddata.last_gear = simdata->gear;
slogt("set gear frequency to %i", sounddevice->sounddata.frequency);
} }
// we could make a vtable for these different effects too int sounddev_free(SoundDevice* sounddevice)
int sounddev_engine_update(SimDevice* this, SimData* simdata)
{ {
SoundDevice* sounddevice = (void *) this->derived; return usb_generic_shaker_free(sounddevice);
sounddevice->sounddata.curr_frequency = simdata->rpms/60;
//sounddevice->sounddata.table_size = 48000/(sounddevice->sounddata.frequency);
slogt("set engine frequency to %i", sounddevice->sounddata.frequency);
} }
double modulate(SoundDevice* sounddevice, double raw_effect, SoundEffectModulationType modulation) int sounddev_init(SoundDevice* sounddevice)
{
double modulated_effect = raw_effect;
switch (modulation)
{
case SOUND_EFFECT_MODULATION_FREQUENCY:
modulated_effect = (sounddevice->sounddata.frequencyMax - sounddevice->sounddata.frequency) * raw_effect;
break;
case SOUND_EFFECT_MODULATION_AMPLIFY:
case SOUND_EFFECT_MODULATION_NONE:
default:
modulated_effect = raw_effect;
}
return modulated_effect;
}
int sounddev_tyreslip_update(SimDevice* this, SimData* simdata)
{
SoundDevice* sounddevice = (void *) this->derived;
double effect = slipeffect(simdata, this->hapticeffect.effecttype, this->hapticeffect.tyre, this->hapticeffect.threshold, this->hapticeffect.useconfig, this->hapticeffect.configcheck, this->hapticeffect.tyrediameterconfig);
slogt("Updating sound device frequency from original tyre slip effect %f", effect);
if (effect > 0)
{
effect = modulate(sounddevice, effect, sounddevice->modulationType);
sounddevice->sounddata.curr_frequency = sounddevice->sounddata.frequency;
sounddevice->sounddata.curr_duration = sounddevice->sounddata.duration;
}
else
{
sounddevice->sounddata.curr_frequency = 0;
sounddevice->sounddata.curr_duration = 0;
}
}
int sounddev_tyrelock_update(SimDevice* this, SimData* simdata)
{
SoundDevice* sounddevice = (void *) this->derived;
double play = slipeffect(simdata, this->hapticeffect.effecttype, this->hapticeffect.tyre, this->hapticeffect.threshold, this->hapticeffect.useconfig, this->hapticeffect.configcheck, this->hapticeffect.tyrediameterconfig);
slogt("Updating sound device frequency from original tyre lock effect %f", play);
if (play > 0)
{
sounddevice->sounddata.curr_frequency = sounddevice->sounddata.frequency;
sounddevice->sounddata.curr_duration = sounddevice->sounddata.duration;
}
else
{
sounddevice->sounddata.curr_frequency = 0;
sounddevice->sounddata.curr_duration = 0;
}
}
int sounddev_absbrakes_update(SimDevice* this, SimData* simdata)
{
SoundDevice* sounddevice = (void *) this->derived;
double play = slipeffect(simdata, this->hapticeffect.effecttype, this->hapticeffect.tyre, this->hapticeffect.threshold, this->hapticeffect.useconfig, this->hapticeffect.configcheck, this->hapticeffect.tyrediameterconfig);
slogt("Updating sound device frequency from original abs effect %f", play);
if (play > 0)
{
sounddevice->sounddata.curr_frequency = sounddevice->sounddata.frequency;
sounddevice->sounddata.curr_duration = sounddevice->sounddata.duration;
}
else
{
sounddevice->sounddata.curr_frequency = 0;
sounddevice->sounddata.curr_duration = 0;
}
}
int sounddev_gearshift_update(SimDevice* this, SimData* simdata)
{
SoundDevice* sounddevice = (void *) this->derived;
gear_sound_set(sounddevice, simdata);
}
#ifdef USE_PULSEAUDIO
int sounddev_free(SimDevice* this)
{
SoundDevice* sounddevice = (void *) this->derived;
usb_generic_shaker_free(sounddevice, mainloop);
free(sounddevice);
return 0;
}
#else
int sounddev_free(SimDevice* this)
{
SoundDevice* sounddevice = (void *) this->derived;
usb_generic_shaker_free(sounddevice);
free(sounddevice);
return 0;
}
#endif
int sounddev_init(SoundDevice* sounddevice, const char* devname, MonocoqueTyreIdentifier tyre, SoundDeviceSettings sds)
{ {
slogi("initializing standalone sound device..."); slogi("initializing standalone sound device...");
sounddevice->sounddata.pitch = 1;
sounddevice->sounddata.pitch = 261.626;
sounddevice->sounddata.amp = 32;
sounddevice->sounddata.left_phase = sounddevice->sounddata.right_phase = 0;
sounddevice->sounddata.table_size = 44100/(100/60);
sounddevice->sounddata.last_gear = 0;
slogi("volume is: %i", sds.volume);
slogi("frequency is: %i", sds.frequency);
slogi("frequency Max is: %i", sds.frequencyMax);
slogi("pan is: %i", sds.pan);
slogi("channels is: %i", sds.channels);
slogi("duration is: %f", sds.duration);
sounddevice->modulationType = sds.modulation;
sounddevice->sounddata.frequency = sds.frequency;
sounddevice->sounddata.curr_frequency = 0;
sounddevice->sounddata.curr_duration = 0;
sounddevice->sounddata.phase = 0;
const char* streamname= "Engine";
switch (sounddevice->m.hapticeffect.effecttype) {
case (EFFECT_GEARSHIFT):
sounddevice->sounddata.last_gear = 0;
sounddevice->sounddata.duration = sds.duration;
streamname = "Gear";
break;
case (EFFECT_TYRESLIP):
streamname = "TyreSlip";
break;
case (EFFECT_TYRELOCK):
streamname = "TyreLock";
break;
case (EFFECT_ABSBRAKES):
streamname = "ABS";
break;
}
#ifdef USE_PULSEAUDIO
//pa_threaded_mainloop* mainloop;
//pa_context* context;
usb_generic_shaker_init(sounddevice, mainloop, context, devname, sds.volume, sds.pan, sds.channels, streamname);
#else
usb_generic_shaker_init(sounddevice); usb_generic_shaker_init(sounddevice);
#endif
} }
static const vtable engine_sound_simdevice_vtable = { &sounddev_engine_update, &sounddev_free };
static const vtable gear_sound_simdevice_vtable = { &sounddev_gearshift_update, &sounddev_free };
static const vtable tyreslip_sound_simdevice_vtable = { &sounddev_tyreslip_update, &sounddev_free };
static const vtable tyrelock_sound_simdevice_vtable = { &sounddev_tyrelock_update, &sounddev_free };
static const vtable absbrakes_sound_simdevice_vtable = { &sounddev_absbrakes_update, &sounddev_free };
SoundDevice* new_sound_device(DeviceSettings* ds, MonocoqueSettings* ms) {
SoundDevice* this = (SoundDevice*) malloc(sizeof(SoundDevice));
this->m.update = &update;
this->m.free = &simdevfree;
this->m.derived = this;
slogt("Attempting to configure sound device with subtype: %i", ds->effect_type);
switch (ds->effect_type) {
case (EFFECT_ENGINERPM):
this->m.hapticeffect.effecttype = EFFECT_ENGINERPM;
this->m.vtable = &engine_sound_simdevice_vtable;
slogi("Initializing sound device for engine vibrations.");
break;
case (EFFECT_GEARSHIFT):
this->m.hapticeffect.effecttype = EFFECT_GEARSHIFT;
this->m.vtable = &gear_sound_simdevice_vtable;
slogi("Initializing sound device for gear shift vibrations.");
break;
case (EFFECT_TYRESLIP):
this->m.hapticeffect.effecttype = EFFECT_TYRESLIP;
this->m.hapticeffect.threshold = ds->threshold;
this->m.hapticeffect.threshold = ds->threshold;
slogt("Haptic effect: %i %i", this->m.hapticeffect.effecttype, ds->effect_type);
this->m.hapticeffect.tyre = ds->tyre;
this->m.hapticeffect.useconfig = ms->useconfig;
this->m.hapticeffect.configcheck = &ms->configcheck;
this->m.hapticeffect.tyrediameterconfig = ms->tyre_diameter_config;
this->m.vtable = &tyreslip_sound_simdevice_vtable;
slogi("Initializing sound device for tyre slip vibrations.");
break;
case (EFFECT_TYRELOCK):
this->m.hapticeffect.effecttype = EFFECT_TYRELOCK;
this->m.hapticeffect.threshold = ds->threshold;
this->m.hapticeffect.threshold = ds->threshold;
slogt("Haptic effect: %i %i", this->m.hapticeffect.effecttype, ds->effect_type);
this->m.hapticeffect.tyre = ds->tyre;
this->m.hapticeffect.useconfig = ms->useconfig;
this->m.hapticeffect.configcheck = &ms->configcheck;
this->m.hapticeffect.tyrediameterconfig = ms->tyre_diameter_config;
this->m.vtable = &tyrelock_sound_simdevice_vtable;
slogi("Initializing sound device for tyre slip vibrations.");
break;
case (EFFECT_ABSBRAKES):
this->m.hapticeffect.effecttype = EFFECT_ABSBRAKES;
this->m.hapticeffect.threshold = ds->threshold;
this->m.hapticeffect.threshold = ds->threshold;
slogt("Haptic effect: %i %i", this->m.hapticeffect.effecttype, ds->effect_type);
this->m.hapticeffect.tyre = ds->tyre;
this->m.hapticeffect.useconfig = ms->useconfig;
this->m.hapticeffect.configcheck = &ms->configcheck;
this->m.hapticeffect.tyrediameterconfig = ms->tyre_diameter_config;
this->m.vtable = &absbrakes_sound_simdevice_vtable;
slogi("Initializing sound device for abs vibrations.");
break;
}
slogt("Attempting to use sound device %s", ds->sounddevsettings.dev);
int error = sounddev_init(this, ds->sounddevsettings.dev, ds->tyre, ds->sounddevsettings);
if (error != 0)
{
free(this);
return NULL;
}
return this;
}
+28 -16
View File
@@ -1,33 +1,45 @@
#ifndef _SOUNDDEVICE_H #ifndef _SOUNDDEVICE_H
#define _SOUNDDEVICE_H #define _SOUNDDEVICE_H
#ifdef USE_PULSEAUDIO
#include <pulse/pulseaudio.h>
#else
#include "portaudio.h" #include "portaudio.h"
#endif
#include "../simulatorapi/simdata.h"
#include "../helper/parameters.h"
typedef enum typedef enum
{ {
SOUND_EFFECT_MODULATION_NONE = 0, SOUNDDEV_UNKNOWN = 0,
SOUND_EFFECT_MODULATION_FREQUENCY = 1, SOUNDDEV_SHAKER = 1
SOUND_EFFECT_MODULATION_AMPLIFY = 2,
} }
SoundEffectModulationType; SoundType;
#define MAX_TABLE_SIZE (6000) #define MAX_TABLE_SIZE (6000)
typedef struct typedef struct
{ {
float sine[MAX_TABLE_SIZE];
float pitch;
int last_gear; int last_gear;
int volume; int left_phase;
uint32_t frequency; int right_phase;
uint32_t frequencyMax; int n;
double duration; int table_size;
int curr_frequency; int amp;
double curr_duration; int gear_sound_data;
double phase;
} }
SoundData; PATestData;
typedef struct
{
int id;
SoundType type;
PATestData sounddata;
PaStreamParameters outputParameters;
PaStream* stream;
}
SoundDevice;
int sounddev_update(SoundDevice* sounddevice, SimData* simdata);
int sounddev_init(SoundDevice* sounddevice);
int sounddev_free(SoundDevice* sounddevice);
#endif #endif
+1 -1
View File
@@ -5,7 +5,7 @@
#include "tachdevice.h" #include "tachdevice.h"
#include "revburner.h" #include "revburner.h"
#include "../../helper/confighelper.h" #include "../../helper/confighelper.h"
#include "../../simulatorapi/simapi/simapi/simdata.h" #include "../../simulatorapi/simdata.h"
#include "../../slog/slog.h" #include "../../slog/slog.h"
int tachdev_update(TachDevice* tachdevice, SimData* simdata) int tachdev_update(TachDevice* tachdevice, SimData* simdata)
+1 -1
View File
@@ -3,7 +3,7 @@
#include <hidapi/hidapi.h> #include <hidapi/hidapi.h>
#include "../helper/confighelper.h" #include "../helper/confighelper.h"
#include "../simulatorapi/simapi/simapi/simdata.h" #include "../simulatorapi/simdata.h"
//typedef int (*tachdev_update)(int revs); //typedef int (*tachdev_update)(int revs);
-105
View File
@@ -1,105 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glob.h>
#include "usbhapticdevice.h"
#include "../../helper/confighelper.h"
#include "../slog/slog.h"
const char* SYSFSRUMBLEPATH = "/sys/module/hid_fanatec/drivers/hid:f*/0003:0EB7:183B.*/rumble";
int cslelitev3_update(USBGenericHapticDevice* usbhapticdevice, int effecttype, int play)
{
int res = 0;
int value = 0;
if (play > 0)
{
switch (effecttype)
{
case (EFFECT_TYRESLIP):
value = 0xff0000;
break;
case (EFFECT_TYRELOCK):
value = 0xff00;
break;
case (EFFECT_ABSBRAKES):
value = 0xffff00;
break;
}
}
fprintf(usbhapticdevice->filehandle, "%i\n", value);
fflush(usbhapticdevice->filehandle);
return res;
}
int cslelitev3_free(USBGenericHapticDevice* usbhapticdevice)
{
int res = 0;
free(usbhapticdevice->dev);
fflush(usbhapticdevice->filehandle);
fclose(usbhapticdevice->filehandle);
return res;
}
int cslelitev3_init(USBGenericHapticDevice* usbhapticdevice)
{
slogi("initializing CSL Elite V3 Pedals...");
int res = 0;
glob_t globlist;
int i = 0;
if (glob(SYSFSRUMBLEPATH, GLOB_PERIOD, NULL, &globlist) == GLOB_NOSPACE || glob(SYSFSRUMBLEPATH, GLOB_PERIOD, NULL, &globlist) == GLOB_NOMATCH)
{
res = 1;
}
if (glob(SYSFSRUMBLEPATH, GLOB_PERIOD, NULL, &globlist) == GLOB_ABORTED)
{
res = 2;
}
if (res == 0)
{
while (globlist.gl_pathv[i])
{
if (i == 0)
{
usbhapticdevice->dev = strdup(globlist.gl_pathv[i]);
}
i++;
}
}
globfree(&globlist);
if (res == 1) {
sloge("Could not find attach Club Sport Elite V3 Pedals");
return res;
}
if (res == 2) {
sloge("Permissions issue finding Club Sport Elite V3 Pedals");
return res;
}
usbhapticdevice->filehandle = fopen(usbhapticdevice->dev, "w");
if (!usbhapticdevice->filehandle)
{
sloge("Could not open pedal device...");
return res;
}
slogd("CSL Elite V3 Pedals Successfully initialized...");
return res;
}
-8
View File
@@ -1,8 +0,0 @@
#ifndef _CSLELITEV3_H
#define _CSLELITEV3_H
int cslelitev3_update(USBGenericHapticDevice* usbhapticdevice, int effecttype, int play);
int cslelitev3_init(USBGenericHapticDevice* usbhapticdevice);
int cslelitev3_free(USBGenericHapticDevice* usbhapticdevice);
#endif
+4 -4
View File
@@ -5,7 +5,7 @@
#include "tachdevice.h" #include "tachdevice.h"
#include "../slog/slog.h" #include "../slog/slog.h"
const size_t REVBURNER_BUFSIZE = 8; const int buf_size = 65;
int revburner_update(TachDevice* tachdevice, int pulses) int revburner_update(TachDevice* tachdevice, int pulses)
@@ -13,8 +13,8 @@ int revburner_update(TachDevice* tachdevice, int pulses)
int res = 0; int res = 0;
unsigned char bytes[REVBURNER_BUFSIZE]; unsigned char bytes[buf_size];
for (int x = 0; x < REVBURNER_BUFSIZE; x++) for (int x = 0; x < buf_size; x++)
{ {
bytes[x] = 0x00; bytes[x] = 0x00;
} }
@@ -27,7 +27,7 @@ int revburner_update(TachDevice* tachdevice, int pulses)
if (tachdevice->handle) if (tachdevice->handle)
{ {
res = hid_write(tachdevice->handle, bytes, REVBURNER_BUFSIZE); res = hid_write(tachdevice->handle, bytes, buf_size);
} }
else else
{ {
-133
View File
@@ -1,133 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hidapi/hidapi.h>
#include "usbhapticdevice.h"
#include "../../helper/confighelper.h"
#include "../slog/slog.h"
#define SIMAGIC_VENDOR_ID 0x0483
#define SIMAGIC_PRODUCT_ID_P1000 0x0525
const size_t SIMAGIC_P1000_BUFSIZE = 49;
const char* SIMAGICP1000DEVSTRING = "SIMAGIC P1000 Pedals";
int senddevreport(USBGenericHapticDevice* usbhapticdevice, unsigned char* buf, size_t bufsize)
{
int res = 0;
if (usbhapticdevice->handle)
{
res = hid_write(usbhapticdevice->handle, buf, SIMAGIC_P1000_BUFSIZE);
slogd("sent %i bytes to %s", bufsize, SIMAGICP1000DEVSTRING);
slogt("sent bytes %02x %02x %02x %02x %02x %02x %02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
}
else
{
slogd("no handle");
}
return res;
}
int simagicp1000_update(USBGenericHapticDevice* usbhapticdevice, int effecttype, int play)
{
int res = 0;
int value = 0;
unsigned char bytes[SIMAGIC_P1000_BUFSIZE];
for (int x = 0; x < SIMAGIC_P1000_BUFSIZE; x++)
{
bytes[x] = 0x00;
}
if (play > 0)
{
bytes[0] = 0xEC;
// we can add config settings for these values
bytes[2] = 0x01;
bytes[3] = 0x0A;
bytes[4] = 0xFF;
switch (effecttype)
{
case (EFFECT_TYRESLIP):
bytes[1] = 0x02;
senddevreport(usbhapticdevice, bytes, SIMAGIC_P1000_BUFSIZE);
break;
case (EFFECT_TYRELOCK):
bytes[1] = 0x01;
senddevreport(usbhapticdevice, bytes, SIMAGIC_P1000_BUFSIZE);
break;
case (EFFECT_ABSBRAKES):
bytes[1] = 0x02;
senddevreport(usbhapticdevice, bytes, SIMAGIC_P1000_BUFSIZE);
bytes[1] = 0x01;
senddevreport(usbhapticdevice, bytes, SIMAGIC_P1000_BUFSIZE);
break;
}
}
else
{
bytes[1] = 0x01;
senddevreport(usbhapticdevice, bytes, SIMAGIC_P1000_BUFSIZE);
bytes[1] = 0x02;
senddevreport(usbhapticdevice, bytes, SIMAGIC_P1000_BUFSIZE);
}
return res;
}
int simagicp1000_free(USBGenericHapticDevice* usbhapticdevice)
{
int res = 0;
hid_close(usbhapticdevice->handle);
res = hid_exit();
return res;
return res;
}
int simagicp1000_init(USBGenericHapticDevice* usbhapticdevice)
{
slogi("initializing %s...", SIMAGICP1000DEVSTRING);
int res = 0;
res = hid_init();
usbhapticdevice->handle = hid_open(SIMAGIC_VENDOR_ID, SIMAGIC_PRODUCT_ID_P1000, NULL);
if (!usbhapticdevice->handle)
{
sloge("Could not find attached %s", SIMAGICP1000DEVSTRING);
res = hid_exit();
return 1;
}
else
{
unsigned char bytes[SIMAGIC_P1000_BUFSIZE];
for (int x = 0; x < SIMAGIC_P1000_BUFSIZE; x++)
{
bytes[x] = 0x00;
}
bytes[0] = 0xF1;
bytes[1] = 0x17;
bytes[2] = 0x00;
bytes[3] = 0x00;
bytes[4] = 0x00;
bytes[5] = 0x01;
bytes[6] = 0x02;
res = senddevreport(usbhapticdevice, bytes, SIMAGIC_P1000_BUFSIZE);
slogd("Initialization returned %i", res);
if(res != 0)
{
slogw("Problem with initialization of %s", SIMAGICP1000DEVSTRING);
}
}
slogd("Found %s...", SIMAGICP1000DEVSTRING);
return res;
}
-8
View File
@@ -1,8 +0,0 @@
#ifndef _SIMAGICP1000_H
#define _SIMAGICP1000_H
int simagicp1000_update(USBGenericHapticDevice* usbhapticdevice, int effecttype, int play);
int simagicp1000_init(USBGenericHapticDevice* usbhapticdevice);
int simagicp1000_free(USBGenericHapticDevice* usbhapticdevice);
#endif
@@ -1,86 +0,0 @@
#include <stdio.h>
#include <math.h>
#include <hidapi/hidapi.h>
#include "cammusc12.h"
#include "../../../slog/slog.h"
const int cammusc12_hidupdate_buf_size = 16;
int cammusc12_update(WheelDevice* wheeldevice, int maxrpm, int rpm, int gear, int velocity)
{
int res = 0;
unsigned char bytes[cammusc12_hidupdate_buf_size];
for (int x = 0; x < cammusc12_hidupdate_buf_size; x++)
{
bytes[x] = 0x00;
}
// byte 1 must be fc it seems
bytes[0] = 0xFA;
bytes[1] = 0xFB;
bytes[2] = 0xD4;
int perct = 0;
if(rpm > 0 && maxrpm > 0)
{
double rpmperct = (double) rpm / (double) maxrpm;
perct = trunc(nearbyint( rpmperct * 100 ));
}
bytes[3] = perct;
// bytes 2 and 3 are a 16 bit velocity
if ( velocity > 0 )
{
bytes[5] = (velocity >> 8) & 0xFF;
bytes[4] = velocity & 0xFF;
}
// byte 4 is gear
bytes[6] = gear-1;
slogt("writing bytes x%02xx%02xx%02xx%02xx%02x%02x%02x from rpm %i velocity %i gear %i", bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], rpm, velocity, gear);
if (wheeldevice->handle)
{
res = hid_write(wheeldevice->handle, bytes, cammusc12_hidupdate_buf_size);
}
else
{
slogd("no handle");
}
return res;
}
int cammusc12_free(WheelDevice* wheeldevice)
{
int res = 0;
hid_close(wheeldevice->handle);
res = hid_exit();
return res;
}
int cammusc12_init(WheelDevice* wheeldevice)
{
slogi("initializing cammus c12 wheel...");
int res = 0;
res = hid_init();
wheeldevice->handle = hid_open(0x3416, 0x1023, NULL);
if (!wheeldevice->handle)
{
sloge("Could not find attached Cammus C12 Wheel");
res = hid_exit();
return 1;
}
slogd("Found Cammus C12 Wheel...");
return res;
}
@@ -1,10 +0,0 @@
#ifndef _CAMMUSC12_H
#define _CAMMUSC12_H
#include "../../wheeldevice.h"
int cammusc12_update(WheelDevice* wheeldevice, int maxrpm, int rpm, int gear, int velocity);
int cammusc12_init(WheelDevice* wheeldevice);
int cammusc12_free(WheelDevice* wheeldevice);
#endif
@@ -1,99 +0,0 @@
#include <stdio.h>
#include <math.h>
#include <hidapi/hidapi.h>
#include "cammusc5.h"
#include "../../../slog/slog.h"
const int cammusc5_hidupdate_buf_size = 14;
const int num_avail_leds = 9;
int cammusc5_update(WheelDevice* wheeldevice, int maxrpm, int rpm, int gear, int velocity)
{
int res = 0;
unsigned char bytes[cammusc5_hidupdate_buf_size];
for (int x = 0; x < cammusc5_hidupdate_buf_size; x++)
{
bytes[x] = 0x00;
}
// byte 1 must be fc it seems
bytes[0] = 0xFC;
// byte 2 is number of lit leds, assuming 9 available leds,
// if we send 10, all leds will blink singling a gear change
// attempting to build in a margin before the maxrpm is achieved
int litleds = 0;
if(rpm > 0 && maxrpm > 0)
{
int rpmmargin = ceil(.05*maxrpm);
int rpminterval = (maxrpm-rpmmargin) / (num_avail_leds+1);
for (int l = 1; l <= (num_avail_leds+1); l++)
{
if(rpm >= (rpminterval * l))
{
litleds = l;
}
}
}
bytes[1] = litleds;
// bytes 2 and 3 are a 16 bit velocity
if ( velocity > 0 )
{
bytes[2] = (velocity >> 8) & 0xFF;
bytes[3] = velocity & 0xFF;
}
// byte 4 is gear
bytes[4] = gear-1;
slogt("writing bytes x%02xx%02xx%02xx%02xx%02x from rpm %i velocity %i gear %i", bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], rpm, velocity, gear);
if (wheeldevice->handle)
{
res = hid_write(wheeldevice->handle, bytes, cammusc5_hidupdate_buf_size);
}
else
{
slogd("no handle");
}
return res;
}
int cammusc5_free(WheelDevice* wheeldevice)
{
int res = 0;
hid_close(wheeldevice->handle);
res = hid_exit();
return res;
}
int cammusc5_init(WheelDevice* wheeldevice)
{
slogi("initializing cammus c5 wheel...");
int res = 0;
res = hid_init();
wheeldevice->handle = hid_open(0x3416, 0x1021, NULL);
if (!wheeldevice->handle)
{
sloge("Could not find attached Cammus C5 Wheel");
res = hid_exit();
return 1;
}
slogd("Found Cammus C5 Wheel...");
return res;
}
@@ -1,10 +0,0 @@
#ifndef _CAMMUSC5_H
#define _CAMMUSC5_H
#include "../../wheeldevice.h"
int cammusc5_update(WheelDevice* wheeldevice, int maxrpm, int rpm, int gear, int velocity);
int cammusc5_init(WheelDevice* wheeldevice);
int cammusc5_free(WheelDevice* wheeldevice);
#endif
+3 -79
View File
@@ -1,56 +1,35 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#include "usbdevice.h" #include "usbdevice.h"
#include "simdevice.h"
#include "../helper/parameters.h" #include "../helper/parameters.h"
#include "../simulatorapi/simapi/simapi/simdata.h" #include "../simulatorapi/simdata.h"
#include "../slog/slog.h" #include "../slog/slog.h"
int usbdev_update(SimDevice* this, SimData* simdata) int usbdev_update(USBDevice* usbdevice, SimData* simdata)
{ {
USBDevice* usbdevice = (void *) this->derived;
switch ( usbdevice->type ) switch ( usbdevice->type )
{ {
case USBDEV_UNKNOWN : case USBDEV_UNKNOWN :
case USBDEV_TACHOMETER : case USBDEV_TACHOMETER :
tachdev_update(&usbdevice->u.tachdevice, simdata); tachdev_update(&usbdevice->u.tachdevice, simdata);
break; break;
case USBDEV_WHEEL :
wheeldev_update(&usbdevice->u.wheeldevice, simdata);
break;
case USBDEV_GENERICHAPTIC :
usbhapticdev_update(&usbdevice->u.hapticdevice, simdata, this->hapticeffect.tyre, this->hapticeffect.useconfig, this->hapticeffect.configcheck, this->hapticeffect.tyrediameterconfig);
break;
} }
return 0; return 0;
} }
int usbdev_free(SimDevice* this) int usbdev_free(USBDevice* usbdevice)
{ {
USBDevice* usbdevice = (void *) this->derived;
slogt("Usb device free");
switch ( usbdevice->type ) switch ( usbdevice->type )
{ {
case USBDEV_UNKNOWN : case USBDEV_UNKNOWN :
case USBDEV_TACHOMETER : case USBDEV_TACHOMETER :
tachdev_free(&usbdevice->u.tachdevice); tachdev_free(&usbdevice->u.tachdevice);
break; break;
case USBDEV_WHEEL :
wheeldev_free(&usbdevice->u.wheeldevice);
break;
case USBDEV_GENERICHAPTIC :
usbhapticdev_free(&usbdevice->u.hapticdevice);
break;
} }
free(usbdevice);
return 0; return 0;
} }
@@ -58,68 +37,13 @@ int usbdev_init(USBDevice* usbdevice, DeviceSettings* ds)
{ {
slogi("initializing usb device..."); slogi("initializing usb device...");
int error = 0; int error = 0;
//usbdevice->type = USBDEV_TACHOMETER;
switch ( usbdevice->type ) switch ( usbdevice->type )
{ {
case USBDEV_UNKNOWN : case USBDEV_UNKNOWN :
case USBDEV_TACHOMETER : case USBDEV_TACHOMETER :
error = tachdev_init(&usbdevice->u.tachdevice, ds); error = tachdev_init(&usbdevice->u.tachdevice, ds);
break; break;
case USBDEV_WHEEL :
error = wheeldev_init(&usbdevice->u.wheeldevice, ds);
break;
case USBDEV_GENERICHAPTIC :
error = usbhapticdev_init(&usbdevice->u.hapticdevice, ds);
break;
} }
return error; return error;
} }
static const vtable usb_simdevice_vtable = { &usbdev_update, &usbdev_free };
USBDevice* new_usb_device(DeviceSettings* ds, MonocoqueSettings* ms) {
USBDevice* this = (USBDevice*) malloc(sizeof(USBDevice));
this->m.update = &update;
this->m.free = &simdevfree;
this->m.derived = this;
this->m.vtable = &usb_simdevice_vtable;
// TODO: turn this into a switch when we get more devices
this->type = USBDEV_TACHOMETER;
if(ds->dev_subtype == SIMDEVTYPE_USBWHEEL)
{
this->type = USBDEV_WHEEL;
}
// really generic haptic isn't and shouldn't be it's own type
// it's an attribute that is added to a device via composition
// same if that haptic device is a serial device
if (ds->dev_subtype == SIMDEVTYPE_USBHAPTIC)
{
this->m.hapticeffect.threshold = ds->threshold;
this->m.hapticeffect.effecttype = ds->effect_type;
this->m.hapticeffect.tyre = ds->tyre;
this->m.hapticeffect.useconfig = ms->useconfig;
this->m.hapticeffect.configcheck = &ms->configcheck;
this->m.hapticeffect.tyrediameterconfig = ms->tyre_diameter_config;
this->type = USBDEV_GENERICHAPTIC;
}
int error = usbdev_init(this, ds);
if (error != 0)
{
free(this);
return NULL;
}
this->m.initialized = true;
return this;
}
+24 -2
View File
@@ -2,7 +2,29 @@
#define _USBDEVICE_H #define _USBDEVICE_H
#include "tachdevice.h" #include "tachdevice.h"
#include "wheeldevice.h" #include "../helper/confighelper.h"
#include "usbhapticdevice.h" #include "../simulatorapi/simdata.h"
typedef enum
{
USBDEV_UNKNOWN = 0,
USBDEV_TACHOMETER = 1
}
USBType;
typedef struct
{
int id;
USBType type;
union
{
TachDevice tachdevice;
} u;
}
USBDevice;
int usbdev_update(USBDevice* usbdevice, SimData* simdata);
int usbdev_init(USBDevice* usbdevice, DeviceSettings* ds);
int usbdev_free(USBDevice* usbdevice);
#endif #endif
-115
View File
@@ -1,115 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include "usbhapticdevice.h"
#include "hapticeffect.h"
#include "usb/cslelitev3.h"
#include "usb/simagicp1000.h"
#include "../../helper/confighelper.h"
#include "../../simulatorapi/simapi/simapi/simdata.h"
#include "../../slog/slog.h"
int usbhapticdev_update(USBGenericHapticDevice* usbhapticdevice, SimData* simdata, int tyre, int useconfig, int* configcheck, char* configfile)
{
double play = slipeffect(simdata, usbhapticdevice->effecttype, tyre, usbhapticdevice->threshold, useconfig, configcheck, configfile);
if (play != usbhapticdevice->state)
{
int rplay = 0;
if(play > 0)
{
rplay = 1;
switch ( usbhapticdevice->type )
{
case USBHAPTIC_CSLELITEV3PEDALS:
cslelitev3_update(usbhapticdevice, usbhapticdevice->effecttype, rplay);
break;
case USBHAPTIC_SIMAGICP1000PEDALS:
simagicp1000_update(usbhapticdevice, usbhapticdevice->effecttype, rplay);
break;
}
}
else
{
switch ( usbhapticdevice->type )
{
case USBHAPTIC_CSLELITEV3PEDALS:
cslelitev3_update(usbhapticdevice, usbhapticdevice->effecttype, rplay);
break;
case USBHAPTIC_SIMAGICP1000PEDALS:
simagicp1000_update(usbhapticdevice, usbhapticdevice->effecttype, rplay);
break;
}
}
usbhapticdevice->state = play;
}
return 0;
}
int usbhapticdev_free(USBGenericHapticDevice* usbhapticdevice)
{
slogt("closing usb haptic device");
switch ( usbhapticdevice->type )
{
case USBHAPTIC_CSLELITEV3PEDALS:
cslelitev3_free(usbhapticdevice);
break;
case USBHAPTIC_SIMAGICP1000PEDALS:
simagicp1000_free(usbhapticdevice);
break;
}
return 0;
}
int usbhapticdev_init(USBGenericHapticDevice* usbhapticdevice, DeviceSettings* ds)
{
int error = 0;
usbhapticdevice->state = 0;
usbhapticdevice->value0 = ds->usbdevsettings.value0;
usbhapticdevice->value1 = ds->usbdevsettings.value1;
usbhapticdevice->state = usbhapticdevice->value0;
usbhapticdevice->effecttype = ds->effect_type;
usbhapticdevice->threshold = ds->threshold;
if(ds->effect_type == EFFECT_TYRESLIP)
{
usbhapticdevice->effecttype = EFFECT_TYRESLIP;
}
if(ds->effect_type == EFFECT_TYRELOCK)
{
usbhapticdevice->effecttype = EFFECT_TYRELOCK;
}
if(ds->effect_type == EFFECT_ABSBRAKES)
{
usbhapticdevice->effecttype = EFFECT_ABSBRAKES;
}
slogi("initializing standalone usb haptic device...");
// detection of usb device model
switch (ds->dev_subsubtype) {
case (SIMDEVSUBTYPE_SIMAGICP1000PEDALS):
usbhapticdevice->type = USBHAPTIC_SIMAGICP1000PEDALS;
error = simagicp1000_init(usbhapticdevice);
break;
case (SIMDEVSUBTYPE_CSLELITEV3PEDALS):
usbhapticdevice->type = USBHAPTIC_CSLELITEV3PEDALS;
error = cslelitev3_init(usbhapticdevice);
break;
default:
slogw("Possibly unknown device");
}
if(usbhapticdevice->handle == 0)
{
error = MONOCOQUE_ERROR_INVALID_DEV;
return error;
}
return error;
}
-37
View File
@@ -1,37 +0,0 @@
#ifndef _USBHAPTICDEVICE_H
#define _USBHAPTICDEVICE_H
#include <hidapi/hidapi.h>
#include "../helper/confighelper.h"
#include "../simulatorapi/simapi/simapi/simdata.h"
typedef enum
{
USBHAPTIC_UNKNOWN = 0,
USBHAPTIC_CSLELITEV3PEDALS = 1,
USBHAPTIC_SIMAGICP1000PEDALS = 2
}
HapticType;
typedef struct
{
int id;
HapticType type;
double state;
double threshold;
int value0;
int value1;
VibrationEffectType effecttype;
FILE* filehandle;
hid_device* handle;
char* dev;
}
USBGenericHapticDevice;
int usbhapticdev_update(USBGenericHapticDevice* hapticdevice, SimData* simdata, int tyre, int useconfig, int* configcheck, char* configfile);
int usbhapticdev_init(USBGenericHapticDevice* hapticdevice, DeviceSettings* ds);
int usbhapticdev_free(USBGenericHapticDevice* hapticdevice);
#endif
-74
View File
@@ -1,74 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "usb/wheels/cammusc5.h"
#include "usb/wheels/cammusc12.h"
#include "serial/moza.h"
#include "wheeldevice.h"
#include "../helper/confighelper.h"
#include "../simulatorapi/simapi/simapi/simdata.h"
#include "../slog/slog.h"
int wheeldev_update(WheelDevice* wheeldevice, SimData* simdata)
{
switch ( wheeldevice->type )
{
case WHEELDEV_UNKNOWN :
case WHEELDEV_CAMMUSC5 :
cammusc5_update(wheeldevice, simdata->maxrpm, simdata->rpms, simdata->gear, simdata->velocity);
break;
case WHEELDEV_CAMMUSC12 :
cammusc12_update(wheeldevice, simdata->maxrpm, simdata->rpms, simdata->gear, simdata->velocity);
break;
}
return 0;
}
int wheeldev_free(WheelDevice* wheeldevice)
{
switch ( wheeldevice->type )
{
case WHEELDEV_UNKNOWN :
case WHEELDEV_CAMMUSC5 :
cammusc5_update(wheeldevice, 0, 0, 0, 0);
cammusc5_free(wheeldevice);
break;
case WHEELDEV_CAMMUSC12 :
cammusc12_update(wheeldevice, 0, 0, 0, 0);
cammusc12_free(wheeldevice);
break;
}
return 0;
}
int wheeldev_init(WheelDevice* wheeldevice, DeviceSettings* ds)
{
slogi("initializing wheel device...");
int error = 0;
// detection of wheel model
switch (ds->dev_subsubtype) {
case SIMDEVSUBTYPE_CAMMUSC5:
wheeldevice->type = WHEELDEV_CAMMUSC5;
slogi("Attempting to initialize cammus C5");
error = cammusc5_init(wheeldevice);
break;
case SIMDEVSUBTYPE_CAMMUSC12:
wheeldevice->type = WHEELDEV_CAMMUSC12;
slogi("Attempting to initialize cammus C12");
error = cammusc12_init(wheeldevice);
break;
default:
wheeldevice->type = WHEELDEV_UNKNOWN;
slogw("Unknown cammus wheel detected, trying C5");
error = cammusc5_init(wheeldevice);
break;
}
return error;
}
-32
View File
@@ -1,32 +0,0 @@
#ifndef _WHEELDEVICE_H
#define _WHEELDEVICE_H
#include <hidapi/hidapi.h>
#include "../helper/confighelper.h"
#include "../simulatorapi/simapi/simapi/simdata.h"
//typedef int (*tachdev_update)(int revs);
typedef enum
{
WHEELDEV_UNKNOWN = 0,
WHEELDEV_CAMMUSC5 = 1,
WHEELDEV_CAMMUSC12 = 2,
WHEELDEV_MOZAR5 = 3
}
WheelType;
typedef struct
{
int id;
WheelType type;
hid_device* handle;
char* port;
}
WheelDevice;
int wheeldev_update(WheelDevice* wheeldevice, SimData* simdata);
int wheeldev_init(WheelDevice* wheeldevice, DeviceSettings* ds);
int wheeldev_free(WheelDevice* wheeldevice);
#endif
-1
View File
@@ -3,7 +3,6 @@ set(gameloop_source_files
gameloop.h gameloop.h
tachconfig.c tachconfig.c
tachconfig.h tachconfig.h
loopdata.h
) )
set(LIBXML_INCLUDE_DIR /usr/include/libxml2) set(LIBXML_INCLUDE_DIR /usr/include/libxml2)
+52 -714
View File
@@ -1,4 +1,3 @@
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -6,38 +5,16 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <poll.h> #include <poll.h>
#include <termios.h> #include <termios.h>
#include <signal.h>
#include <uv.h>
#include "gameloop.h" #include "gameloop.h"
#include "loopdata.h"
#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/simdata.h"
#include "../simulatorapi/simapi/simapi/simdata.h" #include "../simulatorapi/simmapper.h"
#include "../simulatorapi/simapi/simapi/simmapper.h"
#include "../slog/slog.h" #include "../slog/slog.h"
#define DEFAULT_UPDATE_RATE 240.0 #define DEFAULT_UPDATE_RATE 120.0
#define SIM_CHECK_RATE 1.0
bool go = false;
bool go2 = false;
struct sigaction act;
uv_idle_t idler;
uv_timer_t datachecktimer;
uv_timer_t datamaptimer;
uv_udp_t recv_socket;
bool doui = false;
int appstate = 0;
void shmdatamapcallback(uv_timer_t* handle);
void datacheckcallback(uv_timer_t* handle);
void startdatalogger(MonocoqueSettings* ms, loop_data* l);
int showstats(SimData* simdata) int showstats(SimData* simdata)
{ {
@@ -188,400 +165,19 @@ int showstats(SimData* simdata)
fflush(stdout); fflush(stdout);
} }
void simapilib_loginfo(char* message) int looper(SimDevice* devices[], int numdevices, Simulator simulator)
{
slogi(message);
}
void simapilib_logdebug(char* message)
{
slogd(message);
}
void simapilib_logtrace(char* message)
{
slog_display(SLOG_TRACE, 1, message);
}
void on_timer_close_complete(uv_handle_t* handle)
{
free(handle);
}
void devicetimercallback(uv_timer_t* handle)
{
void* b = uv_handle_get_data((uv_handle_t*) handle);
device_loop_data* f = (device_loop_data*) b;
SimData* simdata = f->simdata;
SimDevice* device = f->simdevice;
device->update(device, simdata);
}
void looprun(MonocoqueSettings* ms, loop_data* f, SimData* simdata)
{
if (doui == true)
{
slogi("looking for ui config %s pass 1", ms->config_str);
int confignum = getconfigtouse2(ms->config_str, simdata->car, f->sim);
if(confignum == -1)
{
slogi("looking for ui config %s pass 2", ms->config_str);
confignum = getconfigtouse1(ms->config_str, simdata->car, f->sim);
}
if(confignum == -1)
{
slogi("looking for ui config %s pass 3", ms->config_str);
confignum = getconfigtouse(ms->config_str, simdata->car, f->sim);
}
int configureddevices;
configcheck(ms->config_str, confignum, &configureddevices);
DeviceSettings* ds = malloc(configureddevices * sizeof(DeviceSettings));
slogd("loading confignum %i, with %i devices.", confignum, configureddevices);
f->numdevices = uiloadconfig(ms->config_str, confignum, configureddevices, ms, ds);
if(ms->useconfig == 1)
{
ms->configcheck = 0;
}
f->simdevices = malloc(f->numdevices * sizeof(SimDevice));
int initdevices = devinit(f->simdevices, configureddevices, ds, ms);
int i = 0;
for( i = 0; i < configureddevices; i++)
{
settingsfree(ds[i]);
}
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;
SimDevice* devices = f->simdevices;
f->device_timers = (uv_timer_t*) (malloc(uv_handle_size(UV_TIMER) * numdevices));
f->device_batons = (device_loop_data*) (malloc(sizeof(device_loop_data) * numdevices));
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
device_loop_data* dld = &f->device_batons[x];
dld->simdevice = &devices[x];
dld->simdata = simdata;
uv_timer_t* dt = &f->device_timers[x];
uv_timer_init(uv_default_loop(), dt);
uv_handle_set_data((uv_handle_t*) dt, (void*) dld);
int interval = 1000/devices[x].fps;
uv_timer_start(dt, devicetimercallback, 0, interval);
slogi("starting device at %i fps (%i ms ticks)", devices[x].fps, interval);
}
}
doui = false;
}
else
{
showstats(simdata);
//SimDevice* devices = f->simdevices;
//int numdevices = f->numdevices;
//for (int x = 0; x < numdevices; x++)
//{
// if (devices[x].initialized == true && devices[x].type == 2)
// {
// devices[x].update(&devices[x], simdata);
// }
//}
}
}
void shmdatamapcallback(uv_timer_t* handle)
{
void* b = uv_handle_get_data((uv_handle_t*) handle);
loop_data* f = (loop_data*) b;
SimData* simdata = f->simdata;
SimMap* simmap = f->simmap;
MonocoqueSettings* ms = f->ms;
//appstate = 2;
if (appstate == 2)
{
simdatamap(simdata, simmap, NULL, f->map, false, NULL);
looprun(ms, f, simdata);
}
if (f->simstate == false || simdata->simstatus <= 1 || appstate <= 1)
{
if(f->releasing == false)
{
f->releasing = true;
uv_timer_stop(handle);
slogi("releasing devices, please wait");
f->uion = false;
SimDevice* devices = f->simdevices;
int numdevices = f->numdevices;
// help things spin down
simdata->rpms = 0;
simdata->velocity = 0;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
uv_timer_t* dt = &f->device_timers[x];
slogt("attempting device timer stop and release");
slogt("timer active status %i", uv_is_active((uv_handle_t*) dt));
uv_timer_stop(dt);
//uv_close((uv_handle_t*) dt, on_timer_close_complete);
}
}
free(f->device_batons);
free(f->device_timers);
slogt("stopped device timers");
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].free(&devices[x]);
}
}
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);
slogd("simfree returned %i", r);
f->numdevices = 0;
slogi("stopped mapping data, press q again to quit");
//stopui(ms->ui_type, f);
// free loop data
if(appstate > 0)
{
uv_timer_start(&datachecktimer, datacheckcallback, 3000, 1000);
}
f->releasing = false;
if(appstate > 1)
{
appstate = 1;
}
}
}
}
void on_alloc(uv_handle_t* client, size_t suggested_size, uv_buf_t* buf) {
buf->base = malloc(suggested_size);
buf->len = suggested_size;
bzero(buf->base, suggested_size);
slogt("udp malloc:%lu %p\n",buf->len,buf->base);
}
static void on_udp_recv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* rcvbuf, const struct sockaddr* addr, unsigned flags) {
if (nread > 0) {
slogt("udp data received");
}
char* a;
a = rcvbuf->base;
void* b = uv_handle_get_data((uv_handle_t*) handle);
loop_data* f = (loop_data*) b;
SimData* simdata = f->simdata;
SimMap* simmap = f->simmap;
MonocoqueSettings* ms = f->ms;
if (appstate == 2)
{
simdatamap(simdata, simmap, NULL, f->map, true, a);
looprun(ms, f, simdata);
}
if (f->simstate == false || simdata->simstatus <= 1 || appstate <= 1)
{
if(f->releasing == false)
{
f->releasing = true;
uv_udp_recv_stop(handle);
slogi("releasing devices, please wait");
f->uion = false;
SimDevice* devices = f->simdevices;
int numdevices = f->numdevices;
// help things spin down
simdata->rpms = 0;
simdata->velocity = 0;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].free(&devices[x]);
}
}
free(devices);
int r = simfree(simdata, simmap, f->map);
slogd("simfree returned %i", r);
f->numdevices = 0;
slogi("stopped mapping data, press q again to quit");
//stopui(ms->ui_type, f);
// free loop data
if(appstate > 0)
{
uv_timer_start(&datachecktimer, datacheckcallback, 3000, 1000);
}
f->releasing = false;
if(appstate > 1)
{
appstate = 1;
}
}
}
slogt("udp free :%lu %p\n",rcvbuf->len,rcvbuf->base);
free(rcvbuf->base);
}
int startudp(int port)
{
uv_udp_init(uv_default_loop(), &recv_socket);
struct sockaddr_in recv_addr;
uv_ip4_addr("0.0.0.0", port, &recv_addr);
int err = uv_udp_bind(&recv_socket, (const struct sockaddr *) &recv_addr, UV_UDP_REUSEADDR);
slogt("initial udp error is %i", err);
return err;
}
void udpstart(MonocoqueSettings* sms, loop_data* f, SimData* simdata, SimMap* simmap)
{
if (appstate == 2)
{
simdatamap(simdata, simmap, NULL, f->sim, true, NULL);
if (doui == true)
{
looprun(sms, f, simdata);
}
}
}
void datacheckcallback(uv_timer_t* handle)
{
void* b = uv_handle_get_data((uv_handle_t*) handle);
loop_data* f = (loop_data*) b;
SimData* simdata = f->simdata;
SimMap* simmap = f->simmap;
if ( appstate == 1 )
{
SimInfo si = getSim(simdata, simmap, f->ms->force_udp_mode, startudp, false);
//TODO: move all this to a siminfo struct in loop_data
f->simstate = si.isSimOn;
f->sim = si.simulatorapi;
f->map = si.mapapi;
f->use_udp = si.SimUsesUDP;
if(f->ms->force_udp_mode == true)
{
f->use_udp = true;
}
}
if (f->simstate == true && simdata->simstatus >= 2)
{
if ( appstate == 1 )
{
appstate++;
doui = true;
simdata->tyrediameter[0] = -1;
simdata->tyrediameter[1] = -1;
simdata->tyrediameter[2] = -1;
simdata->tyrediameter[3] = -1;
if(f->use_udp == true)
{
slogt("starting udp receive loop");
udpstart(f->ms, f, simdata, simmap);
uv_udp_recv_start(&recv_socket, on_alloc, on_udp_recv);
slogt("udp receive loop started");
}
else
{
int interval = 1000 / f->ms->fps;
slogd("starting telemetry mapping at %i fps (%i ms ticks)", f->ms->fps, interval);
uv_timer_start(&datamaptimer, shmdatamapcallback, 2000, interval);
}
uv_timer_stop(handle);
}
}
if (appstate == 0)
{
slogi("stopping checking for data");
uv_timer_stop(handle);
}
}
void cb(uv_poll_t* handle, int status, int events)
{
void* b = uv_handle_get_data((uv_handle_t*) handle);
loop_data* f = (loop_data*) b;
char ch;
scanf("%c", &ch);
if (ch == 'q')
{
if(f->releasing == false && doui == false)
{
appstate--;
fprintf(stdout, "\nUser requested stop appstate is now %i\n", appstate);
fflush(stdout);
slogi("User requested stop appstate is now %i", appstate);
}
}
if (appstate == 0)
{
slogi("Monocoque is exiting...");
uv_timer_stop(&datachecktimer);
uv_poll_stop(handle);
}
}
int monocoque_mainloop(MonocoqueSettings* ms)
{ {
slogi("preparing game loop with %i devices...", numdevices);
SimData* simdata = malloc(sizeof(SimData)); SimData* simdata = malloc(sizeof(SimData));
SimMap* simmap = createSimMap(); SimMap* simmap = malloc(sizeof(SimMap));
int error = siminit(simdata, simmap, simulator);
if (error != MONOCOQUE_ERROR_NONE)
{
return error;
}
struct termios newsettings, canonicalmode; struct termios newsettings, canonicalmode;
tcgetattr(0, &canonicalmode); tcgetattr(0, &canonicalmode);
@@ -593,310 +189,52 @@ int monocoque_mainloop(MonocoqueSettings* ms)
char ch; char ch;
struct pollfd mypoll = { STDIN_FILENO, POLLIN|POLLPRI }; struct pollfd mypoll = { STDIN_FILENO, POLLIN|POLLPRI };
uv_poll_t* poll = (uv_poll_t*) malloc(uv_handle_size(UV_POLL)); double update_rate = DEFAULT_UPDATE_RATE;
int t=0;
loop_data* baton = (loop_data*) malloc(sizeof(loop_data)); int go = true;
baton->simmap = simmap; while (go == true)
baton->simdata = simdata;
baton->ms = ms;
baton->simstate = false;
baton->uion = false;
baton->releasing = false;
baton->sim = 0;
baton->req.data = (void*) baton;
uv_handle_set_data((uv_handle_t*) &datachecktimer, (void*) baton);
uv_handle_set_data((uv_handle_t*) &datamaptimer, (void*) baton);
uv_handle_set_data((uv_handle_t*) &recv_socket, (void*) baton);
uv_handle_set_data((uv_handle_t*) poll, (void*) baton);
appstate = 1;
slogd("setting initial app state");
uv_timer_init(uv_default_loop(), &datachecktimer);
fprintf(stdout, "Searching for sim data... Press q to quit...\n");
uv_timer_start(&datachecktimer, datacheckcallback, 1000, 1000);
set_simapi_log_info(simapilib_loginfo);
set_simapi_log_debug(simapilib_logdebug);
set_simapi_log_trace(simapilib_logtrace);
if (0 != uv_poll_init(uv_default_loop(), poll, 0))
{ {
return 1; simdatamap(simdata, simmap, simulator);
}; showstats(simdata);
if (0 != uv_poll_start(poll, UV_READABLE, cb)) t++;
{ if(simdata->rpms<250)
return 2; {
}; simdata->rpms=250;
}
for (int x = 0; x < numdevices; x++)
{
if (devices[x]->type == SIMDEV_SERIAL)
{
if(t>=update_rate)
{
devupdate(devices[x], simdata);
}
}
else
{
devupdate(devices[x], simdata);
}
}
uv_timer_init(uv_default_loop(), &datamaptimer); if(t>=update_rate)
{
uv_run(uv_default_loop(), UV_RUN_DEFAULT); t=0;
}
if( poll(&mypoll, 1, 1000.0/update_rate) )
{
scanf("%c", &ch);
if(ch == 'q')
{
go = false;
}
}
}
fprintf(stdout, "\n"); fprintf(stdout, "\n");
fflush(stdout); fflush(stdout);
tcsetattr(0, TCSANOW, &canonicalmode); tcsetattr(0, TCSANOW, &canonicalmode);
free(baton);
free(simdata);
freesimmap(simmap, false);
return 0;
}
int tester(SimDevice* devices, int numdevices)
{
slogi("preparing test with %i devices...", numdevices);
SimData* simdata = malloc(sizeof(SimData));
struct termios newsettings, canonicalmode;
tcgetattr(0, &canonicalmode);
newsettings = canonicalmode;
newsettings.c_lflag &= (~ICANON & ~ECHO);
newsettings.c_cc[VMIN] = 1;
newsettings.c_cc[VTIME] = 0;
tcsetattr(0, TCSANOW, &newsettings);
fprintf(stdout, "\n");
simdata->car[0] = 'C';
simdata->car[1] = 'A';
simdata->car[2] = 'R';
simdata->car[3] = '\0';
simdata->gear = MONOCOQUE_GEAR_NEUTRAL;
simdata->velocity = 16;
simdata->rpms = 100;
simdata->maxrpm = 8000;
simdata->abs = 0;
simdata->tyrediameter[0] = -1;
simdata->tyrediameter[1] = -1;
simdata->tyrediameter[2] = -1;
simdata->tyrediameter[3] = -1;
simdata->Xvelocity = 0;
simdata->Yvelocity = 100;
simdata->Zvelocity = 0;
sleep(3);
fprintf(stdout, "Setting rpms to 1000\n");
simdata->rpms = 1000;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
sleep(3);
fprintf(stdout, "Shifting into first gear\n");
simdata->gear = 2;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
sleep(3);
fprintf(stdout, "Setting speed to 100\n");
simdata->velocity = 100;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
sleep(3);
fprintf(stdout, "testing wheel spin\n");
simdata->velocity = 15;
simdata->tyreRPS[0] = 50;
simdata->tyreRPS[1] = 50;
simdata->tyreRPS[2] = 50;
simdata->tyreRPS[3] = 50;
simdata->tyrediameter[0] = 0.638636385206394;
simdata->tyrediameter[1] = 0.633384434597093;
simdata->tyrediameter[2] = 0.710475735564615;
simdata->tyrediameter[3] = 0.710475735564615;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
sleep(3);
fprintf(stdout, "Testing wheel Lock\n");
simdata->tyreRPS[0] = 25;
simdata->tyreRPS[1] = 25;
simdata->tyreRPS[2] = 25;
simdata->tyreRPS[3] = 25;
simdata->velocity = 150;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
sleep(3);
fprintf(stdout, "Shifting into second gear\n");
simdata->tyreRPS[0] = 0;
simdata->tyreRPS[1] = 0;
simdata->tyreRPS[2] = 0;
simdata->tyreRPS[3] = 0;
simdata->tyrediameter[0] = -1;
simdata->tyrediameter[1] = -1;
simdata->tyrediameter[2] = -1;
simdata->tyrediameter[3] = -1;
simdata->abs = 0;
simdata->gear = 3;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
sleep(3);
fprintf(stdout, "Testing abs brake lock Lock\n");
simdata->tyreRPS[0] = 50;
simdata->tyreRPS[1] = 50;
simdata->tyreRPS[2] = 50;
simdata->tyreRPS[3] = 50;
simdata->tyrediameter[0] = 0.638636385206394;
simdata->tyrediameter[1] = 0.633384434597093;
simdata->tyrediameter[2] = 0.710475735564615;
simdata->tyrediameter[3] = 0.710475735564615;
simdata->abs = .11;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
sleep(3);
fprintf(stdout, "Setting speed to 200\n");
simdata->tyreRPS[0] = 0;
simdata->tyreRPS[1] = 0;
simdata->tyreRPS[2] = 0;
simdata->tyreRPS[3] = 0;
simdata->tyrediameter[0] = -1;
simdata->tyrediameter[1] = -1;
simdata->tyrediameter[2] = -1;
simdata->tyrediameter[3] = -1;
simdata->abs = 0;
simdata->velocity = 200;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
sleep(3);
fprintf(stdout, "Shifting into third gear\n");
simdata->gear = 4;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
sleep(3);
fprintf(stdout, "Setting rpms to 2000\n");
simdata->rpms = 2000;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
sleep(3);
fprintf(stdout, "Setting rpms to 4000\n");
simdata->rpms = 4000;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
sleep(3);
fprintf(stdout, "Shifting into fourth gear\n");
simdata->gear = 5;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
sleep(3);
fprintf(stdout, "Setting speed to 300\n");
simdata->velocity = 300;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
sleep(3);
fprintf(stdout, "Setting rpms to 7000\n");
simdata->rpms = 7000;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
sleep(3);
fprintf(stdout, "Setting rpms to 8000\n");
simdata->rpms = 8000;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
sleep(3);
simdata->velocity = 0;
simdata->rpms = 100;
simdata->gear = MONOCOQUE_GEAR_NEUTRAL;
for (int x = 0; x < numdevices; x++)
{
if (devices[x].initialized == true)
{
devices[x].update(&devices[x], simdata);
}
}
sleep(1);
fflush(stdout);
tcsetattr(0, TCSANOW, &canonicalmode);
free(simdata); free(simdata);
free(simmap);
return 0; return 0;
} }
+1 -4
View File
@@ -1,7 +1,4 @@
#include "../devices/simdevice.h" #include "../devices/simdevice.h"
#include "../helper/parameters.h" #include "../helper/parameters.h"
int tester(SimDevice* devices, int numdevices); int looper (SimDevice* devices[], int numdevices, Simulator simulator);
int looper(SimDevice* devices, int numdevices, Parameters* p);
int monocoque_mainloop(MonocoqueSettings* ms);
-38
View File
@@ -1,38 +0,0 @@
#ifndef _LOOPDATA_H
#define _LOOPDATA_H
#include <uv.h>
#include "../helper/parameters.h"
#include "../helper/confighelper.h"
#include "../devices/simdevice.h"
#include "../simulatorapi/simapi/simapi/simdata.h"
#include "../simulatorapi/simapi/simapi/simmapper.h"
typedef struct device_loop_data
{
uv_work_t req;
SimData* simdata;
SimDevice* simdevice;
} device_loop_data;
typedef struct loop_data
{
uv_work_t req;
SimulatorAPI sim;
SimulatorAPI map;
bool use_udp;
bool simstate;
bool uion;
bool releasing;
int numdevices;
MonocoqueSettings* ms;
SimData* simdata;
SimMap* simmap;
SimDevice* simdevices;
uv_timer_t* device_timers;
device_loop_data* device_batons;
} loop_data;
#endif
+2 -2
View File
@@ -15,7 +15,7 @@
#include <libxml/tree.h> #include <libxml/tree.h>
#include "../devices/simdevice.h" #include "../devices/simdevice.h"
#include "../simulatorapi/simapi/simapi/simdata.h" #include "../simulatorapi/simdata.h"
#include "../slog/slog.h" #include "../slog/slog.h"
#define DEFAULT_UPDATE_RATE 30.0 #define DEFAULT_UPDATE_RATE 30.0
@@ -183,7 +183,7 @@ int config_tachometer(int max_revs, int granularity, const char* save_file, SimD
WriteXmlFromArrays(nodes, rpm_array, values_array, max_revs, save_file); WriteXmlFromArrays(nodes, rpm_array, values_array, max_revs, save_file);
sleep(2); sleep(2);
simdata->pulses = 0; simdata->pulses = 0;
simdevice->update(simdevice, simdata); devupdate(simdevice, simdata);
fflush(stdout); fflush(stdout);
return 0; return 0;
+1 -1
View File
@@ -2,7 +2,7 @@
#define _TACHCONFIG_H #define _TACHCONFIG_H
#include "../devices/simdevice.h" #include "../devices/simdevice.h"
#include "../simulatorapi/simapi/simapi/simdata.h" #include "../simulatorapi/simdata.h"
int config_tachometer(int max_revs, int granularity, const char* save_file, SimDevice* simdevice, SimData* simdata); int config_tachometer(int max_revs, int granularity, const char* save_file, SimDevice* simdevice, SimData* simdata);
+59 -701
View File
@@ -1,9 +1,7 @@
#include <dirent.h>
#include <stdio.h> #include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include <ctype.h>
#include <libxml/parser.h> #include <libxml/parser.h>
#include <libxml/xmlreader.h> #include <libxml/xmlreader.h>
@@ -11,192 +9,51 @@
#include "confighelper.h" #include "confighelper.h"
#include "../slog/slog.h" #include "../slog/slog.h"
#include "parameters.h"
int strtogame(const char* game, MonocoqueSettings* ms)
#include "../simulatorapi/simapi/simapi/simmapper.h"
#include <pulse/pulseaudio.h>
int strcicmp(char const *a, char const *b)
{ {
for (;; a++, b++) { slogd("Checking for %s in list of supported simulators.", game);
int d = tolower((unsigned char)*a) - tolower((unsigned char)*b); if (strcmp(game, "ac") == 0)
if (d != 0 || !*a)
return d;
}
}
int strtoeffecttype(const char* effect, DeviceSettings* ds)
{
ds->is_valid = false;
if (strcicmp(effect, "Engine") == 0)
{ {
ds->is_valid = true; slogd("Setting simulator to Assetto Corsa");
ds->effect_type = EFFECT_ENGINERPM; ms->sim_name = SIMULATOR_ASSETTO_CORSA;
} }
if (strcicmp(effect, "Gear") == 0) else if (strcmp(game, "rf2") == 0)
{ {
ds->is_valid = true; slogd("Setting simulator to RFactor 2");
ds->effect_type = EFFECT_GEARSHIFT; ms->sim_name = SIMULATOR_RFACTOR2;
}
if (strcicmp(effect, "ABS") == 0)
{
ds->is_valid = true;
slogt("found abas effect set");
ds->effect_type = EFFECT_ABSBRAKES;
}
if ((strcicmp(effect, "SLIP") == 0) || (strcicmp(effect, "TYRESLIP") == 0) || (strcicmp(effect, "TIRESLIP") == 0))
{
ds->is_valid = true;
slogt("found tyreslip effect set");
ds->effect_type = EFFECT_TYRESLIP;
}
if ((strcicmp(effect, "LOCK") == 0) || (strcicmp(effect, "TYRELOCK") == 0) || (strcicmp(effect, "TIRELOCK") == 0))
{
ds->is_valid = true;
slogt("found tyreslock effect set");
ds->effect_type = EFFECT_TYRELOCK;
}
if (ds->is_valid == false)
{
slogw("effect %s is not a valid effect", effect);
}
ds->is_valid = true;
return MONOCOQUE_ERROR_NONE;
}
int strtodevsubsubtype(const char* device_subsubtype, DeviceSettings* ds)
{
ds->dev_subsubtype = SIMDEVSUBTYPE_UNKNOWN;
bool devfound = false;
if (strcicmp(device_subsubtype, "CammusC5") == 0)
{
ds->dev_subsubtype = SIMDEVSUBTYPE_CAMMUSC5;
bool devfound = true;
}
if (strcicmp(device_subsubtype, "CammusC12") == 0)
{
ds->dev_subsubtype = SIMDEVSUBTYPE_CAMMUSC12;
bool devfound = true;
}
if (strcicmp(device_subsubtype, "MozaR5") == 0)
{
ds->dev_subsubtype = SIMDEVSUBTYPE_MOZAR5;
bool devfound = true;
}
if (strcicmp(device_subsubtype, "MozaR8") == 0)
{
ds->dev_subsubtype = SIMDEVSUBTYPE_MOZAR5;
bool devfound = true;
}
if (strcicmp(device_subsubtype, "CSLELITEV3PEDALS") == 0)
{
ds->dev_subsubtype = SIMDEVSUBTYPE_CSLELITEV3PEDALS;
bool devfound = true;
}
if (strcicmp(device_subsubtype, "SIMAGICP1000PEDALS") == 0)
{
ds->dev_subsubtype = SIMDEVSUBTYPE_SIMAGICP1000PEDALS;
bool devfound = true;
}
if(devfound == false)
{
slogw("%s does not appear to be a valid device sub sub type, but attempting to continue with other devices", device_subsubtype);
return MONOCOQUE_ERROR_INVALID_DEV;
}
return MONOCOQUE_ERROR_NONE;
}
int strtodevsubtype(const char* device_subtype, DeviceSettings* ds, int simdev)
{
ds->is_valid = false;
ds->dev_subtype = SIMDEVTYPE_UNKNOWN;
switch (simdev) {
case SIMDEV_USB:
if (strcicmp(device_subtype, "Tachometer") == 0)
{
ds->dev_subtype = SIMDEVTYPE_TACHOMETER;
break;
}
if (strcicmp(device_subtype, "Wheel") == 0)
{
ds->dev_subtype = SIMDEVTYPE_USBWHEEL;
break;
}
if (strcicmp(device_subtype, "UsbHaptic") == 0 || strcicmp(device_subtype, "Haptic") == 0)
{
ds->dev_subtype = SIMDEVTYPE_USBHAPTIC;
break;
}
case SIMDEV_SERIAL:
if (strcicmp(device_subtype, "ShiftLights") == 0)
{
ds->dev_subtype = SIMDEVTYPE_SHIFTLIGHTS;
break;
}
if (strcicmp(device_subtype, "Simleds") == 0)
{
ds->dev_subtype = SIMDEVTYPE_SIMLED;
break;
}
if (strcicmp(device_subtype, "SimWind") == 0)
{
ds->dev_subtype = SIMDEVTYPE_SIMWIND;
break;
}
if (strcicmp(device_subtype, "SerialHaptic") == 0 || strcicmp(device_subtype, "Haptic") == 0)
{
slogt("found serial haptic device settings");
ds->dev_subtype = SIMDEVTYPE_SERIALHAPTIC;
break;
}
if (strcicmp(device_subtype, "Wheel") == 0)
{
ds->dev_subtype = SIMDEVTYPE_SERIALWHEEL;
break;
}
case SIMDEV_SOUND:
ds->is_valid = true;
break;
default:
ds->is_valid = false;
slogw("%s does not appear to be a valid device sub type, but attempting to continue with other devices", device_subtype);
return MONOCOQUE_ERROR_INVALID_DEV;
}
ds->is_valid = true;
return MONOCOQUE_ERROR_NONE;
}
int strtodev(const char* device_type, const char* device_subtype, DeviceSettings* ds)
{
ds->is_valid = false;
if (strcicmp(device_type, "USB") == 0)
{
ds->dev_type = SIMDEV_USB;
strtodevsubtype(device_subtype, ds, SIMDEV_USB);
} }
else else
if (strcicmp(device_type, "Sound") == 0) if (strcmp(game, "test") == 0)
{ {
ds->dev_type = SIMDEV_SOUND; slogd("Setting simulator to Test Data");
strtodevsubtype(device_subtype, ds, SIMDEV_SOUND); ms->sim_name = SIMULATOR_MONOCOQUE_TEST;
} }
else else
if (strcicmp(device_type, "Serial") == 0) {
slogi("%s does not appear to be a supported simulator.", game);
return MONOCOQUE_ERROR_INVALID_SIM;
}
return MONOCOQUE_ERROR_NONE;
}
int strtodev(const char* device_type, DeviceSettings* ds)
{
ds->is_valid = false;
if (strcmp(device_type, "USB") == 0)
{
ds->dev_type = SIMDEV_USB;
}
else
if (strcmp(device_type, "Sound") == 0)
{
ds->dev_type = SIMDEV_SOUND;
}
else
if (strcmp(device_type, "Serial") == 0)
{ {
ds->dev_type = SIMDEV_SERIAL; ds->dev_type = SIMDEV_SERIAL;
strtodevsubtype(device_subtype, ds, SIMDEV_SERIAL);
} }
else else
{ {
@@ -208,233 +65,33 @@ int strtodev(const char* device_type, const char* device_subtype, DeviceSettings
return MONOCOQUE_ERROR_NONE; return MONOCOQUE_ERROR_NONE;
} }
int getsimfromconfig(config_setting_t* c) int strtodevtype(const char* device_subtype, DeviceSettings* ds)
{ {
int sim = 0; ds->is_valid = false;
const char* simstr = NULL; if (strcmp(device_subtype, "Tachometer") == 0)
int found = config_setting_lookup_string(c, "sim", &simstr);
if(found == 0)
{ {
int found = config_setting_lookup_int(c, "sim", &sim); ds->dev_subtype = SIMDEVTYPE_TACHOMETER;
} }
else else
{ if (strcmp(device_subtype, "ShiftLights") == 0)
sim = simapi_strtogame(simstr);
}
return sim;
}
int getNumberOfConfigs(const char* config_file_str)
{
config_t cfg;
config_init(&cfg);
if (!config_read_file(&cfg, config_file_str))
{
fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
return -1;
}
config_setting_t* config = NULL;
config_setting_t* config_widgets = NULL;
config = config_lookup(&cfg, "configs");
int configs = config_setting_length(config);
return configs;
}
int getconfigtouse2(const char* config_file_str, char* car, int sim)
{
config_t cfg;
config_init(&cfg);
if (!config_read_file(&cfg, config_file_str))
{
fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
return -1;
}
config_setting_t* config = NULL;
config_setting_t* config_widgets = NULL;
config = config_lookup(&cfg, "configs");
int configs = config_setting_length(config);
const char* temp;
config_setting_t* config_config = NULL;
int j = 0;
if ( configs == 1 )
{
return -1;
}
int confignum = -1;
slogt("Multiple configs found");
for (j = 0; j < configs; j++)
{
config_config = config_setting_get_elem(config, j);
int found = 0;
int csim = 0;
slogt("sim is %i", sim);
csim = getsimfromconfig(config_config);
if (csim != sim)
{ {
slogt("rejected config %i", j); ds->dev_subtype = SIMDEVTYPE_SHIFTLIGHTS;
continue;
}
slogt("checking if car is matched %i", j);
temp = NULL;
found = config_setting_lookup_string(config_config, "car", &temp);
slogt("config car is %s found is %i", temp, found);
if(temp != NULL && found > 0 && car > 0 && car != NULL)
{
slogt("checking against sim car of %s", car);
if(strcicmp(temp, car) == 0)
{
confignum = j;
}
}
if(confignum>=0)
{
break;
}
}
return confignum;
}
int getconfigtouse1(const char* config_file_str, char* car, int sim)
{
config_t cfg;
config_init(&cfg);
if (!config_read_file(&cfg, config_file_str))
{
fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
return -1;
}
config_setting_t* config = NULL;
config_setting_t* config_widgets = NULL;
config = config_lookup(&cfg, "configs");
int configs = config_setting_length(config);
const char* temp;
config_setting_t* config_config = NULL;
int j = 0;
if ( configs == 1 )
{
return -1;
}
int confignum = -1;
slogt("Multiple configs found");
for (j = 0; j < configs; j++)
{
config_config = config_setting_get_elem(config, j);
int found = 0;
int csim = 0;
slogt("sim is %i", sim);
csim = getsimfromconfig(config_config);
if (csim != sim)
{
slogt("rejected config %i", j);
continue;
}
slogt("checking if car is matched %i", j);
temp = NULL;
found = config_setting_lookup_string(config_config, "car", &temp);
slogt("config car is %s found is %i", temp, found);
if(temp != NULL && found > 0 && car > 0 && car != NULL)
{
slogt("checking against sim car of %s", car);
if(strcicmp(temp, car) == 0)
{
confignum = j;
}
if(strcicmp("default", temp) == 0)
{
slogt("matched default car");
confignum = j;
}
} }
else else
{ if (strcmp(device_subtype, "Shaker") == 0)
slogt("assuming default car");
confignum = j;
}
slogt("bomb");
if(confignum>=0)
{
break;
}
}
return confignum;
}
int getconfigtouse(const char* config_file_str, char* car, int sim)
{
config_t cfg;
config_init(&cfg);
if (!config_read_file(&cfg, config_file_str))
{
fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
return -1;
}
config_setting_t* config = NULL;
config_setting_t* config_widgets = NULL;
config = config_lookup(&cfg, "configs");
int configs = config_setting_length(config);
const char* temp;
config_setting_t* config_config = NULL;
int j = 0;
if ( configs == 1 )
{
return 0;
}
int confignum = 0;
slogt("Multiple configs found");
for (j = 0; j < configs; j++)
{
config_config = config_setting_get_elem(config, j);
int found = 0;
int csim = 0;
slogt("sim is %i", sim);
csim = getsimfromconfig(config_config);
if (csim != sim && csim != 0)
{
slogt("rejected config %i", j);
continue;
}
slogt("checking if car is matched %i", j);
temp = NULL;
found = config_setting_lookup_string(config_config, "car", &temp);
slogt("config car is %s found is %i", temp, found);
if(temp != NULL && found > 0 && car > 0 && car != NULL)
{
slogt("checking against sim car of %s", car);
if(strcicmp(temp, car) == 0)
{ {
confignum = j; ds->dev_subtype = SIMDEVTYPE_SHAKER;
} }
if(strcicmp("default", temp) == 0) else
{ {
slogt("matched default car"); ds->is_valid = false;
confignum = j; slogi("%s does not appear to be a valid device sub type, but attempting to continue with other devices", device_subtype);
return MONOCOQUE_ERROR_INVALID_DEV;
} }
} ds->is_valid = true;
else return MONOCOQUE_ERROR_NONE;
{
slogt("assuming default car");
confignum = j;
}
slogt("bomb");
if(confignum<configs-1)
{
break;
}
}
return confignum;
} }
int loadtachconfig(const char* config_file, DeviceSettings* ds) int loadtachconfig(const char* config_file, DeviceSettings* ds)
{ {
@@ -474,7 +131,7 @@ int loadtachconfig(const char* config_file, DeviceSettings* ds)
{ {
slogt("Xml Element name %s", cursubsubnode->name); slogt("Xml Element name %s", cursubsubnode->name);
} }
if (strcicmp(cursubsubnode->name, "SettingsItem") == 0) if (strcmp(cursubsubnode->name, "SettingsItem") == 0)
{ {
arraysize++; arraysize++;
} }
@@ -496,13 +153,13 @@ int loadtachconfig(const char* config_file, DeviceSettings* ds)
{ {
for (cursubsubsubnode = cursubsubnode->children; cursubsubsubnode; cursubsubsubnode = cursubsubsubnode->next) for (cursubsubsubnode = cursubsubnode->children; cursubsubsubnode; cursubsubsubnode = cursubsubsubnode->next)
{ {
if (strcicmp(cursubsubsubnode->name, "Value") == 0) if (strcmp(cursubsubsubnode->name, "Value") == 0)
{ {
xmlChar* a = xmlNodeGetContent(cursubsubsubnode); xmlChar* a = xmlNodeGetContent(cursubsubsubnode);
rpms_array[i] = strtol((char*) a, &buf, 10); rpms_array[i] = strtol((char*) a, &buf, 10);
xmlFree(a); xmlFree(a);
} }
if (strcicmp(cursubsubsubnode->name, "TimeValue") == 0) if (strcmp(cursubsubsubnode->name, "TimeValue") == 0)
{ {
xmlChar* a = xmlNodeGetContent(cursubsubsubnode); xmlChar* a = xmlNodeGetContent(cursubsubsubnode);
pulses_array[i] = strtol((char*) a, &buf, 10); pulses_array[i] = strtol((char*) a, &buf, 10);
@@ -528,40 +185,6 @@ int loadtachconfig(const char* config_file, DeviceSettings* ds)
return 0; return 0;
} }
int gettyre(config_setting_t* device_settings, DeviceSettings* ds) {
const char* temp;
int found = config_setting_lookup_string(device_settings, "tyre", &temp);
ds->tyre = ALLFOUR;
if (strcicmp(temp, "FRONTS") == 0)
{
ds->tyre = FRONTS;
}
if (strcicmp(temp, "REARS") == 0)
{
ds->tyre = REARS;
}
if (strcicmp(temp, "FRONTLEFT") == 0)
{
ds->tyre = FRONTLEFT;
}
if (strcicmp(temp, "FRONTRIGHT") == 0)
{
ds->tyre = FRONTRIGHT;
}
if (strcicmp(temp, "REARLEFT") == 0)
{
ds->tyre = REARLEFT;
}
if (strcicmp(temp, "REARRIGHT") == 0)
{
ds->tyre = REARRIGHT;
}
}
int loadconfig(const char* config_file, DeviceSettings* ds) int loadconfig(const char* config_file, DeviceSettings* ds)
{ {
if (ds->dev_subtype == SIMDEVTYPE_TACHOMETER) if (ds->dev_subtype == SIMDEVTYPE_TACHOMETER)
@@ -571,42 +194,23 @@ int loadconfig(const char* config_file, DeviceSettings* ds)
return 0; return 0;
} }
int configcheck(const char* config_file_str, int confignum, int* devices)
{
slogt("ui config check");
config_t cfg;
config_init(&cfg);
if (!config_read_file(&cfg, config_file_str))
{
fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
}
config_setting_t* config = NULL;
config = config_lookup(&cfg, "configs");
config_setting_t* selectedconfig = config_setting_get_elem(config, confignum);
slogt("selected num %i", confignum);
config_setting_t* config_devices = NULL;
config_devices = config_setting_lookup(selectedconfig, "devices");
*devices = config_setting_length(config_devices);
config_destroy(&cfg);
return 0;
//return cfg;
}
int devsetup(const char* device_type, const char* device_subtype, const char* config_file, MonocoqueSettings* ms, DeviceSettings* ds, config_setting_t* device_settings) int devsetup(const char* device_type, const char* device_subtype, const char* config_file, MonocoqueSettings* ms, DeviceSettings* ds, config_setting_t* device_settings)
{ {
int error = MONOCOQUE_ERROR_NONE; int error = MONOCOQUE_ERROR_NONE;
//slogt("Called device setup with %s %s %s", device_type, device_subtype, config_file); slogi("Called device setup with %s %s %s", device_type, device_subtype, config_file);
ds->dev_type = SIMDEV_UNKNOWN; ds->dev_type = SIMDEV_UNKNOWN;
ds->dev_subtype = SIMDEVTYPE_UNKNOWN;
error = strtodev(device_type, device_subtype, ds); error = strtodev(device_type, ds);
if (error != MONOCOQUE_ERROR_NONE) if (error != MONOCOQUE_ERROR_NONE)
{ {
return error; return error;
} }
error = strtodevtype(device_subtype, ds);
if (ms->program_action == A_PLAY || ms->program_action == A_TEST) if (error != MONOCOQUE_ERROR_NONE)
{
return error;
}
if (ms->program_action == A_PLAY)
{ {
error = loadconfig(config_file, ds); error = loadconfig(config_file, ds);
} }
@@ -615,10 +219,6 @@ int devsetup(const char* device_type, const char* device_subtype, const char* co
return error; return error;
} }
ds->fps = 60;
config_setting_lookup_int(device_settings, "fps", &ds->fps);
if (ds->dev_subtype == SIMDEVTYPE_TACHOMETER) if (ds->dev_subtype == SIMDEVTYPE_TACHOMETER)
{ {
if (device_settings != NULL) if (device_settings != NULL)
@@ -632,253 +232,11 @@ int devsetup(const char* device_type, const char* device_subtype, const char* co
slogi("Tachometer granularity set to %i", ds->tachsettings.granularity); slogi("Tachometer granularity set to %i", ds->tachsettings.granularity);
} }
ds->tachsettings.use_pulses = true; ds->tachsettings.use_pulses = true;
if (ms->program_action == A_PLAY || ms->program_action == A_TEST) if (ms->program_action == A_PLAY)
{ {
ds->tachsettings.use_pulses = false; ds->tachsettings.use_pulses = false;
} }
} }
if (ds->dev_subtype == SIMDEVTYPE_USBHAPTIC || ds->dev_subtype == SIMDEVTYPE_USBWHEEL)
{
// logic for different devices
int b = 0;
const char* temp;
int found = config_setting_lookup_string(device_settings, "subtype", &temp);
if(temp != NULL && found > 0)
{
b = strtodevsubsubtype(temp, ds);
}
}
if (ds->dev_subtype == SIMDEVTYPE_USBHAPTIC || ds->dev_type == SIMDEV_SOUND || ds->dev_subtype == SIMDEVTYPE_SERIALHAPTIC)
{
slogt("analysing haptic effect settings");
const char* effect;
config_setting_lookup_string(device_settings, "effect", &effect);
strtoeffecttype(effect, ds);
if (ds->effect_type == EFFECT_TYRESLIP || ds->effect_type == EFFECT_TYRELOCK || ds->effect_type == EFFECT_ABSBRAKES)
{
gettyre(device_settings, ds);
ds->threshold = 0;
int found = config_setting_lookup_float(device_settings, "threshold", &ds->threshold);
}
if (ds->dev_type == SIMDEV_SOUND)
{
slogi("reading configured sound device settings");
ds->sounddevsettings.frequency = 0;
ds->sounddevsettings.frequencyMax = 0;
ds->sounddevsettings.volume = 0;
ds->sounddevsettings.pan = 0;
ds->sounddevsettings.channels = 1;
ds->sounddevsettings.duration = 2.0;
if (ds->effect_type == EFFECT_GEARSHIFT)
{
ds->sounddevsettings.duration = .125;
}
if (device_settings != NULL)
{
config_setting_lookup_int(device_settings, "volume", &ds->sounddevsettings.volume);
config_setting_lookup_int(device_settings, "frequency", &ds->sounddevsettings.frequency);
config_setting_lookup_int(device_settings, "frequencyMax", &ds->sounddevsettings.frequencyMax);
config_setting_lookup_int(device_settings, "pan", &ds->sounddevsettings.pan);
config_setting_lookup_int(device_settings, "channels", &ds->sounddevsettings.channels);
config_setting_lookup_float(device_settings, "duration", &ds->sounddevsettings.duration);
const char* temp;
int found = 0;
found = config_setting_lookup_string(device_settings, "devid", &temp);
if (found == 0)
{
ds->sounddevsettings.dev = NULL;
}
else
{
ds->sounddevsettings.dev = strdup(temp);
}
found = config_setting_lookup_string(device_settings, "modulation", &temp);
ds->sounddevsettings.modulation = SOUND_EFFECT_MODULATION_NONE;
if (found == 0)
{
ds->sounddevsettings.modulation = SOUND_EFFECT_MODULATION_NONE;
slogd("Effect modulation not found, set to none");
}
else
{
if(strcicmp(temp, "FREQUENCY"))
{
ds->sounddevsettings.modulation = SOUND_EFFECT_MODULATION_FREQUENCY;
if(ds->sounddevsettings.frequencyMax == 0 || ds->sounddevsettings.frequencyMax < ds->sounddevsettings.frequency)
{
ds->sounddevsettings.modulation = SOUND_EFFECT_MODULATION_NONE;
slogw("Falling back to no frequency modulation since frequencyMax is either not set or set below target frequency");
}
else
{
slogi("Effect modulation found, set to FREQUENCY");
}
}
else if(strcicmp(temp, "AMPLIFY"))
{
ds->sounddevsettings.modulation = SOUND_EFFECT_MODULATION_AMPLIFY;
slogi("Effect modulation found, set to AMPLIFY");
}
else
{
slogw("%s is not a valid modulation type, falling back to no effect modulation");
ds->sounddevsettings.modulation = SOUND_EFFECT_MODULATION_NONE;
}
}
}
}
}
if (ds->dev_type == SIMDEV_SERIAL)
{
if (device_settings != NULL)
{
const char* temp;
config_setting_lookup_string(device_settings, "devpath", &temp);
ds->serialdevsettings.portdev = strdup(temp);
int motorposition = 8;
config_setting_lookup_int(device_settings, "motors", &motorposition);
ds->serialdevsettings.motorsposition = motorposition;
int numlights = 6;
config_setting_lookup_int(device_settings, "numlights", &numlights);
ds->serialdevsettings.numlights = numlights;
int numleds = 6;
config_setting_lookup_int(device_settings, "numleds", &numleds);
ds->serialdevsettings.numleds = numleds;
int startled = 1;
config_setting_lookup_int(device_settings, "startled", &startled);
ds->serialdevsettings.startled = startled;
int endled = 1;
config_setting_lookup_int(device_settings, "endled", &endled);
ds->serialdevsettings.endled = endled;
int baud = 9600;
config_setting_lookup_int(device_settings, "baud", &baud);
ds->serialdevsettings.baud = baud;
double ampfactor = 1.0;
ds->serialdevsettings.ampfactor = 1.0;
int found = config_setting_lookup_float(device_settings, "ampfactor", &ampfactor);
ds->serialdevsettings.ampfactor = ampfactor;
slogt("set port baud rate to %i, ampfactor %f", baud, ampfactor);
}
}
return error; return error;
} }
int uiloadconfig(const char* config_file_str, int confignum, int configureddevices, MonocoqueSettings* ms, DeviceSettings* ds)
{
int numdevices = 0;
config_t cfg;
config_init(&cfg);
if (!config_read_file(&cfg, config_file_str))
{
fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
}
else
{
slogi("Parsing config file");
config_setting_t* config = NULL;
config = config_lookup(&cfg, "configs");
config_setting_t* selectedconfig = config_setting_get_elem(config, confignum);
config_setting_t* config_devices = NULL;
config_devices = config_setting_lookup(selectedconfig, "devices");
int i = 0;
int error = MONOCOQUE_ERROR_NONE;
while (i<configureddevices)
{
error = MONOCOQUE_ERROR_NONE;
DeviceSettings settings;
config_setting_t* config_device = config_setting_get_elem(config_devices, i);
const char* device_type;
const char* device_subtype;
const char* device_config_file;
config_setting_lookup_string(config_device, "device", &device_type);
config_setting_lookup_string(config_device, "type", &device_subtype);
config_setting_lookup_string(config_device, "config", &device_config_file);
//slogt("device type: %s", device_type);
//slogt("device sub type: %s", device_subtype);
//slogt("device config file: %s", device_config_file);
if (error == MONOCOQUE_ERROR_NONE)
{
error = devsetup(device_type, device_subtype, device_config_file, ms, &settings, config_device);
}
if (error == MONOCOQUE_ERROR_NONE)
{
numdevices++;
}
ds[i] = settings;
i++;
}
}
config_destroy(&cfg);
return numdevices;
}
int settingsfree(DeviceSettings ds)
{
if (ds.dev_subtype == SIMDEVTYPE_SIMWIND || ds.dev_subtype == SIMDEVTYPE_SHIFTLIGHTS || ds.dev_subtype == SIMDEVTYPE_SIMLED)
{
if (ds.serialdevsettings.portdev != NULL)
{
free(ds.serialdevsettings.portdev);
}
}
if (ds.dev_type == SIMDEV_SOUND)
{
if (ds.sounddevsettings.dev != NULL)
{
free(ds.sounddevsettings.dev);
}
}
return 0;
}
int monocoquesettingsfree(MonocoqueSettings* ms)
{
if(ms->tyre_diameter_config != NULL)
{
free(ms->tyre_diameter_config);
}
if(ms->config_str != NULL)
{
free(ms->config_str);
}
if(ms->log_filename_str != NULL)
{
free(ms->log_filename_str);
}
if(ms->log_dirname_str != NULL)
{
free(ms->log_dirname_str);
}
}
+8 -148
View File
@@ -1,7 +1,6 @@
#ifndef _CONFIGHELPER_H #ifndef _CONFIGHELPER_H
#define _CONFIGHELPER_H #define _CONFIGHELPER_H
#include <pulse/channelmap.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
@@ -9,8 +8,6 @@
#include "parameters.h" #include "parameters.h"
#include "../devices/sounddevice.h"
typedef enum typedef enum
{ {
SIMDEV_UNKNOWN = 0, SIMDEV_UNKNOWN = 0,
@@ -24,27 +21,19 @@ typedef enum
{ {
SIMDEVTYPE_UNKNOWN = 0, SIMDEVTYPE_UNKNOWN = 0,
SIMDEVTYPE_TACHOMETER = 1, SIMDEVTYPE_TACHOMETER = 1,
SIMDEVTYPE_USBHAPTIC = 2, SIMDEVTYPE_SHAKER = 2,
SIMDEVTYPE_SHIFTLIGHTS = 3, SIMDEVTYPE_SHIFTLIGHTS = 3
SIMDEVTYPE_SIMWIND = 4,
SIMDEVTYPE_SERIALHAPTIC = 5,
SIMDEVTYPE_USBWHEEL = 6,
SIMDEVTYPE_SERIALWHEEL = 7,
SIMDEVTYPE_SIMLED = 8
} }
DeviceSubType; DeviceSubType;
typedef enum typedef enum
{ {
SIMDEVSUBTYPE_UNKNOWN = 0, SIMULATOR_MONOCOQUE_TEST = 0,
SIMDEVSUBTYPE_CAMMUSC5 = 1, SIMULATOR_ASSETTO_CORSA = 1,
SIMDEVSUBTYPE_CAMMUSC12 = 2, SIMULATOR_RFACTOR = 2,
SIMDEVSUBTYPE_MOZAR5 = 3, SIMULATOR_RFACTOR2 = 3
SIMDEVSUBTYPE_CSLELITEV3PEDALS = 4,
SIMDEVSUBTYPE_SIMAGICP1000PEDALS =5
} }
DeviceSubSubType; Simulator;
typedef enum typedef enum
{ {
@@ -57,51 +46,6 @@ typedef enum
} }
SimulatorUpdate; SimulatorUpdate;
typedef enum
{
EFFECT_ENGINERPM = 0,
EFFECT_GEARSHIFT = 1,
EFFECT_ABSBRAKES = 2,
EFFECT_TYRESLIP = 3,
EFFECT_TYRELOCK = 4
}
VibrationEffectType;
typedef enum
{
MOTOR_1 = 0,
MOTOR_2 = 1,
MOTOR_3 = 2,
MOTOR_4 = 3,
MOTOR_1_4 = 4,
MOTOR_2_4 = 5,
MOTOR_3_4 = 6,
MOTOR_1_2 = 7,
MOTOR_1_3 = 8,
MOTOR_2_3 = 9,
MOTOR_1_2_3_4 = 10,
MOTOR_1_2_3 = 11,
MOTOR_2_3_4 = 12,
MOTOR_1_2_4 = 13,
MOTOR_1_3_4 = 14
}
MotorPosition;
typedef enum
{
MONOCOQUE_GEAR_REVERSE = 0,
MONOCOQUE_GEAR_NEUTRAL = 1,
MONOCOQUE_GEAR_ONE = 2,
MONOCOQUE_GEAR_TWO = 3,
MONOCOQUE_GEAR_THREE = 4,
MONOCOQUE_GEAR_FOUR = 5,
MONOCOQUE_GEAR_FIVE = 6,
MONOCOQUE_GEAR_SIX = 7,
MONOCOQUE_GEAR_SEVEN = 8,
MONOCOQUE_GEAR_EIGHT = 9,
}
MonocoqueGear;
typedef enum typedef enum
{ {
MONOCOQUE_ERROR_NONE = 0, MONOCOQUE_ERROR_NONE = 0,
@@ -113,31 +57,10 @@ typedef enum
} }
MonocoqueError; MonocoqueError;
typedef enum
{
FRONTLEFT = 0,
FRONTRIGHT = 1,
REARLEFT = 2,
REARRIGHT = 3,
FRONTS = 4,
REARS = 5,
ALLFOUR = 6
}
MonocoqueTyreIdentifier;
typedef struct typedef struct
{ {
ProgramAction program_action; ProgramAction program_action;
SimulatorAPI sim_name; Simulator sim_name;
int configcheck;
int useconfig;
int verbosity_count;
int fps;
bool force_udp_mode;
char* tyre_diameter_config;
char* config_str;
char* log_filename_str;
char* log_dirname_str;
} }
MonocoqueSettings; MonocoqueSettings;
@@ -151,60 +74,12 @@ typedef struct
} }
TachometerSettings; TachometerSettings;
typedef struct
{
char* portdev;
MotorPosition motorsposition;
int numlights;
int numleds;
int startled;
int endled;
float ampfactor;
int baud;
}
SerialDeviceSettings;
typedef struct
{
uint32_t frequency;
uint32_t volume;
int lowbound_frequency;
int upperbound_frequency;
uint32_t frequencyMax;
int pan;
int channels;
double duration;
char* dev;
SoundEffectModulationType modulation;
}
SoundDeviceSettings;
typedef struct
{
int value0;
int value1;
char* dev;
}
USBDeviceSettings;
typedef struct typedef struct
{ {
bool is_valid; bool is_valid;
int fps;
DeviceType dev_type; DeviceType dev_type;
DeviceSubType dev_subtype; DeviceSubType dev_subtype;
DeviceSubSubType dev_subsubtype;
// to get really fancy move the effect information to it's own structure that would be a member of
// any device settings member structure that can carry an effect
VibrationEffectType effect_type;
MonocoqueTyreIdentifier tyre;
double threshold;
// union?
TachometerSettings tachsettings; TachometerSettings tachsettings;
SerialDeviceSettings serialdevsettings;
SoundDeviceSettings sounddevsettings;
USBDeviceSettings usbdevsettings;
} }
DeviceSettings; DeviceSettings;
@@ -212,19 +87,4 @@ int strtogame(const char* game, MonocoqueSettings* ms);
int devsetup(const char* device_type, const char* device_subtype, const char* config_files, MonocoqueSettings* ms, DeviceSettings* ds, config_setting_t* device_settings); int devsetup(const char* device_type, const char* device_subtype, const char* config_files, MonocoqueSettings* ms, DeviceSettings* ds, config_setting_t* device_settings);
int settingsfree(DeviceSettings ds);
int monocoquesettingsfree(MonocoqueSettings* ms);
int strcicmp(char const *a, char const *b);
int getconfigtouse2(const char* config_file_str, char* car, int sim);
int getconfigtouse1(const char* config_file_str, char* car, int sim);
int getconfigtouse(const char* config_file_str, char* car, int sim);
int configcheck(const char* config_file_str, int confignum, int* devices);
int uiloadconfig(const char* config_file_str, int confignum, int configureddevices, MonocoqueSettings* ms, DeviceSettings* ds);
int getNumberOfConfigs(const char* config_file_str);
#endif #endif
+19 -88
View File
@@ -13,36 +13,6 @@
#include <string.h> #include <string.h>
void create_dir(char* dir)
{
struct stat st = {0};
if (stat(dir, &st) == -1)
{
mkdir(dir, 0700);
}
}
void create_xdg_dir(const char* dir)
{
struct stat st = {0};
if (stat(dir, &st) == -1)
{
mkdir(dir, 0700);
}
}
char* create_user_dir(char* home_dir_str, const char* dirtype, const char* programname)
{
// +3 for slashes
size_t ss = (4 + strlen(home_dir_str) + strlen(dirtype) + strlen(programname));
char* config_dir_str = malloc(ss);
snprintf (config_dir_str, ss, "%s/%s/%s/", home_dir_str, dirtype, programname);
create_dir(config_dir_str);
return config_dir_str;
}
char* gethome() char* gethome()
{ {
char* homedir = getenv("HOME"); char* homedir = getenv("HOME");
@@ -205,67 +175,28 @@ void restrict_folders_to_cache(char* path, int cachesize)
} }
bool does_directory_exist(char* path) bool does_directory_exist(char* path, char* dirname)
{ {
DIR* dir = opendir(path); struct dirent* de;
if (dir) DIR* dr = opendir(path);
if (dr == NULL)
{ {
// Directory exists printf("Could not open current directory");
closedir(dir);
return true;
}
else
{
// Directory does not exist or cannot be opened
return false; return false;
} }
// Refer http://pubs.opengroup.org/onlinepubs/7990989775/xsh/readdir.html
bool answer = false;
while ((de = readdir(dr)) != NULL)
{
if (strcmp(dirname,de->d_name) == 0)
{
answer = true;
}
}
closedir(dr);
return answer;
} }
bool does_file_exist(const char* file)
{
if (file == NULL)
{
return false;
}
#if defined(OS_WIN)
#if defined(WIN_API)
// if you want the WinAPI, versus CRT
if (strnlen(file, MAX_PATH+1) > MAX_PATH)
{
// ... throw error here or ...
return false;
}
DWORD res = GetFileAttributesA(file);
return (res != INVALID_FILE_ATTRIBUTES &&
!(res& FILE_ATTRIBUTE_DIRECTORY));
#else
// Use Win CRT
struct stat fi;
if (_stat(file, &fi) == 0)
{
#if defined(S_ISSOCK)
// sockets come back as a 'file' on some systems
// so make sure it's not a socket or directory
// (in other words, make sure it's an actual file)
return !(S_ISDIR(fi.st_mode)) &&
!(S_ISSOCK(fi.st_mode));
#else
return !(S_ISDIR(fi.st_mode));
#endif
}
return false;
#endif
#else
struct stat fi;
if (stat(file, &fi) == 0)
{
#if defined(S_ISSOCK)
return !(S_ISDIR(fi.st_mode)) &&
!(S_ISSOCK(fi.st_mode));
#else
return !(S_ISDIR(fi.st_mode));
#endif
}
return false;
#endif
}
+1 -5
View File
@@ -3,14 +3,10 @@
#include <stdbool.h> #include <stdbool.h>
void create_dir(char* dir);
void create_xdg_dir(const char* dir);
char* create_user_dir(char* home_dir_str, const char* dirtype, const char* programpath);
char* gethome(); char* gethome();
char* str2md5(const char* str, int length); char* str2md5(const char* str, int length);
bool does_directory_exist(char* path); bool does_directory_exist(char* path, char* dirname);
void restrict_folders_to_cache(char* path, int cachesize); void restrict_folders_to_cache(char* path, int cachesize);
void delete_dir(char* path); void delete_dir(char* path);
bool does_file_exist(const char* file);
#endif #endif
+5 -86
View File
@@ -2,39 +2,12 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <libgen.h>
#include <libconfig.h> #include <libconfig.h>
#include <argtable2.h> #include <argtable2.h>
#include <regex.h> #include <regex.h>
int freeparams(Parameters* p)
{
if(p->config_dirpath != NULL)
{
free(p->config_dirpath);
}
if(p->config_filepath != NULL)
{
free(p->config_filepath);
}
if(p->log_filename_str != NULL)
{
free(p->log_filename_str);
}
if(p->log_fullfilename_str != NULL)
{
free(p->log_fullfilename_str);
}
if(p->log_dirname_str != NULL)
{
free(p->log_dirname_str);
}
return 0;
}
ConfigError getParameters(int argc, char** argv, Parameters* p) ConfigError getParameters(int argc, char** argv, Parameters* p)
{ {
@@ -44,31 +17,19 @@ ConfigError getParameters(int argc, char** argv, Parameters* p)
p->program_action = 0; p->program_action = 0;
p->max_revs = 0; p->max_revs = 0;
p->verbosity_count = 0; p->verbosity_count = 0;
p->fps = 60;
p->udp = false;
p->user_specified_config_file = false;
p->user_specified_log_file = false;
p->user_specified_config_dir = false;
// setup argument handling structures // setup argument handling structures
const char* progname = "monocoque"; const char* progname = "monocoque";
struct arg_lit* arg_verbosity1 = arg_litn("v","verbose", 0, 2, "increase logging verbosity"); struct arg_lit* arg_verbosity1 = arg_litn("v","verbose", 0, 2, "increase logging verbosity");
struct arg_lit* arg_verbosity2 = arg_litn("v","verbose", 0, 2, "increase logging verbosity"); struct arg_lit* arg_verbosity2 = arg_litn("v","verbose", 0, 2, "increase logging verbosity");
struct arg_lit* arg_verbosity3 = arg_litn("v","verbose", 0, 2, "increase logging verbosity");
struct arg_rex* cmd1 = arg_rex1(NULL, NULL, "play", NULL, REG_ICASE, NULL); struct arg_rex* cmd1 = arg_rex1(NULL, NULL, "play", NULL, REG_ICASE, NULL);
struct arg_lit* arg_udp = arg_lit0("d", "udp", "force udp mode for sims which support it"); struct arg_str* arg_sim = arg_strn("s", "sim", "<gamename>", 0, 1, NULL);
struct arg_file* arg_conf = arg_filen(NULL, "uiconf", "<config_file>", 0, 1, NULL);
struct arg_file* arg_log = arg_filen("l", "log", "<log_file>", 0, 1, NULL);
struct arg_str* arg_confdir = arg_strn(NULL, "configdir", "config_dir>", 0, 1, NULL);
struct arg_int* arg_fps = arg_int0("f", "fps", "fps", "main data refresh rate");
struct arg_lit* help = arg_litn(NULL,"help", 0, 1, "print this help and exit"); struct arg_lit* help = arg_litn(NULL,"help", 0, 1, "print this help and exit");
struct arg_lit* vers = arg_litn(NULL,"version", 0, 1, "print version information and exit"); struct arg_lit* vers = arg_litn(NULL,"version", 0, 1, "print version information and exit");
struct arg_end* end1 = arg_end(20); struct arg_end* end1 = arg_end(20);
void* argtable1[] = {cmd1,arg_log,arg_conf,arg_fps,arg_udp,arg_verbosity1,help,vers,end1}; void* argtable1[] = {cmd1,arg_sim,arg_verbosity1,help,vers,end1};
int nerrors1; int nerrors1;
struct arg_rex* cmd2a = arg_rex1(NULL, NULL, "config", NULL, REG_ICASE, NULL); struct arg_rex* cmd2a = arg_rex1(NULL, NULL, "config", NULL, REG_ICASE, NULL);
@@ -82,13 +43,6 @@ ConfigError getParameters(int argc, char** argv, Parameters* p)
void* argtable2[] = {cmd2a,cmd2b,arg_max_revs,arg_granularity,arg_save,arg_verbosity2,help2,vers2,end2}; void* argtable2[] = {cmd2a,cmd2b,arg_max_revs,arg_granularity,arg_save,arg_verbosity2,help2,vers2,end2};
int nerrors2; int nerrors2;
struct arg_rex* cmd3 = arg_rex1(NULL, NULL, "test", NULL, REG_ICASE, NULL);
struct arg_lit* help3 = arg_litn(NULL,"help", 0, 1, "print this help and exit");
struct arg_lit* vers3 = arg_litn(NULL,"version", 0, 1, "print version information and exit");
struct arg_end* end3 = arg_end(20);
void* argtable3[] = {cmd3,arg_verbosity3,help3,vers3,end3};
int nerrors3;
struct arg_lit* help0 = arg_lit0(NULL,"help", "print this help and exit"); struct arg_lit* help0 = arg_lit0(NULL,"help", "print this help and exit");
struct arg_lit* version0 = arg_lit0(NULL,"version", "print version information and exit"); struct arg_lit* version0 = arg_lit0(NULL,"version", "print version information and exit");
struct arg_end* end0 = arg_end(20); struct arg_end* end0 = arg_end(20);
@@ -116,37 +70,12 @@ ConfigError getParameters(int argc, char** argv, Parameters* p)
nerrors0 = arg_parse(argc,argv,argtable0); nerrors0 = arg_parse(argc,argv,argtable0);
nerrors1 = arg_parse(argc,argv,argtable1); nerrors1 = arg_parse(argc,argv,argtable1);
nerrors2 = arg_parse(argc,argv,argtable2); nerrors2 = arg_parse(argc,argv,argtable2);
nerrors3 = arg_parse(argc,argv,argtable3);
if (nerrors1==0) if (nerrors1==0)
{ {
p->program_action = A_PLAY; p->program_action = A_PLAY;
p->sim_string = arg_sim->sval[0];
p->verbosity_count = arg_verbosity1->count; p->verbosity_count = arg_verbosity1->count;
if(arg_conf->count > 0)
{
p->config_filepath = strdup(arg_conf->filename[0]);
p->user_specified_config_file = true;
}
if (arg_udp->count > 0)
{
p->udp = true;
}
if(arg_fps->count > 0)
{
p->fps = arg_fps->ival[0];
}
if(arg_log->count > 0)
{
char* filename = strdup(arg_log->filename[0]);
p->log_fullfilename_str = strdup(arg_log->filename[0]);
p->log_filename_str = strdup(arg_log->basename[0]);
char* dname;
dname = dirname(filename);
p->log_dirname_str = strdup(dname);
p->user_specified_log_file = true;
free(filename);
}
exitcode = E_SUCCESS_AND_DO; exitcode = E_SUCCESS_AND_DO;
} }
else else
@@ -163,12 +92,6 @@ ConfigError getParameters(int argc, char** argv, Parameters* p)
p->verbosity_count = arg_verbosity2->count; p->verbosity_count = arg_verbosity2->count;
exitcode = E_SUCCESS_AND_DO; exitcode = E_SUCCESS_AND_DO;
} }
else if (nerrors3==0)
{
p->program_action = A_TEST;
p->verbosity_count = arg_verbosity3->count;
exitcode = E_SUCCESS_AND_DO;
}
else else
{ {
if (cmd1->count > 0) if (cmd1->count > 0)
@@ -188,13 +111,12 @@ ConfigError getParameters(int argc, char** argv, Parameters* p)
{ {
if (help->count==0 && vers->count==0) if (help->count==0 && vers->count==0)
{ {
printf("%s: missing <play|config|test> command.\n",progname); printf("%s: missing <play|config> command.\n",progname);
printf("Usage 1: %s ", progname); printf("Usage 1: %s ", progname);
arg_print_syntax(stdout,argtable1,"\n"); arg_print_syntax(stdout,argtable1,"\n");
printf("Usage 2: %s ", progname); printf("Usage 2: %s ", progname);
arg_print_syntax(stdout,argtable2,"\n"); arg_print_syntax(stdout,argtable2,"\n");
printf("Usage 3: %s ", progname);
arg_print_syntax(stdout,argtable3,"\n");
} }
} }
exitcode = E_SUCCESS_AND_EXIT; exitcode = E_SUCCESS_AND_EXIT;
@@ -209,8 +131,6 @@ ConfigError getParameters(int argc, char** argv, Parameters* p)
arg_print_syntax(stdout,argtable1,"\n"); arg_print_syntax(stdout,argtable1,"\n");
printf("Usage 2: %s ", progname); printf("Usage 2: %s ", progname);
arg_print_syntax(stdout,argtable2,"\n"); arg_print_syntax(stdout,argtable2,"\n");
printf("Usage 3: %s ", progname);
arg_print_syntax(stdout,argtable3,"\n");
printf("\nReport bugs on the github github.com/spacefreak18/monocoque.\n"); printf("\nReport bugs on the github github.com/spacefreak18/monocoque.\n");
exitcode = E_SUCCESS_AND_EXIT; exitcode = E_SUCCESS_AND_EXIT;
goto cleanup; goto cleanup;
@@ -228,7 +148,6 @@ cleanup:
arg_freetable(argtable0,sizeof(argtable0)/sizeof(argtable0[0])); arg_freetable(argtable0,sizeof(argtable0)/sizeof(argtable0[0]));
arg_freetable(argtable1,sizeof(argtable1)/sizeof(argtable1[0])); arg_freetable(argtable1,sizeof(argtable1)/sizeof(argtable1[0]));
arg_freetable(argtable2,sizeof(argtable2)/sizeof(argtable2[0])); arg_freetable(argtable2,sizeof(argtable2)/sizeof(argtable2[0]));
arg_freetable(argtable3,sizeof(argtable3)/sizeof(argtable3[0]));
return exitcode; return exitcode;
} }
+2 -22
View File
@@ -1,41 +1,22 @@
#ifndef _PARAMETERS_H #ifndef _PARAMETERS_H
#define _PARAMETERS_H #define _PARAMETERS_H
#include <stdbool.h>
#include "../simulatorapi/simapi/simapi/simapi.h"
typedef struct typedef struct
{ {
int program_action; int program_action;
const char* sim_string; const char* sim_string;
const char* save_file; const char* save_file;
int fps;
int max_revs; int max_revs;
int granularity; int granularity;
int verbosity_count; int verbosity_count;
SimulatorAPI sim;
bool simon;
bool udp;
char* config_filepath;
char* config_dirpath;
bool user_specified_config_file;
bool user_specified_config_dir;
bool user_specified_log_file;
char* log_filename_str;
char* log_fullfilename_str;
char* log_dirname_str;
} }
Parameters; Parameters;
typedef enum typedef enum
{ {
A_PLAY = 0, A_PLAY = 0,
A_TEST = 1, A_CONFIG_TACH = 1,
A_CONFIG_TACH = 2, A_CONFIG_SHAKER = 2
A_CONFIG_SHAKER = 3
} }
ProgramAction; ProgramAction;
@@ -47,7 +28,6 @@ typedef enum
} }
ConfigError; ConfigError;
int freeparams(Parameters* p);
ConfigError getParameters(int argc, char** argv, Parameters* p); ConfigError getParameters(int argc, char** argv, Parameters* p);
struct _errordesc struct _errordesc
+122 -189
View File
@@ -2,20 +2,37 @@
#include <stdlib.h> #include <stdlib.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <string.h> #include <string.h>
#include <basedir_fs.h>
#include <libconfig.h>
#include <libconfig.h>
#include "gameloop/gameloop.h" #include "gameloop/gameloop.h"
#include "gameloop/tachconfig.h" #include "gameloop/tachconfig.h"
#include "devices/simdevice.h" #include "devices/simdevice.h"
#include "devices/sound.h"
#include "helper/parameters.h" #include "helper/parameters.h"
#include "helper/dirhelper.h" #include "helper/dirhelper.h"
#include "helper/confighelper.h" #include "helper/confighelper.h"
#include "simulatorapi/simapi/simapi/simdata.h" #include "simulatorapi/simdata.h"
#include "slog/slog.h" #include "slog/slog.h"
#define PROGRAM_NAME "monocoque" int create_dir(char* dir)
{
struct stat st = {0};
if (stat(dir, &st) == -1)
{
mkdir(dir, 0700);
}
}
char* create_user_dir(char* dirtype)
{
char* home_dir_str = gethome();
char* config_dir_str = ( char* ) malloc(1 + strlen(home_dir_str) + strlen(dirtype) + strlen("monocoque/"));
strcpy(config_dir_str, home_dir_str);
strcat(config_dir_str, dirtype);
strcat(config_dir_str, "monocoque");
create_dir(config_dir_str);
free(config_dir_str);
}
void display_banner() void display_banner()
{ {
@@ -26,60 +43,10 @@ void display_banner()
printf("/_/ /_/ \\____/ /_/ |_/ \\____/ \\____/ \\____/ \\___\\_\\\\____/ /_____/ \n"); printf("/_/ /_/ \\____/ /_/ |_/ \\____/ \\____/ \\____/ \\___\\_\\\\____/ /_____/ \n");
} }
void SetSettingsFromParameters(Parameters* p, MonocoqueSettings* ms, char* configdir_str, char* cachedir_str)
{
if(p->user_specified_config_file == true && does_file_exist(p->config_filepath))
{
ms->config_str = strdup(p->config_filepath);
}
else
{
if(p->user_specified_config_dir == true && does_directory_exist(p->config_dirpath))
{
asprintf(&ms->config_str, "%s/%s", p->config_dirpath, "monocoque.config");
}
else
{
asprintf(&ms->config_str, "%s%s", configdir_str, "monocoque.config");
}
}
if(p->user_specified_log_file == true && does_file_exist(p->log_fullfilename_str))
{
ms->log_dirname_str = strdup(p->log_dirname_str);
ms->log_filename_str = strdup(p->log_filename_str);
}
else
{
ms->log_dirname_str = strdup(cachedir_str);
ms->log_filename_str = strdup("monocoque.log");
}
ms->fps = p->fps;
ms->verbosity_count = p->verbosity_count;
ms->program_action = A_TEST;
if (p->program_action == A_PLAY)
{
ms->program_action = A_PLAY;
}
if (p->program_action == A_CONFIG_TACH)
{
ms->program_action = A_CONFIG_TACH;
}
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
display_banner(); display_banner();
char* home_dir_str = gethome();
if(home_dir_str == NULL)
{
fprintf(stderr, "You need a home directory");
return 0;
}
Parameters* p = malloc(sizeof(Parameters)); Parameters* p = malloc(sizeof(Parameters));
MonocoqueSettings* ms = malloc(sizeof(MonocoqueSettings));; MonocoqueSettings* ms = malloc(sizeof(MonocoqueSettings));;
@@ -88,47 +55,25 @@ int main(int argc, char** argv)
{ {
goto cleanup_final; goto cleanup_final;
} }
ms->program_action = p->program_action;
xdgHandle xdg; char* home_dir_str = gethome();
if(!xdgInitHandle(&xdg)) create_user_dir("/.config/");
{ create_user_dir("/.cache/");
fprintf(stderr, "Function xdgInitHandle() failed, is $HOME unset?"); char* config_file_str = ( char* ) malloc(1 + strlen(home_dir_str) + strlen("/.config/") + strlen("monocoque/monocoque.config"));
} char* cache_dir_str = ( char* ) malloc(1 + strlen(home_dir_str) + strlen("/.cache/monocoque/"));
strcpy(config_file_str, home_dir_str);
const char* config_home_str = xdgConfigHome(&xdg); strcat(config_file_str, "/.config/");
const char* cache_home_str = xdgCacheHome(&xdg); strcpy(cache_dir_str, home_dir_str);
strcat(cache_dir_str, "/.cache/monocoque/");
char* cachedir_str = NULL; strcat(config_file_str, "monocoque/monocoque.config");
char* configdir_str = NULL;
if(p->user_specified_config_file == false && p->user_specified_config_dir == false)
{
create_xdg_dir(config_home_str);
configdir_str = create_user_dir(home_dir_str, ".config", PROGRAM_NAME);
}
if(p->user_specified_log_file == false)
{
create_xdg_dir(cache_home_str);
cachedir_str = create_user_dir(home_dir_str, ".cache", PROGRAM_NAME);
}
SetSettingsFromParameters(p, ms, configdir_str, cachedir_str);
freeparams(p);
free(p);
//char* config_file_str = ( char* ) malloc(1 + strlen(home_dir_str) + strlen("/.config/") + strlen("monocoque/monocoque.config"));
size_t diameters_file_sz = snprintf(NULL, 0, "%s/.config/monocoque/diameters.config", home_dir_str);
diameters_file_sz += 1;
char* diameters_file_str = ( char* ) malloc(diameters_file_sz);
snprintf(diameters_file_str, diameters_file_sz, "%s/.config/monocoque/diameters.config", home_dir_str);
slog_config_t slgCfg; slog_config_t slgCfg;
slog_config_get(&slgCfg); slog_config_get(&slgCfg);
slgCfg.eColorFormat = SLOG_COLORING_TAG; slgCfg.eColorFormat = SLOG_COLORING_TAG;
slgCfg.eDateControl = SLOG_TIME_ONLY; slgCfg.eDateControl = SLOG_TIME_ONLY;
strcpy(slgCfg.sFileName, ms->log_filename_str); strcpy(slgCfg.sFileName, "monocoque.log");
strcpy(slgCfg.sFilePath, ms->log_dirname_str); strcpy(slgCfg.sFilePath, cache_dir_str);
slgCfg.nTraceTid = 0; slgCfg.nTraceTid = 0;
slgCfg.nToScreen = 1; slgCfg.nToScreen = 1;
slgCfg.nUseHeap = 0; slgCfg.nUseHeap = 0;
@@ -136,45 +81,41 @@ int main(int argc, char** argv)
slgCfg.nFlush = 0; slgCfg.nFlush = 0;
slgCfg.nFlags = SLOG_FLAGS_ALL; slgCfg.nFlags = SLOG_FLAGS_ALL;
slog_config_set(&slgCfg); slog_config_set(&slgCfg);
if (ms->verbosity_count < 2) if (p->verbosity_count < 2)
{ {
slog_disable(SLOG_TRACE); slog_disable(SLOG_TRACE);
} }
if (ms->verbosity_count < 1) if (p->verbosity_count < 1)
{ {
slog_disable(SLOG_DEBUG); slog_disable(SLOG_DEBUG);
} }
ms->tyre_diameter_config = strdup(diameters_file_str); slogi("Loading configuration file: %s", config_file_str);
ms->useconfig = 0;
ms->configcheck = 0;
free(diameters_file_str);
slogi("Testing monocoque config file: %s", ms->config_str);
slogd("using diameters file %s %i", ms->tyre_diameter_config, ms->configcheck);
config_t cfg; config_t cfg;
config_init(&cfg); config_init(&cfg);
config_setting_t* config_devices = NULL; config_setting_t* config_devices = NULL;
if (!config_read_file(&cfg, ms->config_str))
if (!config_read_file(&cfg, config_file_str))
{ {
fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
goto cleanup_final;
} }
else else
{ {
slogi("Openend monocoque configuration file"); slogi("Openend monocoque configuration file");
config_devices = config_lookup(&cfg, "devices");
} }
free(config_file_str);
free(cache_dir_str);
if (p->program_action == A_CONFIG_TACH)
if (ms->program_action == A_CONFIG_TACH)
{ {
int error = 0; int error = 0;
SimDevice* tachdev = malloc(sizeof(SimDevice)); SimDevice* tachdev = malloc(sizeof(SimDevice));
SimData* sdata = malloc(sizeof(SimData)); SimData* sdata = malloc(sizeof(SimData));
DeviceSettings* ds = malloc(sizeof(DeviceSettings)); DeviceSettings* ds = malloc(sizeof(DeviceSettings));
error = devsetup("USB", "Tachometer", "None", ms, ds, NULL); error = devsetup("USB", "Tachometer", "None", ms, ds, NULL);
error = devinit(tachdev, ds);
slogi("configuring tachometer with max revs: %i, granularity: %i, saving to %s", p->max_revs, p->granularity, p->save_file);
if (error != MONOCOQUE_ERROR_NONE) if (error != MONOCOQUE_ERROR_NONE)
{ {
@@ -182,118 +123,110 @@ int main(int argc, char** argv)
} }
else else
{ {
int devices = 0;
devices = devinit(tachdev, 1, ds, ms);
if(devices < 1)
{
error = MONOCOQUE_ERROR_INVALID_DEV;
}
}
if (error != MONOCOQUE_ERROR_NONE)
{
sloge("Could not proceed with tachometer configuration due to error: %i", error);
}
else
{
slogi("configuring tachometer with max revs: %i, granularity: %i, saving to %s", p->max_revs, p->granularity, p->save_file);
config_tachometer(p->max_revs, p->granularity, p->save_file, tachdev, sdata); config_tachometer(p->max_revs, p->granularity, p->save_file, tachdev, sdata);
} }
devfree(tachdev);
slogt("freeing devices if necessary"); free(tachdev);
if(tachdev->initialized == true)
{
slogt("freeing tachmoeter device");
tachdev->free(tachdev);
}
//free(tachdev);
free(sdata); free(sdata);
free(ds); free(ds);
} }
else else
{ {
slogi("running monocoque in gameloop mode..");
int error = 0; int error = 0;
error = MONOCOQUE_ERROR_NONE;
setupsound();
bool pulseaudio = false;
if (ms->program_action == A_PLAY) error = strtogame(p->sim_string, ms);
if (error != MONOCOQUE_ERROR_NONE)
{ {
ms->useconfig = 1; goto cleanup_final;
slogi("running monocoque in gameloop mode.."); }
#ifdef USE_PULSEAUDIO
pa_threaded_mainloop_unlock(mainloop); int configureddevices = config_setting_length(config_devices);
pulseaudio = true; int numdevices = 0;
#endif DeviceSettings* ds[configureddevices];
slogi("found %i devices in configuration", configureddevices);
int i = 0;
while (i<configureddevices)
{
error = MONOCOQUE_ERROR_NONE;
DeviceSettings* settings = malloc(sizeof(DeviceSettings));
ds[i] = settings;
config_setting_t* config_device = config_setting_get_elem(config_devices, i);
const char* device_type;
const char* device_subtype;
const char* device_config_file;
config_setting_lookup_string(config_device, "device", &device_type);
config_setting_lookup_string(config_device, "type", &device_subtype);
config_setting_lookup_string(config_device, "config", &device_config_file);
//error = looper(devices, numdevices, p);
error = monocoque_mainloop(ms);
if (error == MONOCOQUE_ERROR_NONE) if (error == MONOCOQUE_ERROR_NONE)
{ {
slogi("Game loop exited succesfully with error code: %i", error); error = devsetup(device_type, device_subtype, device_config_file, ms, ds[i], config_device);
} }
else if (error == MONOCOQUE_ERROR_NONE)
{ {
sloge("Game loop exited with error code: %i", error); numdevices++;
} }
i++;
}
i = 0;
int j = 0;
error = MONOCOQUE_ERROR_NONE;
SimDevice* devices[numdevices];
while (i<configureddevices)
{
if (ds[i]->is_valid == true)
{
SimDevice* device = malloc(sizeof(SimDevice));
devinit(device, ds[i]);
devices[j] = device;
j++;
}
i++;
}
error = looper(devices, numdevices, ms->sim_name);
if (error == MONOCOQUE_ERROR_NONE)
{
slogi("Game loop exited succesfully with error code: %i", error);
} }
else else
{ {
slogi("running monocoque in test mode..."); sloge("Game loop exited with error code: %i", error);
#ifdef USE_PULSEAUDIO
pa_threaded_mainloop_unlock(mainloop);
pulseaudio = true;
#endif
ms->useconfig = 0;
int configs = getNumberOfConfigs(ms->config_str);
int confignum = getconfigtouse(ms->config_str, "default", configs-1);
int configureddevices;
configcheck(ms->config_str, confignum, &configureddevices);
DeviceSettings* ds = malloc(configureddevices * sizeof(DeviceSettings));
slogd("loading confignum %i, with %i devices.", confignum, configureddevices);
int numdevices = uiloadconfig(ms->config_str, confignum, configureddevices, ms, ds);
SimDevice* simdevices = malloc(numdevices * sizeof(SimDevice));
int initdevices = devinit(simdevices, configureddevices, ds, ms);
for( int i = 0; i < configureddevices; i++)
{
settingsfree(ds[i]);
}
free(ds);
error = tester(simdevices, numdevices);
if (error == MONOCOQUE_ERROR_NONE)
{
slogi("Test exited succesfully with error code: %i", error);
}
else
{
sloge("Test exited with error code: %i", error);
}
for (int x = 0; x < numdevices; x++)
{
if (simdevices[x].initialized == true)
{
simdevices[x].free(&simdevices[x]);
}
}
} }
if(pulseaudio == true)
i = 0;
while (i<configureddevices)
{ {
freesound(); if(ds[i]->dev_subtype == SIMDEV_USB)
{
free(ds[i]->tachsettings.pulses_array);
free(ds[i]->tachsettings.rpms_array);
}
free(ds[i]);
i++;
}
i = 0;
while (i<numdevices)
{
devfree(devices[i]);
free(devices[i]);
i++;
} }
} }
cleanup_final: configcleanup:
config_destroy(&cfg);
monocoquesettingsfree(ms); cleanup_final:
free(ms); free(ms);
free(p);
exit(0); exit(0);
} }
+6 -17
View File
@@ -1,21 +1,10 @@
set(simulatorapi_source_files set(simulatorapi_source_files
simapi/simapi/simmapper.c simmapper.c
simapi/simapi/simmapper.h simmapper.h
simapi/simapi/simdata.h simdata.h
simapi/simapi/test.h test.h
simapi/include/acdata.h simapi/acdata.h
simapi/include/rf2data.h ac.h
simapi/include/pcars2data.h
simapi/include/scs2data.h
simapi/simmap/basicmap.h
simapi/simmap/mapacdata.c
simapi/simmap/mapacdata.h
simapi/simapi/ac.h
simapi/simapi/rf2.h
simapi/simapi/pcars2.h
simapi/simapi/scs2.h
simapi/simapi/getpid.c
simapi/simapi/getpid.h
) )
add_library(simulatorapi STATIC ${simulatorapi_source_files}) add_library(simulatorapi STATIC ${simulatorapi_source_files})
+21
View File
@@ -0,0 +1,21 @@
#ifndef _AC_H
#define _AC_H
#include <stdbool.h>
#include "simapi/acdata.h"
#define AC_PHYSICS_FILE "acpmf_physics"
#define AC_STATIC_FILE "acpmf_static"
typedef struct
{
bool has_physics;
bool has_static;
void* physics_map_addr;
void* static_map_addr;
struct SPageFilePhysics ac_physics;
struct SPageFileStatic ac_static;
}
ACMap;
#endif
+21
View File
@@ -0,0 +1,21 @@
#ifndef _RF2_H
#define _RF2_H
#include <stdbool.h>
#include "simapi/rf2data.h"
#define RF2_TELEMETRY_FILE "rFactor2SMMP_Telemetry"
#define RF2_SCORING_FILE "rFactor2SMMP_Scoring"
typedef struct
{
bool has_telemetry;
bool has_scoring;
void* telemetry_map_addr;
void* scoring_map_addr;
struct rF2Telemetry rf2_telemetry;
//struct rF2Scoring rf2_scoring;
}
RF2Map;
#endif
+17
View File
@@ -0,0 +1,17 @@
#ifndef _SIMDATA_H
#define _SIMDATA_H
#include <stdint.h>
typedef struct
{
uint32_t velocity;
uint32_t rpms;
uint32_t gear;
uint32_t pulses;
uint32_t maxrpm;
uint32_t altitude;
}
SimData;
#endif
+136
View File
@@ -0,0 +1,136 @@
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <math.h>
#include "simmapper.h"
#include "simdata.h"
#include "test.h"
#include "ac.h"
#include "rf2.h"
#include "../helper/confighelper.h"
#include "../slog/slog.h"
#include "simapi/acdata.h"
#include "simapi/rf2data.h"
int simdatamap(SimData* simdata, SimMap* simmap, Simulator simulator)
{
char* a;
char* b;
switch ( simulator )
{
case SIMULATOR_MONOCOQUE_TEST :
memcpy(simdata, simmap->addr, sizeof(SimData));
break;
case SIMULATOR_ASSETTO_CORSA :
a = simmap->d.ac.physics_map_addr;
if (simmap->d.ac.has_static == true )
{
b = simmap->d.ac.static_map_addr;
simdata->maxrpm = *(uint32_t*) (char*) (b + offsetof(struct SPageFileStatic, maxRpm));
}
simdata->rpms = *(uint32_t*) (char*) (a + offsetof(struct SPageFilePhysics, rpms));
simdata->gear = *(uint32_t*) (char*) (a + offsetof(struct SPageFilePhysics, gear));
simdata->velocity = ceil( *(float*) (char*) (a + offsetof(struct SPageFilePhysics, speedKmh)));
simdata->altitude = 1;
break;
case SIMULATOR_RFACTOR2 :
a = simmap->d.rf2.telemetry_map_addr;
simdata->velocity = ceil(3.6 * ( *(double*) (char*) (a + offsetof(struct rF2Telemetry, mVehicles[0].mLocalVel.z))));
simdata->rpms = ceil( *(double*) (char*) (a + offsetof(struct rF2Telemetry, mVehicles[0].mEngineRPM)));
simdata->maxrpm = ceil( *(double*) (char*) (a + offsetof(struct rF2Telemetry, mVehicles[0].mEngineMaxRPM)));
simdata->gear = *(uint32_t*) (char*) (a + offsetof(struct rF2Telemetry, mVehicles[0].mGear));
break;
}
}
int siminit(SimData* simdata, SimMap* simmap, Simulator simulator)
{
slogi("searching for simulator data...");
int error = MONOCOQUE_ERROR_NONE;
void* a;
switch ( simulator )
{
case SIMULATOR_MONOCOQUE_TEST :
simmap->fd = shm_open(TEST_MEM_FILE_LOCATION, O_RDONLY, S_IRUSR | S_IWUSR);
if (simmap->fd == -1)
{
return 10;
}
simmap->addr = mmap(NULL, sizeof(SimData), PROT_READ, MAP_SHARED, simmap->fd, 0);
if (simmap->addr == MAP_FAILED)
{
return 30;
}
slogi("found data for monocoque test...");
break;
case SIMULATOR_ASSETTO_CORSA :
simmap->d.ac.has_physics=false;
simmap->d.ac.has_static=false;
simmap->fd = shm_open(AC_PHYSICS_FILE, O_RDONLY, S_IRUSR | S_IWUSR);
if (simmap->fd == -1)
{
slogd("could not open Assetto Corsa physics engine");
return MONOCOQUE_ERROR_NODATA;
}
simmap->d.ac.physics_map_addr = mmap(NULL, sizeof(simmap->d.ac.ac_physics), PROT_READ, MAP_SHARED, simmap->fd, 0);
if (simmap->d.ac.physics_map_addr == MAP_FAILED)
{
slogd("could not retrieve Assetto Corsa physics data");
return 30;
}
simmap->d.ac.has_physics=true;
simmap->fd = shm_open(AC_STATIC_FILE, O_RDONLY, S_IRUSR | S_IWUSR);
if (simmap->fd == -1)
{
slogd("could not open Assetto Corsa static data");
return 10;
}
simmap->d.ac.static_map_addr = mmap(NULL, sizeof(simmap->d.ac.ac_static), PROT_READ, MAP_SHARED, simmap->fd, 0);
if (simmap->d.ac.static_map_addr == MAP_FAILED)
{
slogd("could not retrieve Assetto Corsa static data");
return 30;
}
simmap->d.ac.has_static=true;
slogi("found data for Assetto Corsa...");
break;
case SIMULATOR_RFACTOR2 :
simmap->d.rf2.has_telemetry=false;
simmap->d.rf2.has_scoring=false;
simmap->fd = shm_open(RF2_TELEMETRY_FILE, O_RDONLY, S_IRUSR | S_IWUSR);
if (simmap->fd == -1)
{
slogd("could not open RFactor2 Telemetry engine");
return MONOCOQUE_ERROR_NODATA;
}
simmap->d.rf2.telemetry_map_addr = mmap(NULL, sizeof(simmap->d.rf2.rf2_telemetry), PROT_READ, MAP_SHARED, simmap->fd, 0);
if (simmap->d.rf2.telemetry_map_addr == MAP_FAILED)
{
slogd("could not retrieve RFactor2 telemetry data");
return 30;
}
simmap->d.rf2.has_telemetry=true;
slogi("found data for RFactor2...");
break;
}
return error;
}
+28
View File
@@ -0,0 +1,28 @@
#ifndef _SIMMAPPER_H
#define _SIMMAPPER_H
#include "ac.h"
#include "rf2.h"
#include "simdata.h"
#include "../helper/confighelper.h"
#include "simapi/acdata.h"
#include "simapi/rf2data.h"
typedef struct
{
void* addr;
int fd;
union
{
ACMap ac;
RF2Map rf2;
} d;
}
SimMap;
int siminit(SimData* simdata, SimMap* simmap, Simulator simulator);
int simdatamap(SimData* simdata, SimMap* simmap, Simulator simulator);
#endif
+6
View File
@@ -0,0 +1,6 @@
#ifndef _TEST_H
#define _TEST_H
#define TEST_MEM_FILE_LOCATION "/monocoque_test"
#endif
+185 -216
View File
@@ -1,7 +1,7 @@
/* /*
* The MIT License (MIT) * The MIT License (MIT)
* *
* Copyleft (C) 2015-2023 Sun Dro (s.kalatoz@gmail.com) * Copyleft (C) 2015-2020 Sun Dro (f4tb0y@protonmail.com)
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@@ -27,6 +27,7 @@
#endif #endif
#include <stdio.h> #include <stdio.h>
#include <pthread.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@@ -36,89 +37,86 @@
#include <time.h> #include <time.h>
#include "slog.h" #include "slog.h"
#ifdef __linux__ #if !defined(__APPLE__) && !defined(DARWIN) && !defined(WIN32)
#include <syscall.h> #include <syscall.h>
#endif #endif
#include <sys/time.h> #include <sys/time.h>
#ifdef WIN32 #ifdef WIN32
#include <windows.h> #include <windows.h>
#endif #endif
#ifndef PTHREAD_MUTEX_RECURSIVE #ifndef PTHREAD_MUTEX_RECURSIVE
#define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP #define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP
#endif #endif
typedef struct slog_file { typedef struct slog
uint8_t nCurrDay; {
FILE *pHandle; unsigned int nTdSafe:1;
} slog_file_t;
typedef struct slog {
pthread_mutex_t mutex; pthread_mutex_t mutex;
slog_config_t config; slog_config_t config;
slog_file_t logFile;
uint8_t nTdSafe;
} slog_t; } slog_t;
typedef struct slog_context { typedef struct XLogCtx
const char *pFormat; {
const char* pFormat;
slog_flag_t eFlag; slog_flag_t eFlag;
slog_date_t date; slog_date_t date;
uint8_t nFullColor;
uint8_t nNewLine; uint8_t nNewLine;
} slog_context_t; } slog_context_t;
static volatile int g_nHaveSlogVerShort = 0;
static volatile int g_nHaveSlogVerLong = 0;
static char g_slogVerShort[128];
static char g_slogVerLong[256];
static slog_t g_slog; static slog_t g_slog;
static void slog_sync_init(slog_t *pSlog) static void slog_sync_init(slog_t* pSlog)
{ {
if (!pSlog->nTdSafe) return; if (!pSlog->nTdSafe)
{
return;
}
pthread_mutexattr_t mutexAttr; pthread_mutexattr_t mutexAttr;
if (pthread_mutexattr_init(&mutexAttr) || if (pthread_mutexattr_init(&mutexAttr) ||
pthread_mutexattr_settype(&mutexAttr, PTHREAD_MUTEX_RECURSIVE) || pthread_mutexattr_settype(&mutexAttr, PTHREAD_MUTEX_RECURSIVE) ||
pthread_mutex_init(&pSlog->mutex, &mutexAttr) || pthread_mutex_init(&pSlog->mutex, &mutexAttr) ||
pthread_mutexattr_destroy(&mutexAttr)) pthread_mutexattr_destroy(&mutexAttr))
{ {
printf("<%s:%d> %s: [ERROR] Can not initialize mutex: %d\n", printf("<%s:%d> %s: [ERROR] Can not initialize mutex: %d\n",
__FILE__, __LINE__, __func__, errno); __FILE__, __LINE__, __FUNCTION__, errno);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
static void slog_lock(slog_t *pSlog) static void slog_lock(slog_t* pSlog)
{ {
if (pSlog->nTdSafe && pthread_mutex_lock(&pSlog->mutex)) if (pSlog->nTdSafe && pthread_mutex_lock(&pSlog->mutex))
{ {
printf("<%s:%d> %s: [ERROR] Can not lock mutex: %d\n", printf("<%s:%d> %s: [ERROR] Can not lock mutex: %d\n",
__FILE__, __LINE__, __func__, errno); __FILE__, __LINE__, __FUNCTION__, errno);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
static void slog_unlock(slog_t *pSlog) static void slog_unlock(slog_t* pSlog)
{ {
if (pSlog->nTdSafe && pthread_mutex_unlock(&pSlog->mutex)) if (pSlog->nTdSafe && pthread_mutex_unlock(&pSlog->mutex))
{ {
printf("<%s:%d> %s: [ERROR] Can not unlock mutex: %d\n", printf("<%s:%d> %s: [ERROR] Can not unlock mutex: %d\n",
__FILE__, __LINE__, __func__, errno); __FILE__, __LINE__, __FUNCTION__, errno);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
static const char *slog_get_indent(slog_flag_t eFlag) static const char* slog_get_indent(slog_flag_t eFlag)
{ {
slog_config_t *pCfg = &g_slog.config; slog_config_t* pCfg = &g_slog.config;
if (!pCfg->nIndent) return SLOG_EMPTY; if (!pCfg->nIndent)
{
return SLOG_EMPTY;
}
switch (eFlag) switch (eFlag)
{ {
@@ -127,12 +125,13 @@ static const char *slog_get_indent(slog_flag_t eFlag)
case SLOG_NOTE: case SLOG_NOTE:
case SLOG_INFO: case SLOG_INFO:
case SLOG_WARN: case SLOG_WARN:
return SLOG_SPACE; return SLOG_SPACE;
case SLOG_DEBUG: case SLOG_DEBUG:
case SLOG_TRACE: case SLOG_TRACE:
case SLOG_FATAL: case SLOG_FATAL:
case SLOG_ERROR: case SLOG_ERROR:
default: break; default:
break;
} }
return SLOG_EMPTY; return SLOG_EMPTY;
@@ -142,14 +141,22 @@ static const char* slog_get_tag(slog_flag_t eFlag)
{ {
switch (eFlag) switch (eFlag)
{ {
case SLOG_NOTE: return "note"; case SLOG_NOTE:
case SLOG_INFO: return "info"; return "note";
case SLOG_WARN: return "warn"; case SLOG_INFO:
case SLOG_DEBUG: return "debug"; return "info";
case SLOG_ERROR: return "error"; case SLOG_WARN:
case SLOG_TRACE: return "trace"; return "warn";
case SLOG_FATAL: return "fatal"; case SLOG_DEBUG:
default: break; return "debug";
case SLOG_ERROR:
return "error";
case SLOG_TRACE:
return "trace";
case SLOG_FATAL:
return "fatal";
default:
break;
} }
return NULL; return NULL;
@@ -160,62 +167,38 @@ static const char* slog_get_color(slog_flag_t eFlag)
switch (eFlag) switch (eFlag)
{ {
case SLOG_NOTAG: case SLOG_NOTAG:
case SLOG_NOTE: return SLOG_EMPTY; case SLOG_NOTE:
case SLOG_INFO: return SLOG_COLOR_GREEN; return SLOG_EMPTY;
case SLOG_WARN: return SLOG_COLOR_YELLOW; case SLOG_INFO:
case SLOG_DEBUG: return SLOG_COLOR_BLUE; return SLOG_COLOR_GREEN;
case SLOG_ERROR: return SLOG_COLOR_RED; case SLOG_WARN:
case SLOG_TRACE: return SLOG_COLOR_CYAN; return SLOG_COLOR_YELLOW;
case SLOG_FATAL: return SLOG_COLOR_MAGENTA; case SLOG_DEBUG:
default: break; return SLOG_COLOR_BLUE;
case SLOG_ERROR:
return SLOG_COLOR_RED;
case SLOG_TRACE:
return SLOG_COLOR_CYAN;
case SLOG_FATAL:
return SLOG_COLOR_MAGENTA;
default:
break;
} }
return SLOG_EMPTY; return SLOG_EMPTY;
} }
static void slog_close_file(slog_file_t *pFile) uint8_t slog_get_usec()
{
if (pFile->pHandle != NULL)
{
fclose(pFile->pHandle);
pFile->pHandle = NULL;
}
}
static uint8_t slog_open_file(slog_file_t *pFile, const slog_config_t *pCfg, const slog_date_t *pDate)
{
slog_close_file(pFile);
char sFilePath[SLOG_PATH_MAX + SLOG_NAME_MAX + SLOG_DATE_MAX];
snprintf(sFilePath, sizeof(sFilePath), "%s/%s-%04d-%02d-%02d.log",
pCfg->sFilePath, pCfg->sFileName, pDate->nYear, pDate->nMonth, pDate->nDay);
#ifdef _WIN32
if (fopen_s(&pFile->pHandle, sFilePath, "a")) pFile->pHandle = NULL;
#else
pFile->pHandle = fopen(sFilePath, "a");
#endif
if (pFile->pHandle == NULL)
{
printf("<%s:%d> %s: [ERROR] Failed to open file: %s (%s)\n",
__FILE__, __LINE__, __func__, sFilePath, strerror(errno));
return 0;
}
pFile->nCurrDay = pDate->nDay;
return 1;
}
uint16_t slog_get_usec()
{ {
struct timeval tv; struct timeval tv;
if (gettimeofday(&tv, NULL) < 0) return 0; if (gettimeofday(&tv, NULL) < 0)
return (uint16_t)(tv.tv_usec / 1000); {
return 0;
}
return (uint8_t)(tv.tv_usec / 10000);
} }
void slog_get_date(slog_date_t *pDate) void slog_get_date(slog_date_t* pDate)
{ {
struct tm timeinfo; struct tm timeinfo;
time_t rawtime = time(NULL); time_t rawtime = time(NULL);
@@ -234,68 +217,70 @@ void slog_get_date(slog_date_t *pDate)
pDate->nUsec = slog_get_usec(); pDate->nUsec = slog_get_usec();
} }
static size_t slog_get_tid() static uint32_t slog_get_tid()
{ {
#ifdef __linux__ #if defined(__APPLE__) || defined(DARWIN) || defined(WIN32)
return (size_t)syscall(__NR_gettid); return (uint32_t)pthread_self();
#else #else
return (size_t)pthread_self(); return syscall(__NR_gettid);
#endif #endif
} }
static void slog_create_tag(char *pOut, size_t nSize, slog_flag_t eFlag, const char *pColor) static void slog_create_tag(char* pOut, size_t nSize, slog_flag_t eFlag, const char* pColor)
{ {
slog_config_t *pCfg = &g_slog.config; slog_config_t* pCfg = &g_slog.config;
pOut[0] = SLOG_NUL; pOut[0] = SLOG_NUL;
const char *pIndent = slog_get_indent(eFlag); const char* pIndent = slog_get_indent(eFlag);
const char *pTag = slog_get_tag(eFlag); const char* pTag = slog_get_tag(eFlag);
if (pTag == NULL) if (pTag == NULL)
{ {
snprintf(pOut, nSize, "%s", pIndent); snprintf(pOut, nSize, pIndent);
return; return;
} }
if (pCfg->eColorFormat != SLOG_COLORING_TAG) snprintf(pOut, nSize, "<%s>%s", pTag, pIndent); if (pCfg->eColorFormat != SLOG_COLORING_TAG)
else snprintf(pOut, nSize, "%s<%s>%s%s", pColor, pTag, SLOG_COLOR_RESET, pIndent); {
snprintf(pOut, nSize, "<%s>%s", pTag, pIndent);
}
else
{
snprintf(pOut, nSize, "%s<%s>%s%s", pColor, pTag, SLOG_COLOR_RESET, pIndent);
}
} }
static void slog_create_tid(char *pOut, int nSize, uint8_t nTraceTid) static void slog_create_tid(char* pOut, int nSize, uint8_t nTraceTid)
{ {
if (!nTraceTid) pOut[0] = SLOG_NUL; if (!nTraceTid)
else snprintf(pOut, nSize, "(%zu) ", slog_get_tid()); {
pOut[0] = SLOG_NUL;
}
else
{
snprintf(pOut, nSize, "(%u) ", slog_get_tid());
}
} }
static void slog_display_message(const slog_context_t *pCtx, const char *pInfo, int nInfoLen, const char *pInput) static void slog_display_message(const slog_context_t* pCtx, const char* pInfo, int nInfoLen, const char* pInput)
{ {
slog_config_t *pCfg = &g_slog.config; slog_config_t* pCfg = &g_slog.config;
slog_file_t *pFile = &g_slog.logFile;
int nCbVal = 1; int nCbVal = 1;
uint8_t nFullColor = pCfg->eColorFormat == SLOG_COLORING_FULL ? 1 : 0; const char* pSeparator = nInfoLen > 0 ? pCfg->sSeparator : SLOG_EMPTY;
const char *pSeparator = nInfoLen > 0 ? pCfg->sSeparator : SLOG_EMPTY; const char* pReset = pCtx->nFullColor ? SLOG_COLOR_RESET : SLOG_EMPTY;
const char *pNewLine = pCtx->nNewLine ? SLOG_NEWLINE : SLOG_EMPTY; const char* pNewLine = pCtx->nNewLine ? SLOG_NEWLINE : SLOG_EMPTY;
const char *pMessage = pInput != NULL ? pInput : SLOG_EMPTY; const char* pMessage = pInput != NULL ? pInput : SLOG_EMPTY;
const char *pReset = nFullColor ? SLOG_COLOR_RESET : SLOG_EMPTY;
if (pCfg->logCallback != NULL) if (pCfg->logCallback != NULL)
{ {
size_t nLength = 0; size_t nLength = 0;
char *pLog = NULL; char* pLog = NULL;
nLength += asprintf(&pLog, "%s%s%s%s%s", pInfo,
pSeparator, pMessage, pReset, pNewLine);
nLength += asprintf(&pLog, "%s%s%s%s%s", pInfo, pSeparator, pMessage, pReset, pNewLine);
if (pLog != NULL) if (pLog != NULL)
{ {
nCbVal = pCfg->logCallback ( nCbVal = pCfg->logCallback(pLog, nLength, pCtx->eFlag, pCfg->pCallbackCtx);
pLog,
nLength,
pCtx->eFlag,
pCfg->pCallbackCtx
);
free(pLog); free(pLog);
} }
} }
@@ -303,26 +288,36 @@ static void slog_display_message(const slog_context_t *pCtx, const char *pInfo,
if (pCfg->nToScreen && nCbVal > 0) if (pCfg->nToScreen && nCbVal > 0)
{ {
printf("%s%s%s%s%s", pInfo, pSeparator, pMessage, pReset, pNewLine); printf("%s%s%s%s%s", pInfo, pSeparator, pMessage, pReset, pNewLine);
if (pCfg->nFlush) fflush(stdout); if (pCfg->nFlush)
{
fflush(stdout);
}
} }
if (!pCfg->nToFile || nCbVal < 0) return; if (!pCfg->nToFile || nCbVal < 0)
const slog_date_t *pDate = &pCtx->date; {
return;
}
const slog_date_t* pDate = &pCtx->date;
if (pFile->nCurrDay != pDate->nDay && pCfg->nRotate) slog_close_file(pFile); char sFilePath[SLOG_PATH_MAX + SLOG_NAME_MAX + SLOG_DATE_MAX];
if (pFile->pHandle == NULL && !slog_open_file(pFile, pCfg, pDate)) return; snprintf(sFilePath, sizeof(sFilePath), "%s/%s-%04d-%02d-%02d.log",
pCfg->sFilePath, pCfg->sFileName, pDate->nYear, pDate->nMonth, pDate->nDay);
fprintf(pFile->pHandle, "%s%s%s%s%s", pInfo, FILE* pFile = fopen(sFilePath, "a");
pSeparator, pMessage, pReset, pNewLine); if (pFile == NULL)
{
return;
}
if (pCfg->nFlush) fflush(pFile->pHandle); fprintf(pFile, "%s%s%s%s%s", pInfo, pSeparator, pMessage, pReset, pNewLine);
if (!pCfg->nKeepOpen) slog_close_file(pFile); fclose(pFile);
} }
static int slog_create_info(const slog_context_t *pCtx, char* pOut, size_t nSize) static int slog_create_info(const slog_context_t* pCtx, char* pOut, size_t nSize)
{ {
slog_config_t *pCfg = &g_slog.config; slog_config_t* pCfg = &g_slog.config;
const slog_date_t *pDate = &pCtx->date; const slog_date_t* pDate = &pCtx->date;
char sDate[SLOG_DATE_MAX + SLOG_NAME_MAX]; char sDate[SLOG_DATE_MAX + SLOG_NAME_MAX];
sDate[0] = SLOG_NUL; sDate[0] = SLOG_NUL;
@@ -330,30 +325,29 @@ static int slog_create_info(const slog_context_t *pCtx, char* pOut, size_t nSize
if (pCfg->eDateControl == SLOG_TIME_ONLY) if (pCfg->eDateControl == SLOG_TIME_ONLY)
{ {
snprintf(sDate, sizeof(sDate), "%02d:%02d:%02d.%03d ", snprintf(sDate, sizeof(sDate), "%02d:%02d:%02d.%03d ",
pDate->nHour, pDate->nMin, pDate->nSec, pDate->nUsec); pDate->nHour,pDate->nMin, pDate->nSec, pDate->nUsec);
}
else if (pCfg->eDateControl == SLOG_DATE_FULL)
{
snprintf(sDate, sizeof(sDate), "%04d.%02d.%02d-%02d:%02d:%02d.%03d ",
pDate->nYear, pDate->nMonth, pDate->nDay, pDate->nHour,
pDate->nMin, pDate->nSec, pDate->nUsec);
} }
else
if (pCfg->eDateControl == SLOG_DATE_FULL)
{
snprintf(sDate, sizeof(sDate), "%04d.%02d.%02d-%02d:%02d:%02d.%03d ",
pDate->nYear, pDate->nMonth, pDate->nDay, pDate->nHour,
pDate->nMin, pDate->nSec, pDate->nUsec);
}
char sTid[SLOG_TAG_MAX], sTag[SLOG_TAG_MAX]; char sTid[SLOG_TAG_MAX], sTag[SLOG_TAG_MAX];
uint8_t nFullColor = pCfg->eColorFormat == SLOG_COLORING_FULL ? 1 : 0; const char* pColorCode = slog_get_color(pCtx->eFlag);
const char* pColor = pCtx->nFullColor ? pColorCode : SLOG_EMPTY;
const char *pColorCode = slog_get_color(pCtx->eFlag);
const char *pColor = nFullColor ? pColorCode : SLOG_EMPTY;
slog_create_tid(sTid, sizeof(sTid), pCfg->nTraceTid); slog_create_tid(sTid, sizeof(sTid), pCfg->nTraceTid);
slog_create_tag(sTag, sizeof(sTag), pCtx->eFlag, pColorCode); slog_create_tag(sTag, sizeof(sTag), pCtx->eFlag, pColorCode);
return snprintf(pOut, nSize, "%s%s%s%s", pColor, sTid, sDate, sTag); return snprintf(pOut, nSize, "%s%s%s%s", pColor, sTid, sDate, sTag);
} }
static void slog_display_heap(const slog_context_t *pCtx, va_list args) static void slog_display_heap(const slog_context_t* pCtx, va_list args)
{ {
size_t nBytes = 0; size_t nBytes = 0;
char *pMessage = NULL; char* pMessage = NULL;
char sLogInfo[SLOG_INFO_MAX]; char sLogInfo[SLOG_INFO_MAX];
nBytes += vasprintf(&pMessage, pCtx->pFormat, args); nBytes += vasprintf(&pMessage, pCtx->pFormat, args);
@@ -361,18 +355,21 @@ static void slog_display_heap(const slog_context_t *pCtx, va_list args)
if (pMessage == NULL) if (pMessage == NULL)
{ {
printf("<%s:%d> %s<error>%s %s: Can not allocate memory for input: errno(%d)\n", printf("<%s:%d> %s<error>%s %s: Can not allocate memory for input: errno(%d)\n",
__FILE__, __LINE__, SLOG_COLOR_RED, SLOG_COLOR_RESET, __func__, errno); __FILE__, __LINE__, SLOG_COLOR_RED, SLOG_COLOR_RESET, __FUNCTION__, errno);
return; return;
} }
int nLength = slog_create_info(pCtx, sLogInfo, sizeof(sLogInfo)); int nLength = slog_create_info(pCtx, sLogInfo, sizeof(sLogInfo));
slog_display_message(pCtx, sLogInfo, nLength, pMessage); slog_display_message(pCtx, sLogInfo, nLength, pMessage);
if (pMessage != NULL) free(pMessage); if (pMessage != NULL)
{
free(pMessage);
}
} }
static void slog_display_stack(const slog_context_t *pCtx, va_list args) static void slog_display_stack(const slog_context_t* pCtx, va_list args)
{ {
char sMessage[SLOG_MESSAGE_MAX]; char sMessage[SLOG_MESSAGE_MAX];
char sLogInfo[SLOG_INFO_MAX]; char sLogInfo[SLOG_INFO_MAX];
@@ -382,13 +379,13 @@ static void slog_display_stack(const slog_context_t *pCtx, va_list args)
slog_display_message(pCtx, sLogInfo, nLength, sMessage); slog_display_message(pCtx, sLogInfo, nLength, sMessage);
} }
void slog_display(slog_flag_t eFlag, uint8_t nNewLine, char *pFormat, ...) void slog_display(slog_flag_t eFlag, uint8_t nNewLine, const char* pFormat, ...)
{ {
slog_lock(&g_slog); slog_lock(&g_slog);
slog_config_t *pCfg = &g_slog.config; slog_config_t* pCfg = &g_slog.config;
if ((SLOG_FLAGS_CHECK(g_slog.config.nFlags, eFlag)) && if ((SLOG_FLAGS_CHECK(g_slog.config.nFlags, eFlag)) &&
(g_slog.config.nToScreen || g_slog.config.nToFile)) (g_slog.config.nToScreen || g_slog.config.nToFile))
{ {
slog_context_t ctx; slog_context_t ctx;
slog_get_date(&ctx.date); slog_get_date(&ctx.date);
@@ -396,8 +393,9 @@ void slog_display(slog_flag_t eFlag, uint8_t nNewLine, char *pFormat, ...)
ctx.eFlag = eFlag; ctx.eFlag = eFlag;
ctx.pFormat = pFormat; ctx.pFormat = pFormat;
ctx.nNewLine = nNewLine; ctx.nNewLine = nNewLine;
ctx.nFullColor = pCfg->eColorFormat == SLOG_COLORING_FULL ? 1 : 0;
void(*slog_display_args)(const slog_context_t *pCtx, va_list args); void(*slog_display_args)(const slog_context_t* pCtx, va_list args);
slog_display_args = pCfg->nUseHeap ? slog_display_heap : slog_display_stack; slog_display_args = pCfg->nUseHeap ? slog_display_heap : slog_display_stack;
va_list args; va_list args;
@@ -409,50 +407,33 @@ void slog_display(slog_flag_t eFlag, uint8_t nNewLine, char *pFormat, ...)
slog_unlock(&g_slog); slog_unlock(&g_slog);
} }
const char* slog_version(uint8_t nShort) size_t slog_version(char* pDest, size_t nSize, uint8_t nMin)
{ {
if (nShort) size_t nLength = 0;
{
if (!g_nHaveSlogVerShort)
{
snprintf(g_slogVerShort, sizeof(g_slogVerShort), "%d.%d.%d",
SLOG_VERSION_MAJOR, SLOG_VERSION_MINOR, SLOG_BUILD_NUMBER);
g_nHaveSlogVerShort = 1; /* Version short */
} if (nMin)
nLength = snprintf(pDest, nSize, "%d.%d.%d",
SLOG_VERSION_MAJOR, SLOG_VERSION_MINOR, SLOG_BUILD_NUM);
return g_slogVerShort; /* Version long */
} else
nLength = snprintf(pDest, nSize, "%d.%d build %d (%s)",
SLOG_VERSION_MAJOR, SLOG_VERSION_MINOR, SLOG_BUILD_NUM, __DATE__);
if (!g_nHaveSlogVerLong) return nLength;
{
snprintf(g_slogVerLong, sizeof(g_slogVerLong), "%d.%d build %d (%s)",
SLOG_VERSION_MAJOR, SLOG_VERSION_MINOR, SLOG_BUILD_NUMBER, __DATE__);
g_nHaveSlogVerLong = 1;
}
return g_slogVerLong;
} }
void slog_config_get(slog_config_t *pCfg) void slog_config_get(slog_config_t* pCfg)
{ {
slog_lock(&g_slog); slog_lock(&g_slog);
*pCfg = g_slog.config; *pCfg = g_slog.config;
slog_unlock(&g_slog); slog_unlock(&g_slog);
} }
void slog_config_set(slog_config_t *pCfg) void slog_config_set(slog_config_t* pCfg)
{ {
slog_lock(&g_slog); slog_lock(&g_slog);
slog_config_t *pOldCfg = &g_slog.config;
slog_file_t *pFile = &g_slog.logFile;
if (!pCfg->nToFile ||
strncmp(pOldCfg->sFilePath, pCfg->sFilePath, sizeof(pOldCfg->sFilePath)) ||
strncmp(pOldCfg->sFileName, pCfg->sFileName, sizeof(pOldCfg->sFileName)))
slog_close_file(pFile); /* Log function will open it again if required */
g_slog.config = *pCfg; g_slog.config = *pCfg;
slog_unlock(&g_slog); slog_unlock(&g_slog);
} }
@@ -460,11 +441,11 @@ void slog_config_set(slog_config_t *pCfg)
void slog_enable(slog_flag_t eFlag) void slog_enable(slog_flag_t eFlag)
{ {
slog_lock(&g_slog); slog_lock(&g_slog);
slog_config_t *pCfg = &g_slog.config;
if (!SLOG_FLAGS_CHECK(g_slog.config.nFlags, eFlag))
if (eFlag == SLOG_FLAGS_ALL) pCfg->nFlags = SLOG_FLAGS_ALL; {
else if (!SLOG_FLAGS_CHECK(pCfg->nFlags, eFlag)) pCfg->nFlags |= eFlag; g_slog.config.nFlags |= eFlag;
}
slog_unlock(&g_slog); slog_unlock(&g_slog);
} }
@@ -472,18 +453,19 @@ void slog_enable(slog_flag_t eFlag)
void slog_disable(slog_flag_t eFlag) void slog_disable(slog_flag_t eFlag)
{ {
slog_lock(&g_slog); slog_lock(&g_slog);
slog_config_t *pCfg = &g_slog.config;
if (eFlag == SLOG_FLAGS_ALL) pCfg->nFlags = 0; if (SLOG_FLAGS_CHECK(g_slog.config.nFlags, eFlag))
else if (SLOG_FLAGS_CHECK(pCfg->nFlags, eFlag)) pCfg->nFlags &= ~eFlag; {
g_slog.config.nFlags &= ~eFlag;
}
slog_unlock(&g_slog); slog_unlock(&g_slog);
} }
void slog_separator_set(const char *pFormat, ...) void slog_separator_set(const char* pFormat, ...)
{ {
slog_lock(&g_slog); slog_lock(&g_slog);
slog_config_t *pCfg = &g_slog.config; slog_config_t* pCfg = &g_slog.config;
va_list args; va_list args;
va_start(args, pFormat); va_start(args, pFormat);
@@ -505,10 +487,10 @@ void slog_indent(uint8_t nEnable)
slog_unlock(&g_slog); slog_unlock(&g_slog);
} }
void slog_callback_set(slog_cb_t callback, void *pContext) void slog_callback_set(slog_cb_t callback, void* pContext)
{ {
slog_lock(&g_slog); slog_lock(&g_slog);
slog_config_t *pCfg = &g_slog.config; slog_config_t* pCfg = &g_slog.config;
pCfg->pCallbackCtx = pContext; pCfg->pCallbackCtx = pContext;
pCfg->logCallback = callback; pCfg->logCallback = callback;
slog_unlock(&g_slog); slog_unlock(&g_slog);
@@ -516,10 +498,8 @@ void slog_callback_set(slog_cb_t callback, void *pContext)
void slog_init(const char* pName, uint16_t nFlags, uint8_t nTdSafe) void slog_init(const char* pName, uint16_t nFlags, uint8_t nTdSafe)
{ {
slog_config_t *pCfg = &g_slog.config;
slog_file_t *pFile = &g_slog.logFile;
/* Set up default values */ /* Set up default values */
slog_config_t* pCfg = &g_slog.config;
pCfg->eColorFormat = SLOG_COLORING_TAG; pCfg->eColorFormat = SLOG_COLORING_TAG;
pCfg->eDateControl = SLOG_TIME_ONLY; pCfg->eDateControl = SLOG_TIME_ONLY;
pCfg->pCallbackCtx = NULL; pCfg->pCallbackCtx = NULL;
@@ -528,24 +508,19 @@ void slog_init(const char* pName, uint16_t nFlags, uint8_t nTdSafe)
pCfg->sSeparator[1] = '\0'; pCfg->sSeparator[1] = '\0';
pCfg->sFilePath[0] = '.'; pCfg->sFilePath[0] = '.';
pCfg->sFilePath[1] = '\0'; pCfg->sFilePath[1] = '\0';
pCfg->nKeepOpen = 0;
pCfg->nTraceTid = 0; pCfg->nTraceTid = 0;
pCfg->nToScreen = 1; pCfg->nToScreen = 1;
pCfg->nUseHeap = 0; pCfg->nUseHeap = 0;
pCfg->nToFile = 0; pCfg->nToFile = 0;
pCfg->nIndent = 0; pCfg->nIndent = 0;
pCfg->nRotate = 1;
pCfg->nFlush = 0; pCfg->nFlush = 0;
pCfg->nFlags = nFlags; pCfg->nFlags = nFlags;
const char *pFileName = (pName != NULL) ? pName : SLOG_NAME_DEFAULT; const char* pFileName = (pName != NULL) ? pName : SLOG_NAME_DEFAULT;
snprintf(pCfg->sFileName, sizeof(pCfg->sFileName), "%s", pFileName); snprintf(pCfg->sFileName, sizeof(pCfg->sFileName), "%s", pFileName);
pFile->pHandle = NULL;
pFile->nCurrDay = 0;
#ifdef WIN32 #ifdef WIN32
/* Enable color support */ // Enable color support
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD dwMode = 0; DWORD dwMode = 0;
GetConsoleMode(hOutput, &dwMode); GetConsoleMode(hOutput, &dwMode);
@@ -560,14 +535,8 @@ void slog_init(const char* pName, uint16_t nFlags, uint8_t nTdSafe)
void slog_destroy() void slog_destroy()
{ {
slog_lock(&g_slog);
memset(&g_slog.config, 0, sizeof(g_slog.config));
g_slog.config.pCallbackCtx = NULL; g_slog.config.pCallbackCtx = NULL;
g_slog.config.logCallback = NULL; g_slog.config.logCallback = NULL;
slog_close_file(&g_slog.logFile);
slog_unlock(&g_slog);
if (g_slog.nTdSafe) if (g_slog.nTdSafe)
{ {
+52 -55
View File
@@ -31,12 +31,11 @@ extern "C" {
#include <inttypes.h> #include <inttypes.h>
#include <pthread.h> #include <pthread.h>
#include <stdint.h>
/* SLog version information */ /* SLog version information */
#define SLOG_VERSION_MAJOR 1 #define SLOG_VERSION_MAJOR 1
#define SLOG_VERSION_MINOR 8 #define SLOG_VERSION_MINOR 8
#define SLOG_BUILD_NUMBER 37 #define SLOG_BUILD_NUM 26
/* Supported colors */ /* Supported colors */
#define SLOG_COLOR_NORMAL "\x1B[0m" #define SLOG_COLOR_NORMAL "\x1B[0m"
@@ -74,18 +73,19 @@ extern "C" {
#define SLOG_EMPTY "" #define SLOG_EMPTY ""
#define SLOG_NUL '\0' #define SLOG_NUL '\0'
typedef struct slog_date { typedef struct SLogDate
{
uint16_t nYear; uint16_t nYear;
uint8_t nMonth; uint8_t nMonth;
uint8_t nDay; uint8_t nDay;
uint8_t nHour; uint8_t nHour;
uint8_t nMin; uint8_t nMin;
uint8_t nSec; uint8_t nSec;
uint16_t nUsec; uint8_t nUsec;
} slog_date_t; } slog_date_t;
uint16_t slog_get_usec(); uint8_t slog_get_usec();
void slog_get_date(slog_date_t *pDate); void slog_get_date(slog_date_t* pDate);
/* Log level flags */ /* Log level flags */
typedef enum typedef enum
@@ -100,7 +100,7 @@ typedef enum
SLOG_FATAL = (1 << 7) SLOG_FATAL = (1 << 7)
} slog_flag_t; } slog_flag_t;
typedef int(*slog_cb_t)(const char *pLog, size_t nLength, slog_flag_t eFlag, void *pCtx); typedef int(*slog_cb_t)(const char* pLog, size_t nLength, slog_flag_t eFlag, void* pCtx);
/* Output coloring control flags */ /* Output coloring control flags */
typedef enum typedef enum
@@ -117,25 +117,32 @@ typedef enum
SLOG_DATE_FULL SLOG_DATE_FULL
} slog_date_ctrl_t; } slog_date_ctrl_t;
/* Slog function definitions */ #define slog(...) \
#define slog(...) slog_display(SLOG_NOTAG, 1, __VA_ARGS__) slog_display(SLOG_NOTAG, 1, __VA_ARGS__)
#define slog_note(...) slog_display(SLOG_NOTE, 1, __VA_ARGS__)
#define slog_info(...) slog_display(SLOG_INFO, 1, __VA_ARGS__)
#define slog_warn(...) slog_display(SLOG_WARN, 1, __VA_ARGS__)
#define slog_debug(...) slog_display(SLOG_DEBUG, 1, __VA_ARGS__)
#define slog_error(...) slog_display(SLOG_ERROR, 1, __VA_ARGS__)
#define slog_trace(...) slog_display(SLOG_TRACE, 1, SLOG_THROW_LOCATION __VA_ARGS__)
#define slog_fatal(...) slog_display(SLOG_FATAL, 1, SLOG_THROW_LOCATION __VA_ARGS__)
/* No new line definitions */ #define slogwn(...) \
#define slog_wn(...) slog_display(SLOG_NOTAG, 0, __VA_ARGS__) slog_display(SLOG_NOTAG, 0, __VA_ARGS__)
#define slog_note_wn(...) slog_display(SLOG_NOTE, 0, __VA_ARGS__)
#define slog_info_wn(...) slog_display(SLOG_INFO, 0, __VA_ARGS__) #define slog_note(...) \
#define slog_warn_wn(...) slog_display(SLOG_WARN, 0, __VA_ARGS__) slog_display(SLOG_NOTE, 1, __VA_ARGS__)
#define slog_debug_wn(...) slog_display(SLOG_DEBUG, 0, __VA_ARGS__)
#define slog_error_wn(...) slog_display(SLOG_ERROR, 0, __VA_ARGS__) #define slog_info(...) \
#define slog_trace_wn(...) slog_display(SLOG_TRACE, 0, SLOG_THROW_LOCATION __VA_ARGS__) slog_display(SLOG_INFO, 1, __VA_ARGS__)
#define slog_fatal_wn(...) slog_display(SLOG_FATAL, 0, SLOG_THROW_LOCATION __VA_ARGS__)
#define slog_warn(...) \
slog_display(SLOG_WARN, 1, __VA_ARGS__)
#define slog_debug(...) \
slog_display(SLOG_DEBUG, 1, __VA_ARGS__)
#define slog_error(...) \
slog_display(SLOG_ERROR, 1, __VA_ARGS__)
#define slog_trace(...) \
slog_display(SLOG_TRACE, 1, SLOG_THROW_LOCATION __VA_ARGS__)
#define slog_fatal(...) \
slog_display(SLOG_FATAL, 1, SLOG_THROW_LOCATION __VA_ARGS__)
/* Short name definitions */ /* Short name definitions */
#define slogn(...) slog_note(__VA_ARGS__) #define slogn(...) slog_note(__VA_ARGS__)
@@ -146,50 +153,40 @@ typedef enum
#define slogt(...) slog_trace(__VA_ARGS__) #define slogt(...) slog_trace(__VA_ARGS__)
#define slogf(...) slog_fatal(__VA_ARGS__) #define slogf(...) slog_fatal(__VA_ARGS__)
/* Short name definitions without new line */ typedef struct SLogConfig
#define slogn_wn(...) slog_note_wn(__VA_ARGS__) {
#define slogi_wn(...) slog_info_wn(__VA_ARGS__) slog_date_ctrl_t eDateControl; // Display output with date format
#define slogw_wn(...) slog_warn_wn(__VA_ARGS__) slog_coloring_t eColorFormat; // Output color format control
#define slogd_wn(...) slog_debug_wn( __VA_ARGS__) slog_cb_t logCallback; // Log callback to collect logs
#define sloge_wn(...) slog_error_wn( __VA_ARGS__) void* pCallbackCtx; // Data pointer passed to log callback
#define slogt_wn(...) slog_trace_wn(__VA_ARGS__)
#define slogf_wn(...) slog_fatal_wn(__VA_ARGS__)
typedef struct SLogConfig { uint8_t nTraceTid; // Trace thread ID and display in output
slog_date_ctrl_t eDateControl; // Display output with date format uint8_t nToScreen; // Enable screen logging
slog_coloring_t eColorFormat; // Output color format control uint8_t nUseHeap; // Use dynamic allocation
slog_cb_t logCallback; // Log callback to collect logs uint8_t nToFile; // Enable file logging
void* pCallbackCtx; // Data pointer passed to log callback uint8_t nIndent; // Enable indentations
uint8_t nFlush; // Flush stdout after screen log
uint8_t nKeepOpen; // Keep file handle open for next file writes uint16_t nFlags; // Allowed log level flags
uint8_t nTraceTid; // Trace thread ID and display in output
uint8_t nToScreen; // Enable screen logging
uint8_t nUseHeap; // Use dynamic allocation
uint8_t nToFile; // Enable file logging
uint8_t nIndent; // Enable indentations
uint8_t nRotate; // Enable log rotation
uint8_t nFlush; // Flush stdout after screen log
uint16_t nFlags; // Allowed log level flags
char sSeparator[SLOG_NAME_MAX]; // Separator between info and log char sSeparator[SLOG_NAME_MAX]; // Separator between info and log
char sFileName[SLOG_NAME_MAX]; // Output file name for logs char sFileName[SLOG_NAME_MAX]; // Output file name for logs
char sFilePath[SLOG_PATH_MAX]; // Output file path for logs char sFilePath[SLOG_PATH_MAX]; // Output file path for logs
} slog_config_t; } slog_config_t;
const char* slog_version(uint8_t nShort); size_t slog_version(char* pDest, size_t nSize, uint8_t nMin);
void slog_config_get(slog_config_t *pCfg); void slog_config_get(slog_config_t* pCfg);
void slog_config_set(slog_config_t *pCfg); void slog_config_set(slog_config_t* pCfg);
void slog_separator_set(const char *pFormat, ...); void slog_separator_set(const char* pFormat, ...);
void slog_callback_set(slog_cb_t callback, void *pContext); void slog_callback_set(slog_cb_t callback, void* pContext);
void slog_indent(uint8_t nEnable); void slog_indent(uint8_t nEnable);
void slog_enable(slog_flag_t eFlag); void slog_enable(slog_flag_t eFlag);
void slog_disable(slog_flag_t eFlag); void slog_disable(slog_flag_t eFlag);
void slog_init(const char* pName, uint16_t nFlags, uint8_t nTdSafe); void slog_init(const char* pName, uint16_t nFlags, uint8_t nTdSafe);
void slog_display(slog_flag_t eFlag, uint8_t nNewLine, char *pFormat, ...); void slog_display(slog_flag_t eFlag, uint8_t nNewLine, const char* pFormat, ...);
void slog_destroy(); // Required only if (nTdSafe > 0 || nKeepOpen > 0) void slog_destroy(); // Needed only if the slog_init() function argument nTdSafe > 0
#ifdef __cplusplus #ifdef __cplusplus
} }
+2 -2
View File
@@ -5,8 +5,8 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include "../src/monocoque/simulatorapi/simapi/simapi/simdata.h" #include "../src/monocoque/simulatorapi/simdata.h"
#include "../src/monocoque/simulatorapi/simapi/simapi/test.h" #include "../src/monocoque/simulatorapi/test.h"
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
+2 -2
View File
@@ -6,8 +6,8 @@
#include <string.h> #include <string.h>
#include <termios.h> #include <termios.h>
#include "../src/monocoque/simulatorapi/simapi/simapi/simdata.h" #include "../src/monocoque/simulatorapi/simdata.h"
#include "../src/monocoque/simulatorapi/simapi/simapi/test.h" #include "../src/monocoque/simulatorapi/test.h"
#define DATA "Hello, World! From PID %d" #define DATA "Hello, World! From PID %d"
+2 -2
View File
@@ -5,8 +5,8 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include "../src/monocoque/simulatorapi/simapi/simapi/simdata.h" #include "../src/monocoque/simulatorapi/simdata.h"
#include "../src/monocoque/simulatorapi/simapi/simapi/test.h" #include "../src/monocoque/simulatorapi/test.h"
#define DATA "Hello, World! From PID %d" #define DATA "Hello, World! From PID %d"
-20
View File
@@ -1,20 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <errno.h>
void display(char* prog, char* bytes, int n);
int main(void)
{
const char* name = "acpmf_physics"; // file name
shm_unlink(name);
}
+32 -86
View File
@@ -2,15 +2,21 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <libserialport.h> #include <libserialport.h>
#include "../src/arduino/shiftlights/shiftlights.h" #include "../src/monocoque/simulatorapi/simdata.h"
/* Helper function for error handling. */ /* Helper function for error handling. */
int check(enum sp_return result); int check(enum sp_return result);
int main() int main()
{ {
SimData sd;
sd.maxrpm = 6500;
sd.rpms = 0;
sd.altitude = 10;
sd.gear = 1;
sd.velocity = 74;
char* port_name = "/dev/simdev0"; char* port_name = "/dev/ttyACM0";
/* The ports we will use. */ /* The ports we will use. */
struct sp_port* port; struct sp_port* port;
@@ -22,110 +28,50 @@ int main()
printf("Opening port.\n"); printf("Opening port.\n");
check(sp_open(port, SP_MODE_READ_WRITE)); check(sp_open(port, SP_MODE_READ_WRITE));
printf("Setting port to 115200 8N1, no flow control.\n"); printf("Setting port to 9600 8N1, no flow control.\n");
check(sp_set_baudrate(port, 115200)); check(sp_set_baudrate(port, 9600));
check(sp_set_bits(port, 8)); check(sp_set_bits(port, 8));
check(sp_set_parity(port, SP_PARITY_NONE)); check(sp_set_parity(port, SP_PARITY_NONE));
check(sp_set_stopbits(port, 1)); check(sp_set_stopbits(port, 1));
check(sp_set_flowcontrol(port, SP_FLOWCONTROL_NONE)); check(sp_set_flowcontrol(port, SP_FLOWCONTROL_NONE));
ShiftLightsData sd; while ( sd.rpms <= sd.maxrpm )
size_t bufsize1 = 11;
size_t recv_bufsize1 = 5;
char recv_buf1[recv_bufsize1];
char bytes1[bufsize1];
for(int j = 0; j < bufsize1; j++)
{ {
bytes1[j] = 0x00;
}
bytes1[0] = 0xff;
bytes1[1] = 0xff;
bytes1[2] = 0xff;
bytes1[3] = 0xff;
bytes1[4] = 0xff;
bytes1[5] = 0xff;
bytes1[6] = 0x6c;
bytes1[7] = 0x65;
bytes1[8] = 0x64;
bytes1[9] = 0x73;
bytes1[10] = 0x63;
int result = 0;
unsigned int timeout = 2000;
result = check(sp_blocking_write(port, &bytes1, bufsize1, timeout));
result = check(sp_blocking_read(port, &recv_buf1, recv_bufsize1, timeout));
char numstr[4];
for(int j = 0; j < 4; j++)
{
numstr[j] = '\0';
}
for(int j = 0; j < recv_bufsize1; j++)
{
if(recv_buf1[j] != 0 && recv_buf1[j] != 0x0d && recv_buf1[j] != 0x0a)
{
numstr[j] = recv_buf1[j];
}
}
int numlights = atoi(numstr);
printf("numlights is %i\n", numlights);
//printf("%x\n", recv_buf[0]);
//printf("%x\n", recv_buf[1]);
//printf("%x\n", recv_buf[2]);
//printf("%x\n", recv_buf[3]);
//printf("%x\n", recv_buf[4]);
size_t bufsize = (numlights * 3) + 14;
char bytes[bufsize];
for(int j = 0; j < bufsize; j++)
{
bytes[j] = 0x00;
}
bytes[0] = 0xff;
bytes[1] = 0xff;
bytes[2] = 0xff;
bytes[3] = 0xff;
bytes[4] = 0xff;
bytes[5] = 0xff;
bytes[6] = 0x73;
bytes[7] = 0x6c;
bytes[8] = 0x65;
bytes[9] = 0x64;
bytes[10] = 0x73;
bytes[bufsize-1] = 0xfd;
bytes[bufsize-2] = 0xfe;
bytes[bufsize-3] = 0xff;
for( int i = 0; i < numlights; i++) unsigned int timeout = 2000;
{
bytes[(i * 3) + 11 + 1] = 0xff; /* On success, sp_blocking_write() and sp_blocking_read()
* return the number of bytes sent/received before the
* timeout expired. We'll store that result here. */
int result;
int size = sizeof(SimData);
/* Send data. */ /* Send data. */
result = check(sp_blocking_write(port, &bytes, bufsize, timeout)); result = check(sp_blocking_write(port, &sd, size, timeout));
/* Check whether we sent all of the data. */ /* Check whether we sent all of the data. */
if (result == bufsize) if (result == size)
{ {
printf("Sent %d bytes successfully, %i lit leds.\n", bufsize, numlights); printf("Sent %d bytes successfully, %i rpm.\n", size, sd.rpms);
} }
else else
{ {
printf("Timed out, %d/%d bytes sent.\n", result, bufsize); printf("Timed out, %d/%d bytes sent.\n", result, size);
} }
sd.rpms += 1000;
if ( sd.rpms == sd.maxrpm + 1000 )
{
sd.rpms = 0;
}
if ( sd.rpms > sd.maxrpm )
{
sd.rpms = sd.maxrpm;
}
sleep(2); sleep(1);
} }
for( int i = 0; i < numlights; i++)
{
bytes[(i * 3) + 11 + 1] = 0x00;
}
result = check(sp_blocking_write(port, &bytes, bufsize, timeout));
check(sp_close(port)); check(sp_close(port));
sp_free_port(port); sp_free_port(port);
BIN
View File
Binary file not shown.
-47
View File
@@ -1,47 +0,0 @@
# Maintainer: Paul Jones <paul@spacefreak18.xyz>
_reponame=monocoque
pkgname=monocoque-git
pkgver=0.1.0r94
pkgrel=2
pkgdesc="Device Manager for Racing Sims"
arch=('x86_64')
url="https://github.com/spacefreak18/monocoque"
license=('GPL3')
depends=(
hidapi
libserialport
libxml2
argtable
libconfig
libpulse
libxdg-basedir
libuv
)
makedepends=(
git
cmake
)
source=(
git+https://github.com/spacefreak18/monocoque
)
sha256sums=(
'SKIP'
)
pkgver() {
cd "$srcdir/$_reponame"
git describe --long --tags | cut -d "-" -f 1-2 | tr "-" "r"
}
package() {
cd "$srcdir/$_reponame" || exit 1
git submodule sync --recursive
git submodule update --init --recursive
mkdir -p build
cd build
cmake -DUSE_PULSEAUDIO=yes ..
make
mkdir -p "${pkgdir}/usr/bin/"
cp "$srcdir/$_reponame"/build/$_reponame "${pkgdir}/usr/bin/$_reponame"
}
-44
View File
@@ -1,44 +0,0 @@
# Maintainer: Paul Jones <paul@spacefreak18.xyz>
_reponame=monocoque
pkgname=monocoque
pkgver=0.2.0
pkgrel=4
pkgdesc="Device Manager for Racing Sims"
arch=('x86_64')
url="https://github.com/spacefreak18/monocoque"
license=('GPL3')
_commit=12509e9709871afcb3ae264823b4a7d3c3b71bf7
depends=(
hidapi
libserialport
libxml2
argtable
libconfig
libpulse
libxdg-basedir
libuv
)
makedepends=(
git
cmake
)
source=("git+https://github.com/spacefreak18/monocoque.git#commit=$_commit")
sha256sums=(
'SKIP'
)
package() {
cd "$srcdir/$_reponame" || exit 1
git submodule sync --recursive
git submodule update --init --recursive
mkdir -p build
cd build
cmake -Wno-dev -DUSE_PULSEAUDIO=yes ..
make
mkdir -p "${pkgdir}/usr/bin/"
cp "$srcdir/$_reponame"/build/monocoque "${pkgdir}/usr/bin/monocoque"
install -D -m644 "$srcdir/$_reponame"/LICENSE.rst -t "${pkgdir}/usr/share/licenses/$_reponame"
}
-4
View File
@@ -1,5 +1 @@
SUBSYSTEMS=="usb",ATTRS{product}=="Rev Burner",GROUP="input",TAG+="uaccess" SUBSYSTEMS=="usb",ATTRS{product}=="Rev Burner",GROUP="input",TAG+="uaccess"
SUBSYSTEM=="tty", ATTRS{idVendor}=="2341", ATTRS{idProduct}=="0043", ATTRS{serial}=="75033303335351A080F0", SYMLINK+="simdev0", GROUP="input", TAG+="uaccess"
SUBSYSTEM=="tty", ATTRS{idVendor}=="2341", ATTRS{idProduct}=="0043", ATTRS{serial}=="242303138313514131F1", SYMLINK+="simdev1", GROUP="input", TAG+="uaccess"