From ae1823285330d05cf61cd89b4843969c36111acd Mon Sep 17 00:00:00 2001 From: Simon Hardt Date: Fri, 4 Mar 2022 21:44:18 +0100 Subject: [PATCH] add: VirtualDisplay --- CMakeLists.txt | 24 ++++++++- frame/CMakeLists.txt | 33 +++++++++++-- frame/src/Config.h | 2 + frame/src/Config.h.in | 2 + frame/src/display/Display.cpp | 27 ++++++++++ frame/src/display/Display.hpp | 13 +++++ frame/src/display/IDisplay.hpp | 2 + frame/src/display/VirtualDisplay.cpp | 73 ++++++++++++++++++++++++++++ frame/src/display/VirtualDisplay.hpp | 33 +++++++++++++ frame/src/main.cpp | 28 ++++++----- frame/src/render/RenderTarget.cpp | 49 +++++++++++-------- vcpkg.json | 11 +++++ 12 files changed, 261 insertions(+), 36 deletions(-) create mode 100644 frame/src/Config.h create mode 100644 frame/src/Config.h.in create mode 100644 frame/src/display/Display.cpp create mode 100644 frame/src/display/Display.hpp create mode 100644 frame/src/display/VirtualDisplay.cpp create mode 100644 frame/src/display/VirtualDisplay.hpp create mode 100644 vcpkg.json diff --git a/CMakeLists.txt b/CMakeLists.txt index a258284..5e714d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,34 @@ cmake_minimum_required(VERSION 3.18) +if (BUILD_VIRTUAL_DISPLAY) + set(VCPKG_MANIFEST_FEATURES virtual) +endif(BUILD_VIRTUAL_DISPLAY) + + project(Frame) set(CMAKE_CXX_STANDARD 17) +option(BUILD_EPD + "Build EPD Display" + OFF +) -#if (UNIX) +find_package(fmt CONFIG REQUIRED) + +option(BUILD_VIRTUAL_DISPLAY + "Build virtual sfml based display" + OFF +) + +if (BUILD_EPD) add_subdirectory(bcm2835) add_subdirectory(waveshare) -#endif (UNIX) +endif (BUILD_EPD) + +if (BUILD_VIRTUAL_DISPLAY) + find_package(SFML COMPONENTS system window graphics CONFIG REQUIRED) +endif(BUILD_VIRTUAL_DISPLAY) add_subdirectory(frame) diff --git a/frame/CMakeLists.txt b/frame/CMakeLists.txt index c84ab39..42188fd 100644 --- a/frame/CMakeLists.txt +++ b/frame/CMakeLists.txt @@ -1,17 +1,44 @@ set(target frame) +configure_file ( + "${PROJECT_SOURCE_DIR}/frame/src/Config.h.in" + "${PROJECT_SOURCE_DIR}/frame/src/Config.h" +) + set(src src/main.cpp src/Image.hpp src/Image.cpp src/display/IDisplay.hpp - src/display/EPD_7in5_V2.hpp - src/display/EPD_7in5_V2.cpp + src/display/Display.hpp + src/display/Display.cpp src/render/RenderTarget.hpp src/render/RenderTarget.cpp ) +if (BUILD_EPD) + set(src ${src} + src/display/EPD_7in5_V2.hpp + src/display/EPD_7in5_V2.cpp + ) +endif (BUILD_EPD) + +if (BUILD_VIRTUAL_DISPLAY) + set(src ${src} + src/display/VirtualDisplay.hpp + src/display/VirtualDisplay.cpp + ) +endif (BUILD_VIRTUAL_DISPLAY) + add_executable(${target} ${src}) -target_link_libraries(${target} PRIVATE waveshare) \ No newline at end of file +target_link_libraries(${target} PRIVATE fmt::fmt) + +if (BUILD_EPD) + target_link_libraries(${target} PRIVATE waveshare) +endif (BUILD_EPD) + +if (BUILD_VIRTUAL_DISPLAY) + target_link_libraries(${target} PRIVATE sfml-system sfml-window sfml-graphics) +endif(BUILD_VIRTUAL_DISPLAY) \ No newline at end of file diff --git a/frame/src/Config.h b/frame/src/Config.h new file mode 100644 index 0000000..eaf6409 --- /dev/null +++ b/frame/src/Config.h @@ -0,0 +1,2 @@ +#define BUILD_VIRTUAL_DISPLAY +/* #undef BUILD_EPD */ diff --git a/frame/src/Config.h.in b/frame/src/Config.h.in new file mode 100644 index 0000000..81f54b2 --- /dev/null +++ b/frame/src/Config.h.in @@ -0,0 +1,2 @@ +#cmakedefine BUILD_VIRTUAL_DISPLAY +#cmakedefine BUILD_EPD \ No newline at end of file diff --git a/frame/src/display/Display.cpp b/frame/src/display/Display.cpp new file mode 100644 index 0000000..4b84bbe --- /dev/null +++ b/frame/src/display/Display.cpp @@ -0,0 +1,27 @@ +#include "Display.hpp" + +#include "../Config.h" + +#ifdef BUILD_EPD +# include "EPD_7in5_V2.hpp" +#endif + +#ifdef BUILD_VIRTUAL_DISPLAY +# include "VirtualDisplay.hpp" +#endif + +namespace frame::display +{ + std::unique_ptr Create() + { +#ifdef BUILD_EPD + return std::make_unique(); +#endif + +#ifdef BUILD_VIRTUAL_DISPLAY + return std::make_unique(); +#endif + + return nullptr; + } +} // namespace frame::display \ No newline at end of file diff --git a/frame/src/display/Display.hpp b/frame/src/display/Display.hpp new file mode 100644 index 0000000..d7aaa60 --- /dev/null +++ b/frame/src/display/Display.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "IDisplay.hpp" + +#include + + +namespace frame::display +{ + + std::unique_ptr Create(); + +} \ No newline at end of file diff --git a/frame/src/display/IDisplay.hpp b/frame/src/display/IDisplay.hpp index d286d46..36e19bf 100644 --- a/frame/src/display/IDisplay.hpp +++ b/frame/src/display/IDisplay.hpp @@ -26,6 +26,8 @@ namespace frame::display virtual void Sleep() = 0; + virtual void Update() {} + public: Size const& getSize() { diff --git a/frame/src/display/VirtualDisplay.cpp b/frame/src/display/VirtualDisplay.cpp new file mode 100644 index 0000000..0d2758e --- /dev/null +++ b/frame/src/display/VirtualDisplay.cpp @@ -0,0 +1,73 @@ +#include "VirtualDisplay.hpp" + +#include "../size.hpp" + +#include + +namespace frame::display +{ + constexpr std::string_view title = "Virtual Display"; + + VirtualDisplay::VirtualDisplay() + : IDisplay(title, {800, 480}) + , size(getSize()) + , window(sf::VideoMode(size.width, size.height), std::string(title)) + { + } + + bool VirtualDisplay::Init() + { + renderTarget.create(size.width, size.height, sf::Color::White); + Draw(); + return true; + } + + void VirtualDisplay::Clear(Color color) + { + renderTarget.create(size.width, + size.height, + color == Color::WHITE ? sf::Color::White + : sf::Color::Black); + Draw(); + } + + void VirtualDisplay::Display(Image const& image, bool invert) + { + + for(auto y = 0; y < size.height; ++y) + { + for(auto x = 0; x < size.width; ++x) + { + renderTarget.setPixel(x, + y, + (image.at(x, y) > 265 / 2) + ? sf::Color::Black + : sf::Color::White); + } + } + Draw(); + } + + void VirtualDisplay::Sleep() {} + + void VirtualDisplay::Update() + { + sf::Event ev; + while(window.pollEvent(ev)) + { + } + } + + void VirtualDisplay::Draw() + { + sf::Sprite sprite; + sf::Texture texture; + texture.loadFromImage(renderTarget); + sprite.setTexture(texture); + + window.clear(sf::Color::White); + window.draw(sprite); + window.display(); + } + +}; // namespace frame::display diff --git a/frame/src/display/VirtualDisplay.hpp b/frame/src/display/VirtualDisplay.hpp new file mode 100644 index 0000000..a6ca71b --- /dev/null +++ b/frame/src/display/VirtualDisplay.hpp @@ -0,0 +1,33 @@ +#pragma once +#include "IDisplay.hpp" + +#include + +namespace frame::display +{ + + class VirtualDisplay : public IDisplay + { + Size size; + sf::RenderWindow window; + sf::Image renderTarget; + + public: + VirtualDisplay(); + ~VirtualDisplay() = default; + + bool Init() override; + + void Clear(Color color) override; + + void Display(Image const& image, bool invert = false) override; + + void Sleep() override; + + void Update() override; + + private: + void Draw(); + }; + +} // namespace frame::display diff --git a/frame/src/main.cpp b/frame/src/main.cpp index d00d7ea..8618ddf 100644 --- a/frame/src/main.cpp +++ b/frame/src/main.cpp @@ -4,25 +4,29 @@ #include #include - using namespace std::chrono_literals; -#include "display/EPD_7in5_V2.hpp" +#include "display/Display.hpp" #include "render/RenderTarget.hpp" int main() { constexpr double pi = 3.14159; - frame::display::EPD_7in5_V2 display{}; + auto display = frame::display::Create(); - display.Init(); + if(!display) + { + return 0; + } - display.Clear(frame::display::Color::WHITE); + display->Init(); - frame::render::RenderTarget target(display.getSize()); + display->Clear(frame::display::Color::WHITE); - frame::Vector const center = (display.getSize() / 2); + frame::render::RenderTarget target(display->getSize()); + + frame::Vector const center = (display->getSize() / 2); target.DrawPixel({10, 10}, frame::BLACK); target.DrawLine({10, 12}, {100, 12}, frame::BLACK); @@ -52,15 +56,17 @@ int main() target.DrawCircle({151, 151}, 30, frame::WHITE); target.DrawCircle({151, 151}, 20, frame::WHITE); target.DrawCircle({151, 151}, 10, frame::WHITE); - target.DrawCircle({151, 151}, 1, frame::WHITE); + target.DrawCircle({151, 151}, 1, frame::WHITE); - target.DrawRect({10, (int)display.getSize().height - 110}, {110, (int)display.getSize().height - 10}, 5); + target.DrawRect({10, (int)display->getSize().height - 110}, + {110, (int)display->getSize().height - 10}, + 5); - display.Display(target.getImage()); + display->Display(target.getImage()); std::this_thread::sleep_for(10s); - display.Clear(frame::display::Color::WHITE); + display->Clear(frame::display::Color::WHITE); } /* diff --git a/frame/src/render/RenderTarget.cpp b/frame/src/render/RenderTarget.cpp index 8680a82..627a986 100644 --- a/frame/src/render/RenderTarget.cpp +++ b/frame/src/render/RenderTarget.cpp @@ -12,7 +12,8 @@ namespace frame::render void RenderTarget::DrawPixel(Vector const& position, Color color) { - if(position.x < 0 || position.y < 0 || position.x >= image.getWidth() || position.y > image.getHeight()) + if(position.x < 0 || position.y < 0 || position.x >= image.getWidth() + || position.y >= image.getHeight()) return; image.at(position.x, position.y) = color; } @@ -85,7 +86,8 @@ namespace frame::render while(pos.x <= radius / std::sqrt(2.f)) { - float E = pos.x * pos.x + ((float)pos.y + 0.5f) * ((float)pos.y + 0.5f) - r_2; + float E = pos.x * pos.x + + ((float)pos.y + 0.5f) * ((float)pos.y + 0.5f) - r_2; if(E <= 0) { @@ -104,23 +106,28 @@ namespace frame::render } } - void RenderTarget::DrawRectFilled(Vector const& LeftTop, Vector const& BottomRight, Color color) + void RenderTarget::DrawRectFilled(Vector const& LeftTop, + Vector const& BottomRight, + Color color) { - auto pos = LeftTop; + auto pos = LeftTop; - while(pos.y <= BottomRight.y) - { - while(pos.x <= BottomRight.x) - { - DrawPixel(pos, color); - pos.x++; - } - pos.x = LeftTop.x; - pos.y++; - } + while(pos.y <= BottomRight.y) + { + while(pos.x <= BottomRight.x) + { + DrawPixel(pos, color); + pos.x++; + } + pos.x = LeftTop.x; + pos.y++; + } } - void RenderTarget::DrawRect(Vector const& TopLeft, Vector const& BottomRight, uint8_t LineWidth, Color color) + void RenderTarget::DrawRect(Vector const& TopLeft, + Vector const& BottomRight, + uint8_t LineWidth, + Color color) { auto pos = TopLeft; @@ -129,13 +136,15 @@ namespace frame::render DrawRectFilled(TopLeft, {BottomRight.x, TopLeft.y + lw}, color); DrawRectFilled({TopLeft.x, BottomRight.y - lw}, BottomRight); - DrawRectFilled({TopLeft.x , TopLeft.y + lw}, - {TopLeft.x + lw, BottomRight.y - lw}); - DrawRectFilled({BottomRight.x - lw, TopLeft.y + lw}, - {BottomRight.x , BottomRight.y - lw}); + DrawRectFilled({TopLeft.x, TopLeft.y + lw}, + {TopLeft.x + lw, BottomRight.y - lw}); + DrawRectFilled({BottomRight.x - lw, TopLeft.y + lw}, + {BottomRight.x, BottomRight.y - lw}); } - void RenderTarget::DrawPointsMirrorCircle(Vector const& center, Vector const& pos, Color color) + void RenderTarget::DrawPointsMirrorCircle(Vector const& center, + Vector const& pos, + Color color) { DrawPixel(center + pos, color); DrawPixel(center + Vector{pos.x, pos.y * -1}, color); diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 0000000..c937e32 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,11 @@ +{ + "name": "frame", + "version": "1.0", + "dependencies": ["fmt"], + "features": { + "virtual": { + "description": "Build Virtual Display", + "dependencies": ["sfml"] + } + } +}