diff --git a/Makefile b/Makefile index a0c14934..a64b9008 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,9 @@ core: teletype: +$(MAKE) -f scripts/teletype.mk +example: + +$(MAKE) -f scripts/example.mk + core-clean: +$(MAKE) -f scripts/core.mk clean @@ -60,15 +63,15 @@ pbl-clean: +$(MAKE) -f scripts/pbl.mk clean emu: - +$(MAKE) -f scripts/lua.mk ARCH=linux - +$(MAKE) -f scripts/miniz.mk ARCH=linux - +$(MAKE) -f scripts/lodepng.mk ARCH=linux + +$(MAKE) -f scripts/lua.mk + +$(MAKE) -f scripts/miniz.mk + +$(MAKE) -f scripts/lodepng.mk +$(MAKE) -f scripts/emu.mk emu-clean: - +$(MAKE) -f scripts/lua.mk ARCH=linux clean - +$(MAKE) -f scripts/miniz.mk ARCH=linux clean - +$(MAKE) -f scripts/lodepng.mk ARCH=linux clean + +$(MAKE) -f scripts/lua.mk clean + +$(MAKE) -f scripts/miniz.mk clean + +$(MAKE) -f scripts/lodepng.mk clean +$(MAKE) -f scripts/emu.mk clean dist-clean: diff --git a/README.md b/README.md index 0b1b3566..a6326cd2 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,7 @@ Edit this file with your own values to configure various items like key mappings Packages encapsulate unit presets (*.unit), unit definitions (*.lua), and shared libraries (*.so) into one shareable bundle along with any necessary assets (e.g. sound files and so on). The core units are also distributed as a package, so let's use the core package as an example. First, to compile and create the core package, execute: ```bash -make core ARCH=linux +make core ``` Next, let's go over the two main methods for installing packages. @@ -188,7 +188,7 @@ First, you will need to install the TI-RTOS development tools for the AM335x. 4. ***When asked, please set the destination folder to ```~/ti```.*** This is the path assumed by the project makefiles. If instead you install to a different folder then before executing any cross-compilation commands, you will need to set the TI_INSTALL_DIR shell environment variable to the actual path that you used. If you don't want to change your shell environment then you can also pass the path on the commandline like this: ```bash -make core TI_INSTALL_DIR=~/your-path-to-ti-sdk +make core TI_INSTALL_DIR=~/your-path-to-ti-sdk ARCH=am355x ``` This documentation will assume that you used the default location. @@ -206,7 +206,7 @@ sudo apt install swig python3 zip gcc-multilib A good test of your build environment is to see if you can successfully build the factory mods: ```bash -make core teletype +make core teletype ARCH=am355x ``` ## USB Functions @@ -223,10 +223,11 @@ All build outputs are placed in a sub folder composed of the build profile and t * debug: No optimizations. Logging enabled. * release: All optimizations enabled. Logging disabled. -And here are the 2 supported target architectures: +And here are the 3 supported target architectures: * am335x * linux +* darwin (OSX) So for example, if I execute the following make command: @@ -234,10 +235,4 @@ So for example, if I execute the following make command: make core PROFILE=debug ARCH=linux ``` -Then the build outputs will be placed in the ```debug/linux``` directory of the project root. Generally, the default profile is **testing** and the default architecture for everything except the emulator is **am335x**. So if you execute just: - -```bash -make core -``` - -Then the build outputs will appear in the ```testing/am335x``` directory of the project root. See the [top-level Makefile](Makefile) for more details. +Then the build outputs will be placed in the ```debug/linux``` directory of the project root. Generally, the default profile is **testing** and the default architecture is determined by your OS (`uname -s`). See the [top-level Makefile](Makefile) for more details. diff --git a/arch/linux/hal/fileops.c b/arch/linux/hal/fileops.c index 6cb6df7d..35133533 100644 --- a/arch/linux/hal/fileops.c +++ b/arch/linux/hal/fileops.c @@ -1,6 +1,7 @@ #include #include -#include +#include +#include #include #include #include @@ -155,7 +156,7 @@ int diskFreeSpaceMB(const char *path) struct statfs fsinfo; if (statfs(path, &fsinfo) == 0) { - uint64_t bytes = fsinfo.f_frsize * fsinfo.f_blocks; + uint64_t bytes = fsinfo.f_bsize * fsinfo.f_blocks; return (int)(bytes / 1024 / 1024); } return 0; @@ -166,7 +167,7 @@ int diskTotalSpaceMB(const char *path) struct statfs fsinfo; if (statfs(path, &fsinfo) == 0) { - uint64_t bytes = fsinfo.f_frsize * fsinfo.f_bavail; + uint64_t bytes = fsinfo.f_bsize * fsinfo.f_bavail; return (int)(bytes / 1024 / 1024); } return 0; diff --git a/hal/pump/rfifo4.c b/hal/pump/rfifo4.c index eff7151e..44d06338 100644 --- a/hal/pump/rfifo4.c +++ b/hal/pump/rfifo4.c @@ -1,7 +1,7 @@ #include #include #include "rfifo4.h" -#include +#include void rfifo4_alloc(rfifo4_t *fifo, int length) { @@ -10,7 +10,7 @@ void rfifo4_alloc(rfifo4_t *fifo, int length) fifo->wpos = 0; fifo->numread = length; int bytes = length * 2 * sizeof(float32x4_t); - fifo->buffer = (float32x4_t *)memalign(CACHELINE_SIZE_MAX, bytes); + posix_memalign((void **)&fifo->buffer, CACHELINE_SIZE_MAX, bytes); logAssert(fifo->buffer); bzero(fifo->buffer, bytes); fifo->length = length; diff --git a/mods/example/AR.cpp b/mods/example/AR.cpp new file mode 100644 index 00000000..21ef44fe --- /dev/null +++ b/mods/example/AR.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include + +namespace example { + + AR::AR() { + addInput(mGateInput); + addInput(mLoopInput); + addInput(mAttack); + addInput(mRelease); + addOutput(mOutput); + + mAttackStage = &od::LookupTables::ConcaveParabolicRise; + mReleaseStage = &od::LookupTables::ConcaveParabolicFall; + } + + AR::~AR() { } + + void AR::process() { + float *gate = mGateInput.buffer(); + float *loop = mLoopInput.buffer(); + float *attack = mAttack.buffer(); + float *release = mRelease.buffer(); + float *out = mOutput.buffer(); + + mAttackPhaseChange = globalConfig.samplePeriod / MAX(0.0001f, attack[0]); + mReleasePhaseChange = globalConfig.samplePeriod / MAX(0.0001f, release[0]); + + for (int i = 0; i < FRAMELENGTH; i++) { + out[i] = next(gate[i], loop[i]); + } + } + + inline float AR::next(float currentGate, float currentLoop) { + switch (mStage) { + case 0: + if (currentGate > 0.5f || currentLoop > 0.5f) { + mStage = 1; + mPhase = 0.0f; + mCapture = mCurrentValue; + } + break; + + case 1: + mPhase += mAttackPhaseChange; + if (mPhase < 1.0f) { + mCurrentValue = mCapture + (1.0f - mCapture) * mAttackStage->get(mPhase); + } else { + mCapture = mCurrentValue; + mPhase = 0.0f; + mStage = 2; + } + break; + + case 2: + mCurrentValue = 1.0f; + if (currentGate < 0.5f) { + mCapture = mCurrentValue; + mPhase = 0.0f; + mStage = 3; + } + break; + + case 3: + mPhase += mReleasePhaseChange; + if (mPhase < 1.0f) { + mCurrentValue = mCapture * mReleaseStage->get(mPhase); + } else { + mCapture = 0.0f; + mPhase = 0.0f; + mStage = 0; + + // Force to zero, possible discontinuity + mCurrentValue = 0.0f; + + if (currentLoop > 0.5f) { + mStage = 1; + } + } + break; + } + + return mCurrentValue; + } +} \ No newline at end of file diff --git a/mods/example/AR.h b/mods/example/AR.h new file mode 100644 index 00000000..0addb1d5 --- /dev/null +++ b/mods/example/AR.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +namespace example { + class AR : public od::Object { + public: + AR(); + virtual ~AR(); + +#ifndef SWIGLUA + virtual void process(); + od::Inlet mGateInput{"Gate"}; + od::Inlet mLoopInput{"Loop"}; + od::Inlet mAttack{"Attack"}; + od::Inlet mRelease{"Release"}; + od::Outlet mOutput{"Out"}; +#endif + + private: + float next(float currentGate, float currentLoop); + + int mStage = 0; + + float mPhase = 0.0f; + float mCapture = 0.0f; + float mAttackPhaseChange = 0.0f; + float mReleasePhaseChange = 0.0f; + float mCurrentValue = 0.0f; + + od::LookupTable *mAttackStage = NULL; + od::LookupTable *mReleaseStage = NULL; + }; +} diff --git a/mods/example/assets/AR.lua b/mods/example/assets/AR.lua new file mode 100644 index 00000000..17048eff --- /dev/null +++ b/mods/example/assets/AR.lua @@ -0,0 +1,110 @@ +local app = app +local libexample = require "example.libexample" +local Class = require "Base.Class" +local Unit = require "Unit" +local GainBias = require "Unit.ViewControl.GainBias" +local InputGate = require "Unit.ViewControl.InputGate" +local Gate = require "Unit.ViewControl.Gate" +local Encoder = require "Encoder" + +local AR = Class {} +AR:include(Unit) + +function AR:init(args) + args.title = "AR" + args.mnemonic = "En" + Unit.init(self, args) +end + +function AR:onLoadGraph(channelCount) + if channelCount == 2 then + self:loadStereoGraph() + else + self:loadMonoGraph() + end +end + +function AR:loadMonoGraph() + local gate = self:addObject("gate", app.Comparator()) + gate:setGateMode() + local loop = self:addObject("loop", app.Comparator()) + loop:setToggleMode() + local ar = self:addObject("ar", libexample.AR()) + local attack = self:addObject("attack", app.GainBias()) + local release = self:addObject("release", app.GainBias()) + local attackRange = self:addObject("attackRange", app.MinMax()) + local releaseRange = self:addObject("releaseRange", app.MinMax()) + + connect(self, "In1", gate, "In") + connect(gate, "Out", ar, "Gate") + connect(loop, "Out", ar, "Loop") + connect(ar, "Out", self, "Out1") + + connect(attack, "Out", ar, "Attack") + connect(release, "Out", ar, "Release") + + connect(attack, "Out", attackRange, "In") + connect(release, "Out", releaseRange, "In") + + self:addMonoBranch("loop", loop, "In", loop, "Out") + self:addMonoBranch("attack", attack, "In", attack, "Out") + self:addMonoBranch("release", release, "In", release, "Out") +end + +function AR:loadStereoGraph() + self:loadMonoGraph() + connect(self.objects.ar, "Out", self, "Out2") +end + +local views = { + expanded = { + "input", + "loop", + "attack", + "release" + }, + collapsed = {} +} + +function AR:onLoadViews(objects, branches) + local controls = {} + + controls.input = InputGate { + button = "input", + description = "Unit Input", + comparator = objects.gate + } + + controls.loop = Gate { + button = "loop", + description = "Loop", + branch = branches.loop, + comparator = objects.loop + } + + controls.attack = GainBias { + button = "A", + branch = branches.attack, + description = "Attack", + gainbias = objects.attack, + range = objects.attackRange, + biasMap = Encoder.getMap("ADSR"), + biasUnits = app.unitSecs, + initialBias = 0.050 + } + + controls.release = GainBias { + button = "R", + branch = branches.release, + description = "Release", + gainbias = objects.release, + range = objects.releaseRange, + biasMap = Encoder.getMap("ADSR"), + biasUnits = app.unitSecs, + initialBias = 0.100 + } + + return controls, views +end + +return AR diff --git a/mods/example/assets/toc.lua b/mods/example/assets/toc.lua new file mode 100644 index 00000000..d82624ff --- /dev/null +++ b/mods/example/assets/toc.lua @@ -0,0 +1,13 @@ +return { + title = "Example Library", + author = "tomf", + name = "example", + keyword = "", + units = { + { + title = "AR", + moduleName = "AR", + keywords = "" + } + } +} \ No newline at end of file diff --git a/mods/example/example.cpp.swig b/mods/example/example.cpp.swig new file mode 100644 index 00000000..696e95b6 --- /dev/null +++ b/mods/example/example.cpp.swig @@ -0,0 +1,14 @@ +%module example_libexample +%include + +%{ + +#undef SWIGLUA + +#include + +#define SWIGLUA + +%} + +%include diff --git a/od/extras/AlignmentAllocator.h b/od/extras/AlignmentAllocator.h index c0ecdef9..6a1b86f2 100644 --- a/od/extras/AlignmentAllocator.h +++ b/od/extras/AlignmentAllocator.h @@ -1,7 +1,6 @@ #pragma once #include -#include #include #include @@ -42,7 +41,9 @@ namespace od inline pointer allocate(size_type n) { - return (pointer)memalign(N, n * sizeof(value_type)); + pointer p; + posix_memalign((void **)&p, N, n * sizeof(value_type)); + return p; } inline void deallocate(pointer p, size_type) diff --git a/od/extras/BufferPool.h b/od/extras/BufferPool.h index 2bde9dad..513ed9f3 100644 --- a/od/extras/BufferPool.h +++ b/od/extras/BufferPool.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include #include @@ -27,7 +27,7 @@ namespace od { deallocate(); uint32_t poolSizeInBytes = bufferCount * bufferSize * sizeof(T); - mPool = (T *)memalign(CACHELINE_SIZE_MAX, poolSizeInBytes); + posix_memalign((void **)&mPool, CACHELINE_SIZE_MAX, poolSizeInBytes); if (mPool) { bzero(mPool, poolSizeInBytes); diff --git a/od/extras/SystemBuffer.cpp b/od/extras/SystemBuffer.cpp index c236e319..f31edb7f 100644 --- a/od/extras/SystemBuffer.cpp +++ b/od/extras/SystemBuffer.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include namespace od { @@ -17,7 +17,7 @@ namespace od bool SystemBuffer::allocate(int n) { deallocate(); - mpData = (char *)memalign(CACHELINE_SIZE_MAX, n); + posix_memalign((void **)&mpData, CACHELINE_SIZE_MAX, n); if (mpData) { mSizeInBytes = n; diff --git a/od/glue/Interpreter.cpp b/od/glue/Interpreter.cpp index 88c679b7..a2d0c22a 100644 --- a/od/glue/Interpreter.cpp +++ b/od/glue/Interpreter.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include extern "C" { diff --git a/scripts/darwin.mk b/scripts/darwin.mk new file mode 100644 index 00000000..36ba5c7c --- /dev/null +++ b/scripts/darwin.mk @@ -0,0 +1,15 @@ +# Build Tools for OSX +CC := gcc-10 -fdiagnostics-color -fmax-errors=5 +CPP := g++-10 -fdiagnostics-color -fmax-errors=5 +OBJCOPY := objcopy +OBJDUMP := objdump +ADDR2LINE := addr2line +LD := ld +AR := gcc-ar-10 +SIZE := size +STRIP := strip +READELF := readelf +NM := nm +SWIG := swig +PYTHON := python3 +ZIP := zip \ No newline at end of file diff --git a/scripts/emu.mk b/scripts/emu.mk index d224b22b..cca4fed1 100644 --- a/scripts/emu.mk +++ b/scripts/emu.mk @@ -1,4 +1,3 @@ -ARCH=linux include scripts/env.mk include scripts/utils.mk @@ -23,11 +22,26 @@ objects := $(addprefix $(out_dir)/,$(c_sources:%.c=%.o) $(cpp_sources:%.cpp=%.o) # Manually add objects objects += $(out_dir)/od/glue/app_swig.o objects += $(out_dir)/libs/SDL_FontCache/SDL_FontCache.o - + +ifeq ($(ARCH),linux) +LFLAGS += -Wl,--export-dynamic -Wl,--gc-sections +endif + +ifeq ($(ARCH),darwin) +# Locate our deps using brew +sdl2 := $(shell brew --prefix sdl2) +sdl2_ttf := $(shell brew --prefix sdl2_ttf) +fftw := $(shell brew --prefix fftw) + +CFLAGS += -rdynamic +CFLAGS += -I$(sdl2)/include -I$(sdl2)/include/SDL2 -I$(sdl2_ttf)/include +LFLAGS += -L$(sdl2)/lib -L$(sdl2_ttf)/lib -L$(fftw)/lib +endif + CFLAGS += -DFIRMWARE_VERSION=\"$(FIRMWARE_VERSION)\" CFLAGS += -DFIRMWARE_NAME=\"$(FIRMWARE_NAME)\" CFLAGS += -DFIRMWARE_STATUS=\"$(FIRMWARE_STATUS)\" -LFLAGS = -Wl,--export-dynamic -Wl,--gc-sections -lSDL2 -lSDL2_ttf -lfftw3f -lm -ldl -lstdc++ +LFLAGS += -lSDL2 -lSDL2_ttf -lfftw3f -lm -ldl -lstdc++ all: $(out_dir)/$(program_name).elf @@ -51,13 +65,13 @@ missing: $(objects) $(libraries) @$(PYTHON) list-undefined.py $(out_dir)/error.log > $(out_dir)/missing.log libs: - +$(MAKE) -f lua.mk ARCH=linux - +$(MAKE) -f miniz.mk ARCH=linux - +$(MAKE) -f lodepng.mk ARCH=linux + +$(MAKE) -f lua.mk + +$(MAKE) -f miniz.mk + +$(MAKE) -f lodepng.mk clean-libs: - +$(MAKE) -f lua.mk clean ARCH=linux - +$(MAKE) -f miniz.mk clean ARCH=linux - +$(MAKE) -f lodepng.mk clean ARCH=linux + +$(MAKE) -f lua.mk clean + +$(MAKE) -f miniz.mk clean + +$(MAKE) -f lodepng.mk clean include scripts/rules.mk diff --git a/scripts/env.mk b/scripts/env.mk index 6f6d2e2e..c695e7d8 100644 --- a/scripts/env.mk +++ b/scripts/env.mk @@ -1,14 +1,31 @@ - -ARCH ?= am335x -#ARCH = linux -PROFILE ?= testing -#PROFILE = release -#PROFILE = debug - FIRMWARE_NAME ?= Thoon FIRMWARE_VERSION ?= 0.6.02 FIRMWARE_STATUS ?= unstable +# Determine ARCH if it's not provided... +# linux | darwin | am335x +ifndef ARCH + SYSTEM_NAME := $(shell uname -s) + ifeq ($(SYSTEM_NAME),Linux) + ARCH = linux + else ifeq ($(SYSTEM_NAME),Darwin) + ARCH = darwin + else + $(error Unsupported system $(SYSTEM_NAME)) + endif +endif + +# Use the linux source files unless we're building am335x +arch_source = linux +ifeq ($(ARCH),am335x) + arch_source = am335x +endif + + +# Determine PROFILE if it's not provided... +# testing | release | debug +PROFILE ?= testing + scriptname := $(word 1, $(MAKEFILE_LIST)) scriptname := $(scriptname:scripts/%=%) @@ -24,7 +41,7 @@ describe_env = $(blueON)[$(scriptname) $(ARCH) $(PROFILE)]$(blueOFF) # Frequently used paths build_dir = $(PROFILE)/$(ARCH) libs_build_dir = $(build_dir)/libs -arch_dir = arch/$(ARCH) +arch_dir = arch/$(arch_source) mods_dir = mods od_dir = od libs_dir = libs @@ -47,6 +64,12 @@ CFLAGS.size = -Os symbols = includes = +# Default card locations +front_card_label = front +front_card_dir = ~/.od/$(front_card_label) +rear_card_label = rear +rear_card_dir = ~/.od/$(rear_card_label) + ########################### #### am335x-specific @@ -79,15 +102,23 @@ CFLAGS.release ?= $(CFLAGS.speed) -Wno-unused CFLAGS.testing ?= -g -DBUILDOPT_TESTING CFLAGS.debug ?= -g -DBUILDOPT_TESTING -front_card_label = front -front_card_dir = ~/.od/$(front_card_label) -rear_card_label = rear -rear_card_dir = ~/.od/$(rear_card_label) - include scripts/linux.mk # symbols += BUILDOPT_LUA_USE_REALLOC CFLAGS.linux = -Wno-deprecated-declarations -msse4 -fPIC + +endif + +### darwin-specific +ifeq ($(ARCH),darwin) + +CFLAGS.release ?= $(CFLAGS.speed) -Wno-unused +CFLAGS.testing ?= -g -DBUILDOPT_TESTING +CFLAGS.debug ?= -g -DBUILDOPT_TESTING + +include scripts/darwin.mk + +CFLAGS.darwin = -Wno-deprecated-declarations -msse4 -fPIC endif ########################### diff --git a/scripts/example.mk b/scripts/example.mk new file mode 100644 index 00000000..1e9883ef --- /dev/null +++ b/scripts/example.mk @@ -0,0 +1,9 @@ +include scripts/env.mk + +MODNAME := example +src_dir = $(mods_dir)/$(MODNAME) +asset_dir = $(src_dir)/assets + +includes += . $(mods_dir) $(arch_dir) $(lua_dir) + +include scripts/mod-builder.mk diff --git a/scripts/libemu.mk b/scripts/libemu.mk index 7f1567ee..08f1c545 100644 --- a/scripts/libemu.mk +++ b/scripts/libemu.mk @@ -1,4 +1,3 @@ -ARCH=linux include scripts/env.mk include scripts/utils.mk @@ -24,9 +23,23 @@ objects := $(addprefix $(out_dir)/,$(c_sources:%.c=%.o) $(cpp_sources:%.cpp=%.o) objects += $(out_dir)/od/glue/app_swig.o objects += $(out_dir)/emu/emu_swig.o objects += $(out_dir)/libs/SDL_FontCache/SDL_FontCache.o - + +ifeq ($(ARCH),linux) +LFLAGS += --gc-sections +endif + +ifeq ($(ARCH),darwin) +# Locate our deps using brew +sdl2 := $(shell brew --prefix sdl2) +sdl2_ttf := $(shell brew --prefix sdl2_ttf) +fftw := $(shell brew --prefix fftw) + +CFLAGS += -I$(sdl2)/include -I$(sdl2)/include/SDL2 -I$(sdl2_ttf)/include +LFLAGS += -L$(sdl2)/lib -L$(sdl2_ttf)/lib -L$(fftw)/lib +endif + CFLAGS += -fpic -LFLAGS = -shared -Wl,--gc-sections -lSDL2 -lSDL2_ttf -lfftw3f -lm -ldl -lstdc++ +LFLAGS += -lSDL2 -lSDL2_ttf -lfftw3f -lm -ldl -lstdc++ all: $(out_dir)/$(program_name).so @@ -40,13 +53,13 @@ clean: # WARNING. This will overwrite the shared lib build dir. Needs to be fixed. libs: - +CFLAGS=-fpic $(MAKE) -f lua.mk ARCH=linux - +CFLAGS=-fpic $(MAKE) -f miniz.mk ARCH=linux - +CFLAGS=-fpic $(MAKE) -f lodepng.mk ARCH=linux + +CFLAGS=-fpic $(MAKE) -f lua.mk + +CFLAGS=-fpic $(MAKE) -f miniz.mk + +CFLAGS=-fpic $(MAKE) -f lodepng.mk clean-libs: - +$(MAKE) -f lua.mk clean ARCH=linux - +$(MAKE) -f miniz.mk clean ARCH=linux - +$(MAKE) -f lodepng.mk clean ARCH=linux + +$(MAKE) -f lua.mk clean + +$(MAKE) -f miniz.mk clean + +$(MAKE) -f lodepng.mk clean include scripts/rules.mk diff --git a/scripts/mod-builder.mk b/scripts/mod-builder.mk index 94d5c0d5..8569f1e1 100644 --- a/scripts/mod-builder.mk +++ b/scripts/mod-builder.mk @@ -62,6 +62,11 @@ ifeq ($(ARCH),linux) LFLAGS = -shared endif +ifeq ($(ARCH),darwin) +# Do not try to resolve dynamic links when linking. +LFLAGS = -dynamic -undefined dynamic_lookup -lSystem +endif + # Prevent swig from placing symbols exported by mods in the global namespace. SWIGFLAGS += -nomoduleglobal -small -fvirtual