diff --git a/.gitignore b/.gitignore index 19ad330..19717c6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ src/lv_conf.h build/ +bin +scene*.json diff --git a/dev.sh b/dev.sh new file mode 100755 index 0000000..92acc19 --- /dev/null +++ b/dev.sh @@ -0,0 +1,114 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SRC_DIR="${ROOT_DIR}/src" +BIN="${ROOT_DIR}/bin/x32ctrl" + +usage() { + cat <<'EOF' +Usage: ./dev.sh [--clean] [--skip-submodules] [--] [x32ctrl args...] + +Builds the SDL2 desktop development simulator, then starts it in bodyless +development mode. + +Options: + --clean Remove the simulator build output before compiling. + --skip-submodules Do not run git submodule update --init --recursive. + -h, --help Show this help text. + +Any remaining arguments are forwarded to x32ctrl after --bodyless. +EOF +} + +clean=0 +update_submodules=1 +app_args=() + +while [[ $# -gt 0 ]]; do + case "$1" in + --clean) + clean=1 + shift + ;; + --skip-submodules) + update_submodules=0 + shift + ;; + -h|--help) + usage + exit 0 + ;; + --) + shift + app_args+=("$@") + break + ;; + *) + app_args+=("$1") + shift + ;; + esac +done + +jobs_count() { + if command -v nproc >/dev/null 2>&1; then + nproc 2>/dev/null || echo 4 + elif command -v sysctl >/dev/null 2>&1; then + sysctl -n hw.ncpu 2>/dev/null || echo 4 + else + echo 4 + fi +} + +sdl_cflags="" +sdl_libs="" + +if command -v sdl2-config >/dev/null 2>&1; then + sdl_cflags="$(sdl2-config --cflags)" + sdl_libs="$(sdl2-config --libs)" +elif command -v pkg-config >/dev/null 2>&1 && pkg-config --exists sdl2; then + sdl_cflags="$(pkg-config --cflags sdl2)" + sdl_libs="$(pkg-config --libs sdl2)" +else + cat >&2 <<'EOF' +SDL2 development files were not found. + +Install SDL2, then run this script again: + macOS: brew install sdl2 + Debian/Ubuntu: sudo apt install libsdl2-dev + Fedora: sudo dnf install SDL2-devel +EOF + exit 1 +fi + +case "$(uname -s)" in + Linux) + platform_ldflags="-lrt" + ;; + Darwin) + platform_ldflags="" + ;; + *) + platform_ldflags="" + ;; +esac + +if [[ "${update_submodules}" -eq 1 ]]; then + git -C "${ROOT_DIR}" submodule update --init --recursive +fi + +if [[ "${clean}" -eq 1 ]]; then + make -C "${SRC_DIR}" -f Makefile_x64_SDL2 clean +fi + +common_flags="-g -I../lib -I../lib/libartnet -I../lib/lv_port_linux -I../lib/glaze/include ${sdl_cflags} -MMD -MP -DBODYLESS_SDL2" + +make -C "${SRC_DIR}" -f Makefile_x64_SDL2 -j"$(jobs_count)" \ + CC="${CC:-cc}" \ + CXX="${CXX:-c++}" \ + CFLAGS="${CFLAGS:-${common_flags}}" \ + CXXFLAGS="${CXXFLAGS:-"-std=c++23 ${common_flags}"}" \ + LDFLAGS="${LDFLAGS:-"${sdl_libs} -lm -lpthread ${platform_ldflags}"}" + +exec "${BIN}" --bodyless "${app_args[@]}" diff --git a/files/lv_conf_SDL2.h b/files/lv_conf_SDL2.h index d15358d..673874d 100644 --- a/files/lv_conf_SDL2.h +++ b/files/lv_conf_SDL2.h @@ -1179,7 +1179,11 @@ #endif /** Driver for /dev/fb */ +#ifdef __APPLE__ +#define LV_USE_LINUX_FBDEV 0 +#else #define LV_USE_LINUX_FBDEV 1 +#endif #if LV_USE_LINUX_FBDEV #define LV_LINUX_FBDEV_BSD 0 #define LV_LINUX_FBDEV_RENDER_MODE LV_DISPLAY_RENDER_MODE_PARTIAL diff --git a/src/Makefile_x64_SDL2 b/src/Makefile_x64_SDL2 index de5c1a1..df6973b 100644 --- a/src/Makefile_x64_SDL2 +++ b/src/Makefile_x64_SDL2 @@ -8,27 +8,34 @@ #LD = arm-linux-gnueabi-ld LVGL_DIR_NAME ?= lvgl -LVGL_DIR ?= ./lv_port_linux +LVGL_DIR ?= ../lib/lv_port_linux LVGL_PATH = demosAreDisabledByThisHack -GLAZE_PATH = ./lib +LIB_DIR = ../lib +GLAZE_PATH = ../lib/glaze/include WARNINGS := -Wall -Wshadow -Wundef -Wextra -Wno-unused-function -Wno-error=strict-prototypes -Wpointer-arith \ - -fno-strict-aliasing -Wno-error=cpp -Wuninitialized -Wmaybe-uninitialized -Wno-unused-parameter -Wno-missing-field-initializers -Wtype-limits \ + -fno-strict-aliasing -Wno-error=cpp -Wuninitialized -Wno-unused-parameter -Wno-missing-field-initializers -Wtype-limits \ -Wsizeof-pointer-memaccess -Wno-format-nonliteral -Wno-cast-qual -Wunreachable-code -Wno-switch-default -Wreturn-type -Wmultichar -Wformat-security \ - -Wno-ignored-qualifiers -Wno-error=pedantic -Wno-sign-compare -Wno-error=missing-prototypes -Wdouble-promotion -Wclobbered -Wdeprecated -Wempty-body \ - -Wshift-negative-value -Wstack-usage=2048 -Wno-unused-value + -Wno-ignored-qualifiers -Wno-error=pedantic -Wno-sign-compare -Wno-error=missing-prototypes -Wdouble-promotion -Wdeprecated -Wempty-body \ + -Wshift-negative-value -Wno-unused-value -DEPFLAGS = -MMD -MP -D=BODYLESS_SDL2 +DEPFLAGS = -MMD -MP -DBODYLESS_SDL2 # normal build -#CFLAGS ?= -O3 -g0 -I$(LVGL_DIR)/ -I $(GLAZE_PATH)/ $(WARNINGS) $(DEPFLAGS) -#CXXFLAGS ?= -std=c++23 -O3 -g0 -I$(LVGL_DIR)/ -I$(GLAZE_PATH)/ $(WARNINGS) $(DEPFLAGS) +#CFLAGS ?= -O3 -g0 -I$(LIB_DIR) -I$(LIB_DIR)/libartnet -I$(LVGL_DIR)/ -I $(GLAZE_PATH)/ $(WARNINGS) $(DEPFLAGS) +#CXXFLAGS ?= -std=c++23 -O3 -g0 -I$(LIB_DIR) -I$(LIB_DIR)/libartnet -I$(LVGL_DIR)/ -I$(GLAZE_PATH)/ $(WARNINGS) $(DEPFLAGS) # debug build -CFLAGS ?= -g -I$(LVGL_DIR)/ -I$(GLAZE_PATH)/ $(WARNINGS) $(DEPFLAGS) -CXXFLAGS ?= -std=c++23 -g -I$(LVGL_DIR)/ -I$(GLAZE_PATH)/ $(WARNINGS) $(DEPFLAGS) +CFLAGS ?= -g -I$(LIB_DIR) -I$(LIB_DIR)/libartnet -I$(LVGL_DIR)/ -I$(GLAZE_PATH)/ $(WARNINGS) $(DEPFLAGS) +CXXFLAGS ?= -std=c++23 -g -I$(LIB_DIR) -I$(LIB_DIR)/libartnet -I$(LVGL_DIR)/ -I$(GLAZE_PATH)/ $(WARNINGS) $(DEPFLAGS) -LDFLAGS ?= -lSDL2 -lm -lrt -lpthread #-lartnet +LDFLAGS ?= -lSDL2 -lm -lpthread + +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Linux) + LDFLAGS += -lrt + WARNINGS += -Wmaybe-uninitialized -Wclobbered -Wstack-usage=2048 +endif BIN = x32ctrl BUILD_DIR = ../bin @@ -38,19 +45,24 @@ BUILD_BIN_DIR = $(BUILD_DIR) prefix ?= /usr bindir ?= $(prefix)/bin -# Collect source files recursively -CSRCS := $(shell find \ - -path './lv_port_linux/example' -prune -o \ - -path './lv_port_linux/lvgl/demos' -prune -o \ - -path './lv_port_linux/lvgl/examples' -prune -o \ - -path './lv_port_linux/lvgl/tests' -prune -o \ - -type f -name '*.c' -not -path './lv_port_linux/src/main.c' -print) -CXXSRCS := $(shell find \ - -path './lv_port_linux/example' -prune -o \ - -path './lv_port_linux/lvgl/demos' -prune -o \ - -path './lv_port_linux/lvgl/examples' -prune -o \ - -path './lv_port_linux/lvgl/tests' -prune -o \ - -type f -name '*.cpp' -not -path './lv_port_linux/src/main.c' -print) +# Collect source files recursively (macOS and Linux compatible find) +CSRCS := $(shell find . -type f -name '*.c' -print) \ + $(shell find ../lib \ + -path '../lib/lv_port_linux/example' -prune -o \ + -path '../lib/lv_port_linux/lvgl/demos' -prune -o \ + -path '../lib/lv_port_linux/lvgl/examples' -prune -o \ + -path '../lib/lv_port_linux/lvgl/tests' -prune -o \ + -path '../lib/glaze' -prune -o \ + -type f -name '*.c' -not -path '../lib/lv_port_linux/src/main.c' -print) + +CXXSRCS := $(shell find . -type f -name '*.cpp' -print) \ + $(shell find ../lib \ + -path '../lib/lv_port_linux/example' -prune -o \ + -path '../lib/lv_port_linux/lvgl/demos' -prune -o \ + -path '../lib/lv_port_linux/lvgl/examples' -prune -o \ + -path '../lib/lv_port_linux/lvgl/tests' -prune -o \ + -path '../lib/glaze' -prune -o \ + -type f -name '*.cpp' -not -path '../lib/lv_port_linux/src/main.c' -print) all: copy default @@ -84,9 +96,16 @@ $(BUILD_OBJ_DIR)/%.o: %.S lv_conf.h @echo "AS $<" copy: - @if ! diff -q lv_conf_SDL2.h lv_port_linux/lv_conf.h >/dev/null 2>&1; then \ - cp lv_conf_SDL2.h lv_port_linux/lv_conf.h; \ - echo "Update lv_port_linux/lv_conf.h (changed content)"; \ + @if ! diff -q ../files/lv_conf_SDL2.h $(LVGL_DIR)/lv_conf.h >/dev/null 2>&1; then \ + cp ../files/lv_conf_SDL2.h $(LVGL_DIR)/lv_conf.h; \ + echo "Update $(LVGL_DIR)/lv_conf.h (changed content)"; \ + else \ + echo "lv_conf.h is up to date."; \ + fi + + @if ! diff -q ../files/lv_conf_SDL2.h lv_conf.h >/dev/null 2>&1; then \ + cp ../files/lv_conf_SDL2.h lv_conf.h; \ + echo "Update lv_conf.h (changed content)"; \ else \ echo "lv_conf.h is up to date."; \ fi diff --git a/src/artnet.h b/src/artnet.h index ead9e46..00e4cca 100755 --- a/src/artnet.h +++ b/src/artnet.h @@ -9,14 +9,13 @@ #include "base.h" using namespace std; -using enum MP_ID; - #if ENABLE_ARTNET #include "../libartnet/artnet/artnet.h" class Artnet : public X32Base { + using enum MP_ID; public: Artnet(X32BaseParameter* basepar); void Init(); diff --git a/src/external.h b/src/external.h index d8098af..834631e 100644 --- a/src/external.h +++ b/src/external.h @@ -9,7 +9,9 @@ #include #include #include +#ifndef __APPLE__ #include +#endif #include #include diff --git a/src/lcd-menu.h b/src/lcd-menu.h index ad88f76..6bea9d9 100644 --- a/src/lcd-menu.h +++ b/src/lcd-menu.h @@ -10,6 +10,7 @@ using namespace std; class LcdMenu : public X32Base { private: + using enum MP_ID; Mixer* mixer; Surface* surface; bool initDone = false; diff --git a/src/main.cpp b/src/main.cpp index 6c9cd3d..068e008 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -61,9 +61,11 @@ static lv_indev_t *mouse_wheel; static lv_indev_t *keyboard; #endif +#ifndef __APPLE__ timer_t timerid_10ms; struct sigevent sev_10ms; struct itimerspec trigger_10ms; +#endif uint8_t vtimercounter = 0; void timer100msCallbackLvgl(_lv_timer_t* lv_timer) { @@ -77,6 +79,8 @@ void timer50msCallbackLvgl(_lv_timer_t* lv_timer) { void timer10msCallbackLvgl(_lv_timer_t* lv_timer) { ui_tick(); ctrl->Tick10ms(); } + +#ifndef __APPLE__ void timer10msCallbackLinux(int timer) { ctrl->Tick10ms(); @@ -122,8 +126,10 @@ void init10msTimer_NonGUI(void) { perror("timer_settime"); } } +#endif void guiInit(X32Config* config) { + using enum MP_ID; lv_init(); @@ -389,7 +395,11 @@ int main(int argc, char* argv[]) { if (config->IsModelX32Core()){ // only necessary if LVGL is not used helper->Log("Starting Timers...\n"); +#ifndef __APPLE__ init10msTimer_NonGUI(); +#else + helper->Log("Timers not supported on macOS.\n"); +#endif helper->Log("Press Ctrl+C to terminate program.\n"); while (1) { diff --git a/src/mixer.h b/src/mixer.h index abd06f7..f241d5c 100644 --- a/src/mixer.h +++ b/src/mixer.h @@ -20,10 +20,9 @@ #include "card.h" using namespace std; -using enum MP_ID; - class Mixer : public X32Base { + using enum MP_ID; private: // solo is (somewhere) activated diff --git a/src/mixerparameter.h b/src/mixerparameter.h index 67ae0aa..3661722 100644 --- a/src/mixerparameter.h +++ b/src/mixerparameter.h @@ -9,6 +9,9 @@ #include "defines.h" #include "enum.h" +#include +#include + using namespace std; using namespace WString; @@ -83,7 +86,7 @@ class Mixerparameter { if (index >= instances) { - __throw_out_of_range((String("The index ") + String(index) + String(" is bigger than the specified instances of ") + String(instances) + String(" (zero based!) of the Mixerparameter ") + GetName() + String(".")).c_str()); + throw std::out_of_range((String("The index ") + String(index) + String(" is bigger than the specified instances of ") + String(instances) + String(" (zero based!) of the Mixerparameter ") + GetName() + String(".")).c_str()); } } @@ -94,7 +97,7 @@ class Mixerparameter { if (mp_value_type != value_type) { - __throw_bad_typeid(); + throw std::bad_typeid(); } } @@ -104,7 +107,7 @@ class Mixerparameter { if (readonly) { - __throw_logic_error((String("The Mixerparameter ") + GetName() + String(" can not be changed, it is readonly.")).c_str()); + throw std::logic_error((String("The Mixerparameter ") + GetName() + String(" can not be changed, it is readonly.")).c_str()); } } @@ -884,7 +887,7 @@ class Mixerparameter if (stepsize == 0) { - __throw_logic_error((String("Stepsize of Mixerparameter ") + GetName() + String(" is 0, so no change can happen!")).c_str()); + throw std::logic_error((String("Stepsize of Mixerparameter ") + GetName() + String(" is 0, so no change can happen!")).c_str()); } float newValue; diff --git a/src/page-meters.h b/src/page-meters.h index c1e9fbc..e5de12d 100644 --- a/src/page-meters.h +++ b/src/page-meters.h @@ -2,10 +2,9 @@ #include "page.h" using namespace std; -using enum MP_ID; - class PageMeters : public Page { + using enum MP_ID; private: lv_obj_t* meterBlocks[9]; diff --git a/src/page-routing-channels.h b/src/page-routing-channels.h index 2e20deb..fd8b83d 100644 --- a/src/page-routing-channels.h +++ b/src/page-routing-channels.h @@ -6,7 +6,9 @@ using namespace std; class PageRoutingChannels: public Page { +#ifndef __clang__ using enum MP_ID; +#endif private: diff --git a/src/page-routing-dsp.h b/src/page-routing-dsp.h index a38d0d7..e62a17d 100644 --- a/src/page-routing-dsp.h +++ b/src/page-routing-dsp.h @@ -3,10 +3,9 @@ #include "page.h" using namespace std; -using enum MP_ID; - class PageRoutingDsp: public Page { + using enum MP_ID; private: int gui_selected_item = 0; diff --git a/src/page-rta.h b/src/page-rta.h index c3c482d..aa8baa8 100644 --- a/src/page-rta.h +++ b/src/page-rta.h @@ -2,10 +2,9 @@ #include "page.h" using namespace std; -using enum MP_ID; - class PageRta : public Page { + using enum MP_ID; private: lv_chart_series_t* chartSeriesRta; uint8_t updateRateReducer = 0; diff --git a/src/page-scenes.h b/src/page-scenes.h index 0186b2b..f7b23a1 100644 --- a/src/page-scenes.h +++ b/src/page-scenes.h @@ -2,10 +2,9 @@ #include "page.h" using namespace std; -using enum MP_ID; - class PageScenes: public Page { + using enum MP_ID; private: int configindex = 0; diff --git a/src/page-setup.h b/src/page-setup.h index 1acaff0..663dccb 100644 --- a/src/page-setup.h +++ b/src/page-setup.h @@ -4,7 +4,9 @@ using namespace std; class PageSetup: public Page { +#ifndef __clang__ using enum MP_ID; +#endif public: PageSetup(PageBaseParameter* pagebasepar) : Page(pagebasepar) diff --git a/src/page.h b/src/page.h index d15b023..dfa3b21 100644 --- a/src/page.h +++ b/src/page.h @@ -15,11 +15,10 @@ #include "eez/src/ui/styles.h" using namespace std; -using enum MP_ID; - class Page : public X32Base { protected: + using enum MP_ID; Mixer* mixer; Surface* surface; diff --git a/src/spi.cpp b/src/spi.cpp index ab2bea3..6d84152 100644 --- a/src/spi.cpp +++ b/src/spi.cpp @@ -24,6 +24,7 @@ #include "spi.h" +#ifndef __APPLE__ SPI::SPI(X32BaseParameter* basepar) : X32Base(basepar) {} // configures a Xilinx Spartan 3A via SPI @@ -1289,3 +1290,28 @@ SpiEvent* SPI::GetNextEvent(void){ eventBuffer.pop_back(); return event; } +#endif + +#ifdef __APPLE__ +SPI::SPI(X32BaseParameter* basepar) : X32Base(basepar) { + connected = false; +} +int SPI::UploadBitstreamFpgaXilinx() { return 0; } +int SPI::UploadBitstreamFpgaLattice() { return 0; } +int SPI::UploadBitstreamDsps(bool useCli) { return 0; } +bool SPI::OpenConnectionFpga() { return false; } +bool SPI::CloseConnectionFpga() { return true; } +bool SPI::OpenConnectionDsps() { return false; } +bool SPI::CloseConnectionDsps() { return true; } +bool SPI::SendFpgaData(uint8_t txData[], uint8_t rxData[], uint8_t len) { return false; } +void SPI::QueueDspData(uint8_t dsp, uint8_t classId, uint8_t channel, uint8_t index, uint8_t valueCount, float values[]) {} +void SPI::ProcessDspTxQueue(uint8_t dsp) {} +uint32_t SPI::GetDspTxQueueLength(uint8_t dsp) { return 0; } +bool SPI::SendDspData(uint8_t dsp, sSpiTxBufferElement* buffer) { return false; } +void SPI::UpdateNumberOfExpectedReadBytes(uint8_t dsp, uint8_t classId, uint8_t channel, uint8_t index) {} +bool SPI::ReadDspData(uint8_t dsp, uint8_t classId, uint8_t channel, uint8_t index) { return false; } +void SPI::PushValuesToRxBuffer(uint8_t dsp, uint32_t valueCount, uint32_t values[]) {} +void SPI::ProcessRxData(uint8_t dsp) {} +bool SPI::HasNextEvent(void) { return false; } +SpiEvent* SPI::GetNextEvent(void) { return nullptr; } +#endif diff --git a/src/spi.h b/src/spi.h index d85eb95..59e5a72 100644 --- a/src/spi.h +++ b/src/spi.h @@ -1,7 +1,9 @@ #pragma once +#ifndef __APPLE__ #include #include +#endif #include #include diff --git a/src/uart.cpp b/src/uart.cpp index 7962ae4..cd73f59 100644 --- a/src/uart.cpp +++ b/src/uart.cpp @@ -88,6 +88,7 @@ int Uart::Open(const char* ttydev, uint32_t baudrate, bool raw) { } else if (baudrate == 115200) { cfsetispeed(&tty, B115200); cfsetospeed(&tty, B115200); +#ifndef __APPLE__ } else if (baudrate == 500000) { cfsetispeed(&tty, B500000); cfsetospeed(&tty, B500000); @@ -115,6 +116,7 @@ int Uart::Open(const char* ttydev, uint32_t baudrate, bool raw) { } else if (baudrate == 4000000) { cfsetispeed(&tty, B4000000); cfsetospeed(&tty, B4000000); +#endif } else { perror("Error: unsupported baudrate!"); return 1; diff --git a/src/uart.h b/src/uart.h index 2f135fa..23c8952 100644 --- a/src/uart.h +++ b/src/uart.h @@ -3,7 +3,9 @@ #include #include #include +#ifndef __APPLE__ #include +#endif #include #include #include // for FIONREAD diff --git a/src/wsm.cpp b/src/wsm.cpp index 7493e74..3ad8a64 100644 --- a/src/wsm.cpp +++ b/src/wsm.cpp @@ -50,7 +50,7 @@ int WSM::Init() return -1; } - if (bind(UdpHandle, (const struct sockaddr *)&ServerAddr, sizeof(ServerAddr)) < 0) { + if (::bind(UdpHandle, (const struct sockaddr *)&ServerAddr, sizeof(ServerAddr)) < 0) { //fprintf(stderr, "Error on binding UDP-socket!"); close(UdpHandle); return -1; diff --git a/src/wsm.h b/src/wsm.h index a11efd4..f8fd252 100644 --- a/src/wsm.h +++ b/src/wsm.h @@ -8,7 +8,9 @@ #include #include #include +#ifndef __APPLE__ #include +#endif #include // includes for UDP-communication diff --git a/src/xremote.cpp b/src/xremote.cpp index 5182e73..8b779e7 100644 --- a/src/xremote.cpp +++ b/src/xremote.cpp @@ -49,7 +49,7 @@ int8_t XRemote::Init() { ServerAddr.sin_addr.s_addr = INADDR_ANY; ServerAddr.sin_port = htons(10023); - if (bind(UdpHandle, (const struct sockaddr *)&ServerAddr, sizeof(ServerAddr)) < 0) { + if (::bind(UdpHandle, (const struct sockaddr *)&ServerAddr, sizeof(ServerAddr)) < 0) { //fprintf(stderr, "Error on binding UDP-socket!"); close(UdpHandle); return -1; diff --git a/src/xremote.h b/src/xremote.h index 1b4ebde..7916b76 100644 --- a/src/xremote.h +++ b/src/xremote.h @@ -8,7 +8,9 @@ #include #include #include +#ifndef __APPLE__ #include +#endif // includes for UDP-communication #include