Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task 16 implementation. #63

Open
wants to merge 1 commit into
base: devel
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/bind/FrameBuffer.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class FrameBuffer : public Reference {
int get_height() noexcept;
int get_freq() noexcept;
bool write_rgb888(Ref<Image> img);
PoolByteArray read_rgb888();
};
}; // namespace godot

Expand Down
3 changes: 2 additions & 1 deletion project/Global.gd
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ var _classes: Array = [
preload("res://src/attachments/Gyroscope.gd"),
preload("res://src/utilities/sensors/odometer/Odometer.gd"),
RayCar, RayWheel, UltraSonic,
preload("res://src/attachments/Odometer.gd")]
preload("res://src/attachments/Odometer.gd"),
ScreenBuffer]

var classes: Dictionary = {}

Expand Down
37 changes: 37 additions & 0 deletions project/share/library_patches/arduino_mkrrgb/src/MKRRGBMatrix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// Created by danie on 2021-11-02.
//

Comment on lines +1 to +4
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can remove just this

#include "MKRRGBMatrix.h"

RGBMatrixClass MATRIX;

RGBMatrixClass::RGBMatrixClass()
: ArduinoGraphics(RGB_MATRIX_WIDTH, RGB_MATRIX_HEIGHT), framebufferAccessor() {}

RGBMatrixClass::~RGBMatrixClass() {}

int RGBMatrixClass::begin() {
return framebufferAccessor.begin(RGB_MATRIX_WIDTH, RGB_MATRIX_HEIGHT, PIXEL_FORMAT, FPS);
}

void RGBMatrixClass::end() { framebufferAccessor.end(); }

void RGBMatrixClass::brightness(uint8_t brightness) {}

void RGBMatrixClass::beginDraw() {
ArduinoGraphics::beginDraw();
framebufferAccessor.read(buf);
}

void RGBMatrixClass::endDraw() {
ArduinoGraphics::endDraw();
framebufferAccessor.write(buf);
}

void RGBMatrixClass::set(int x, int y, uint8_t r, uint8_t g, uint8_t b) {
int index = (y * RGB_MATRIX_WIDTH + x) * (BITS_PER_PIXEL / CHAR_BIT);
buf[index] = static_cast<std::byte>(r);
buf[index + 1] = static_cast<std::byte>(g);
buf[index + 2] = static_cast<std::byte>(b);
}
41 changes: 41 additions & 0 deletions project/share/library_patches/arduino_mkrrgb/src/MKRRGBMatrix.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// Created by danie on 2021-11-02.
//

#ifndef MKRRGBMATRIX_H
#define MKRRGBMATRIX_H

#include <cstddef>
#include <cstdint>
#include <ArduinoGraphics.h>
#include <FramebufferAccess.h>
#include "SMCE_dll.hpp"
Comment on lines +11 to +12
Copy link
Collaborator

@RuthgerD RuthgerD Nov 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ideally these shoudnt go in the public header to avoid leaking stuff we dont want the user to stumble upon.
you can forward declare FramebufferAccess in the header and then store it as a pointer or unique_ptr. this way the definition is hidden

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(And the class name should be prefixed with SMCE__ so as to not conflict with user-defined identifiers)


#define RGB_MATRIX_WIDTH 640
#define RGB_MATRIX_HEIGHT 480
#define PIXEL_FORMAT SMCE_Pixel_Format::RGB888
#define BITS_PER_PIXEL 24
#define FPS 60
Comment on lines +14 to +18
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt all of these are part of the MKRRGB API. If not, they should either be deleted, or prefixed with SMCE__


class RGBMatrixClass : public ArduinoGraphics {
private:
FramebufferAccess framebufferAccessor;
std::byte buf[(BITS_PER_PIXEL * RGB_MATRIX_HEIGHT * RGB_MATRIX_WIDTH) / CHAR_BIT];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::byte is relatively new, use uint8_t instead to be more compatible


public:
RGBMatrixClass();
virtual ~RGBMatrixClass();

int begin();
void end();

void brightness(uint8_t brightness);

virtual void beginDraw();
virtual void endDraw();

virtual void set(int x, int y, uint8_t r, uint8_t g, uint8_t b);
};

extern RGBMatrixClass MATRIX;
#endif // MKRRGBMATRIX_H
96 changes: 96 additions & 0 deletions project/src/attachments/ScreenBuffer.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
class_name ScreenBuffer
extends Spatial

onready var mesh: MeshInstance = MeshInstance.new()
onready var screen: MeshInstance = MeshInstance.new()
var img: Image = Image.new()
var texture: ImageTexture = ImageTexture.new()

func extern_class_name():
return "ScreenBuffer"

export var pin = 0
export var display_width = 0.34
export var display_height = 0.2
var resolution = Vector2(0, 0) # Base resolution (for MKRRGBMAtrix)
var image_buf = null
var fps = 1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should probably be 0

var aspect_ratio = 1
var view = null
var timer: Timer = Timer.new()

func _ready():
timer.connect("timeout", self, "_on_frame")
timer.autostart = true
add_child(timer)

img.create(resolution.x, resolution.y, false, Image.FORMAT_RGB8)
img.fill(Color.black)
_create_texture()

mesh.mesh = CubeMesh.new()
_update_mesh_size()
mesh.rotate_y(PI)

screen.mesh = PlaneMesh.new()
screen.scale_object_local(Vector3(0.9, 0.9, 0.9))
screen.rotate_x(PI/2)
screen.translate(Vector3(0, 1.5, 0))
screen.material_override = SpatialMaterial.new()
screen.material_override.albedo_texture = texture

mesh.add_child(screen)
add_child(mesh)

func _on_frame() -> void:
if ! view || ! view.is_valid():
return

var new_image_buf = view.framebuffers(pin).read_rgb888(img)
if new_image_buf != image_buf:
img.create_from_data(resolution.x, resolution.y,
false, Image.FORMAT_RGB8, new_image_buf)
_create_texture()
image_buf = new_image_buf

func _physics_process(delta):
var buffer = view.framebuffers(pin)
var new_res = Vector2(buffer.get_width(), buffer.get_height())
var new_fps = buffer.get_freq()

if new_fps != fps and new_fps != 0:
timer.wait_time = 1.0/new_fps
fps = new_fps

if new_res != resolution and new_res.x != 0 and new_res.y != 0:
resolution = new_res
aspect_ratio = float(resolution.x) / resolution.y
_update_mesh_size()


func _create_texture():
if texture.get_size() != resolution:
texture.create_from_image(img, 0)
else:
texture.set_data(img)

func _update_mesh_size():
if aspect_ratio >= 1:
mesh.scale = Vector3(display_width, display_width / aspect_ratio, 0.025)
else:
mesh.scale = Vector3(display_height * aspect_ratio, display_height, 0.025)

func set_view(_view: Node) -> void:
if ! _view:
return
view = _view

func visualize() -> Control:
var visualizer = ScreenBufferVisualizer.new()
visualizer.display_node(self, "visualize_content")
return visualizer


func visualize_content() -> Array:
var text = " Resolution: %dx%d" % [resolution.x, resolution.y]
return [texture, aspect_ratio, text]
Comment on lines +94 to +96
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since ScreenBufferVisualizer is very specific this method is not needed and can be put inside the visualizer class

Copy link
Contributor

@danielolssonIT danielolssonIT Nov 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we put setters in ScreenBufferVisualizer and set the texture, aspect_ratio, and text value from the ScreenBuffer's _physics_process() method instead?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't ScreenBufferVisualizer already take self ? it can just directly access the fields here

3 changes: 3 additions & 0 deletions project/src/objects/ray_car/RayCar.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ transform = Transform( -4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, 0.974,
[node name="Back" type="Position3D" parent="AttachmentSlots"]
transform = Transform( -1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0.4, 1.8 )

[node name="Logo" type="Position3D" parent="AttachmentSlots"]
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.00163135, 0.0371331, -2.20274 )

[node name="BuiltinAttachments" type="Spatial" parent="."]

[node name="Left BrushedMotor" type="Node" parent="BuiltinAttachments"]
Expand Down
71 changes: 71 additions & 0 deletions project/src/ui/node_visualizer/ScreenBufferVisualizer.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#
# ScreenBufferVisualizer.gd
# Copyright 2021 ItJustWorksTM
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

class_name ScreenBufferVisualizer
extends VBoxContainer

var _node: Node = null
var _visual_func: String = ""

var text_display: Label = Label.new()
var image_display: TextureRect = TextureRect.new()
var viewport: Viewport = Viewport.new()
var viewport_container: ViewportContainer = ViewportContainer.new()
Comment on lines +26 to +27
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we using a viewport here?


func display_node(node: Node, visual_func: String) -> bool:
if ! node || ! node.has_method(visual_func):
return false
_node = node
_visual_func = visual_func

add_child(viewport_container)
viewport_container.add_child(viewport)
viewport.add_child(image_display)

# Needed to make sure that the viewport does not swallow clicks meant for the collapsable element
viewport.set_disable_input(true)

add_child(text_display)

return true

func _process(_delta: float) -> void:
if ! _node:
return

# values[0] = texture
# values[1] = aspect ratio of image
# values[2] = text
var values = _node.call(_visual_func)

image_display.texture = values[0]

# Set max width of viewport and use aspect ration to determine height
var aspect_ratio = values[1]
if aspect_ratio == 0:
viewport.size = Vector2(0, 0)
else:
viewport.size = Vector2(290, 290 * (1.0/aspect_ratio))

# Expanding the display to fit the viewport
image_display.set_anchors_and_margins_preset(Control.PRESET_TOP_LEFT, Control.PRESET_MODE_MINSIZE, 0)
image_display.rect_min_size = viewport.size
image_display.expand = true
#image_display.stretch_mode = TextureRect.STRETCH_SCALE

text_display.text = values[2]

15 changes: 15 additions & 0 deletions src/bind/FrameBuffer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ void FrameBuffer::_register_methods() {
register_method("get_height", &FrameBuffer::get_height);
register_method("get_freq", &FrameBuffer::get_freq);
register_method("write_rgb888", &FrameBuffer::write_rgb888);
register_method("read_rgb888", &FrameBuffer::read_rgb888);
}

bool FrameBuffer::exists() { return frame_buf.exists(); }
Expand All @@ -50,3 +51,17 @@ bool FrameBuffer::write_rgb888(Ref<Image> img) {

return frame_buf.write_rgb888(byte_span);
}

PoolByteArray FrameBuffer::read_rgb888() {
auto bytes = PoolByteArray{};

bytes.resize(get_height() * get_width() * 3);

const auto byte_span =
std::span{reinterpret_cast<std::byte*>(bytes.write().ptr()), static_cast<size_t>(bytes.size())};

// TODO: maybe check success :|
frame_buf.read_rgb888(byte_span);

return bytes; // pray for some kind of return value optimization
}
46 changes: 31 additions & 15 deletions src/bind/Sketch.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,37 @@ void Sketch::_register_methods() {
#undef U

void Sketch::init(String src, String home_dir) {
sketch =
smce::Sketch{std_str(src),
{.fqbn = "arduino:sam:arduino_due_x",
.legacy_preproc_libs = {smce::SketchConfig::ArduinoLibrary{"[email protected]"},
smce::SketchConfig::ArduinoLibrary{"[email protected]"},
smce::SketchConfig::ArduinoLibrary{"[email protected]"},
smce::SketchConfig::ArduinoLibrary{"[email protected]"}},
.plugins = {smce::PluginManifest{
.name = "Smartcar_shield",
.version = "7.0.1",
.uri = "https://github.com/platisd/smartcar_shield/archive/refs/tags/7.0.1.tar.gz",
.patch_uri = "file://" + (std::filesystem::absolute(std_str(home_dir)) /
"library_patches" / "smartcar_shield")
.generic_string(),
.defaults = smce::PluginManifest::Defaults::arduino}}}};
std::vector<std::string> dep = {"ArduinoGraphics"};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What has this vector done to you for you to copy it it and thus exclude it from being directly initialized where it's used?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I remember correctly, we got a "C1001: Internal compiler error" when using .depends = {"ArduinoGraphics"} directly, and this was just a quick fix for that.

sketch = smce::Sketch{
std_str(src),
{.fqbn = "arduino:sam:arduino_due_x",
.legacy_preproc_libs = {smce::SketchConfig::ArduinoLibrary{"[email protected]"},
smce::SketchConfig::ArduinoLibrary{"[email protected]"},
smce::SketchConfig::ArduinoLibrary{"[email protected]"},
smce::SketchConfig::ArduinoLibrary{"[email protected]"}},
.plugins = {
smce::PluginManifest{
.name = "Smartcar_shield",
.version = "7.0.1",
.uri = "https://github.com/platisd/smartcar_shield/archive/refs/tags/7.0.1.tar.gz",
.patch_uri = "file://" + (std::filesystem::absolute(std_str(home_dir)) / "library_patches" /
"smartcar_shield")
.generic_string(),
.defaults = smce::PluginManifest::Defaults::arduino},
smce::PluginManifest{
.name = "ArduinoGraphics",
.version = "1.0.0",
.uri = "https://github.com/arduino-libraries/ArduinoGraphics/archive/refs/tags/1.0.0.zip",
.defaults = smce::PluginManifest::Defaults::arduino},
smce::PluginManifest{
.name = "Arduino_MKRRGB",
.version = "1.0.0",
.depends = dep,
.uri = "https://github.com/arduino-libraries/Arduino_MKRRGB/archive/refs/tags/1.0.0.zip",
.patch_uri = "file://" + (std::filesystem::absolute(std_str(home_dir)) / "library_patches" /
"arduino_mkrrgb")
.generic_string(),
.defaults = smce::PluginManifest::Defaults::arduino}}}};
}

String Sketch::get_source() { return sketch.get_source().c_str(); }
Expand Down