serial library in c++ for godot
initial commit
bendn 2022-07-07
commit 6704d07
-rw-r--r--.gitattributes1
-rw-r--r--.gitignore5
-rw-r--r--.gitmodules5
-rw-r--r--LICENSE21
-rw-r--r--README.md10
-rw-r--r--SConstruct61
-rw-r--r--bin/gdserial.gdnlib14
-rw-r--r--bin/gdserial.gdns9
-rwxr-xr-xbin/libgdserial.so3
m---------godot-cpp0
-rw-r--r--serial.gd27
-rw-r--r--src/gdlibrary.cpp16
-rw-r--r--src/gdserial.cpp111
-rw-r--r--src/gdserial.h31
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
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..5e69554
--- /dev/null
+++ b/LICENSE
@@ -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