serial library in c++ for godot
initial commit
| -rw-r--r-- | .gitattributes | 1 | ||||
| -rw-r--r-- | .gitignore | 5 | ||||
| -rw-r--r-- | .gitmodules | 5 | ||||
| -rw-r--r-- | LICENSE | 21 | ||||
| -rw-r--r-- | README.md | 10 | ||||
| -rw-r--r-- | SConstruct | 61 | ||||
| -rw-r--r-- | bin/gdserial.gdnlib | 14 | ||||
| -rw-r--r-- | bin/gdserial.gdns | 9 | ||||
| -rwxr-xr-x | bin/libgdserial.so | 3 | ||||
| m--------- | godot-cpp | 0 | ||||
| -rw-r--r-- | serial.gd | 27 | ||||
| -rw-r--r-- | src/gdlibrary.cpp | 16 | ||||
| -rw-r--r-- | src/gdserial.cpp | 111 | ||||
| -rw-r--r-- | src/gdserial.h | 31 |
14 files changed, 314 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..c3ad15c --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.so filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fdafaea --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +libraries/ +.vscode/ +car_driver/godot/car_driver/.import/ +*.os +*.dblite diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..ff1ffe0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,5 @@ + +[submodule "godot-cpp"] + path = godot-cpp + url = https://github.com/godotengine/godot-cpp + branch = 3.x @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 bendn + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..de95524 --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# gdcereal + +### build steps: + +``` +scons +``` + +Inspired by: +https://github.com/valentegamedev/arduino_godot diff --git a/SConstruct b/SConstruct new file mode 100644 index 0000000..e07e8ea --- /dev/null +++ b/SConstruct @@ -0,0 +1,61 @@ +#!python +import os +import subprocess + +opts = Variables([], ARGUMENTS) + +# Gets the standard flags CC, CCX, etc. +env = DefaultEnvironment() + +# Define our options +opts.Add(EnumVariable('target', "Compilation target", + 'debug', ['d', 'debug', 'r', 'release'])) +opts.Add(BoolVariable('use_llvm', "Use the LLVM / Clang compiler", 'no')) +opts.Add(PathVariable('target_path', + 'The path where the lib is installed.', 'bin/')) +opts.Add(PathVariable('target_name', 'The library name.', + 'libgdserial', PathVariable.PathAccept)) + +# Local dependency paths, adapt them to your setup +godot_headers_path = "godot-cpp/godot-headers/" +cpp_bindings_path = "godot-cpp/" +cpp_library = "libgodot-cpp.linux" + +# only support 64 at this time.. +bits = 64 + +# Updates the environment with the option variables. +opts.Update(env) + +# Process some arguments +if env['use_llvm']: + env['CC'] = 'clang' + env['CXX'] = 'clang++' + + +if env['target'] in ('debug', 'd'): + cpp_library += '.debug' + env.Append(CCFLAGS=['-fPIC', '-g3', '-Og', '-std=c++17']) +else: + env.Append(CCFLAGS=['-fPIC', '-g', '-O3', '-std=c++17']) + cpp_library += '.release' + +cpp_library += '.' + str(bits) + +# make sure our binding library is properly includes +env.Append(CPPPATH=['.', godot_headers_path, cpp_bindings_path + 'include/', + cpp_bindings_path + 'include/core/', cpp_bindings_path + 'include/gen/']) +env.Append(LIBPATH=[cpp_bindings_path + 'bin/']) +env.Append(LIBS=[cpp_library]) + +# tweak this if you want to use different folders, or more folders, to store your source code in. +env.Append(CPPPATH=['src/']) +sources = Glob('src/*.cpp') + +library = env.SharedLibrary( + target=env['target_path'] + env['target_name'], source=sources) + +Default(library) + +# Generates help for the -h scons option. +Help(opts.GenerateHelpText(env)) diff --git a/bin/gdserial.gdnlib b/bin/gdserial.gdnlib new file mode 100644 index 0000000..b3ed6df --- /dev/null +++ b/bin/gdserial.gdnlib @@ -0,0 +1,14 @@ +[general] + +singleton=false +load_once=true +symbol_prefix="godot_" +reloadable=false + +[entry] + +X11.64="res://bin/libgdserial.so" + +[dependencies] + +X11.64=[ ] diff --git a/bin/gdserial.gdns b/bin/gdserial.gdns new file mode 100644 index 0000000..1243df9 --- /dev/null +++ b/bin/gdserial.gdns @@ -0,0 +1,9 @@ +[gd_resource type="NativeScript" load_steps=2 format=2] + +[ext_resource path="res://bin/gdserial.gdnlib" type="GDNativeLibrary" id=1] + +[resource] + +resource_name = "gdserial" +class_name = "GDSerial" +library = ExtResource( 1 )
\ No newline at end of file diff --git a/bin/libgdserial.so b/bin/libgdserial.so new file mode 100755 index 0000000..b3f1910 --- /dev/null +++ b/bin/libgdserial.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7bf17a8fd57ea019ebd237a18f22395a46561ebd6a4a285745753e728e64d182 +size 3335144 diff --git a/godot-cpp b/godot-cpp new file mode 160000 +Subproject 666a378336a45d01eed2d9172b9a2990bc3d555 diff --git a/serial.gd b/serial.gd new file mode 100644 index 0000000..3deecc7 --- /dev/null +++ b/serial.gd @@ -0,0 +1,27 @@ +extends Reference + +const Serial = preload("res://bin/gdserial.gdns") +var serial: Serial + +signal recieved() + +const baud_rate := 9600 +const endline := "\n" + + +#@param text the text to send +func write(text: String) -> void: + serial.send(text) + + +func create_serial(): + if serial: + serial.end() + serial = Serial.new() + serial.start("/dev/ttyACM0", baud_rate) + + +func _process(delta): + if serial.get_available() > 0: + var data = serial.read_string() + emit_signal("recieved", data) diff --git a/src/gdlibrary.cpp b/src/gdlibrary.cpp new file mode 100644 index 0000000..a7c2360 --- /dev/null +++ b/src/gdlibrary.cpp @@ -0,0 +1,16 @@ +#include "gdserial.h" + +extern "C" void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *o) { + godot::Godot::gdnative_init(o); +} + +extern "C" void GDN_EXPORT +godot_gdnative_terminate(godot_gdnative_terminate_options *o) { + godot::Godot::gdnative_terminate(o); +} + +extern "C" void GDN_EXPORT godot_nativescript_init(void *handle) { + godot::Godot::nativescript_init(handle); + + godot::register_class<godot::GDSerial>(); +}
\ No newline at end of file diff --git a/src/gdserial.cpp b/src/gdserial.cpp new file mode 100644 index 0000000..3b5a9ea --- /dev/null +++ b/src/gdserial.cpp @@ -0,0 +1,111 @@ +#include "gdserial.h" + +#define DEBUG_LOG 0 + +#include <cstdio> +#include <errno.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <termios.h> +#include <unistd.h> + +using namespace godot; + +void GDSerial::_register_methods() { + register_method("start", &GDSerial::start); + register_method("end", &GDSerial::end); + register_method("send", &GDSerial::send); + register_method("read_string", &GDSerial::read_string); + register_method("get_available", &GDSerial::get_available); +} + +GDSerial::GDSerial() {} + +GDSerial::~GDSerial() {} + +void GDSerial::_init() {} + +bool GDSerial::start(String port, int baud_rate) { + const char *port_c = port.utf8().get_data(); +#if DEBUG_LOG + printf("GDSerial: Trying to open %s at baudrate %s.\n", port_c, baud_rate); +#endif + serial_port = open(port_c, O_RDWR | O_NOCTTY | O_NDELAY); + struct termios tty; + struct termios tty_old; + memset(&tty, 0, sizeof tty); + if (tcgetattr(serial_port, &tty) != 0) { +#if DEBUG_LOG + printf("GDSerial: Failed to get current serial parameters.\n"); +#endif + return false; + } + tty_old = tty; + cfsetospeed(&tty, (speed_t)baud_rate); + cfsetispeed(&tty, (speed_t)baud_rate); + + tty.c_cflag &= ~PARENB; + tty.c_cflag &= ~CSTOPB; + tty.c_cflag |= CS8; + tty.c_cflag &= ~CRTSCTS; + tty.c_cflag |= CREAD | CLOCAL; + tty.c_lflag &= ~ICANON; + tty.c_lflag &= ~ECHO; + tty.c_lflag &= ~ECHOE; + tty.c_lflag &= ~ECHONL; + tty.c_lflag &= ~ISIG; + tty.c_iflag &= ~(IXON | IXOFF | IXANY); + tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); + tty.c_oflag &= ~OPOST; + tty.c_oflag &= ~ONLCR; + tty.c_cc[VTIME] = 0; + tty.c_cc[VMIN] = 0; + + cfmakeraw(&tty); + tcflush(serial_port, TCIFLUSH); + + if (tcsetattr(serial_port, TCSANOW, &tty) != 0) { +#if DEBUG_LOG + printf("GDSerial: Could not set serial port parameters.\n"); +#endif + return false; + } + fcntl(serial_port, F_SETFL, FNDELAY); +#if DEBUG_LOG + printf("GDSerial: %s opened.\n", port_c); +#endif + return true; +} + +void GDSerial::end() { + + close(serial_port); + serial_port = 0; + +#if DEBUG_LOG + printf("GDSerial: Serial port closed.\n"); +#endif +} + +void GDSerial::send(String text) { + const char *text_c = text.utf8().get_data(); + write(serial_port, text_c, text.length()); +} + +String GDSerial::read_string() { + String text = ""; + + unsigned char buf[4096]; + int n; + n = read(serial_port, &buf, sizeof(buf)); + for (int x = 0; x < n; x++) { + text += buf[x]; + } + return text; +} + +int GDSerial::get_available() { + int bytes_available = 0; + ioctl(serial_port, FIONREAD, &bytes_available); + return bytes_available; +} diff --git a/src/gdserial.h b/src/gdserial.h new file mode 100644 index 0000000..dd8c9e1 --- /dev/null +++ b/src/gdserial.h @@ -0,0 +1,31 @@ +#ifndef GDSERIAL_H +#define GDSERIAL_H + +#include <Godot.hpp> + +namespace godot { + +class GDSerial : public Reference { + GODOT_CLASS(GDSerial, Reference) + +private: + int serial_port; + +public: + static void _register_methods(); + + GDSerial(); + ~GDSerial(); + + void _init(); // our initializer called by Godot + + bool start(String port, int baud_rate); + void end(); + void send(String text); + int get_available(); + String read_string(); +}; + +} // namespace godot + +#endif |