Repository navigation
developer_guide
When extending the Polyend Tracker Community Edition (CE) firmware, adding new synthesizer engines, or writing Sample Editor effects, keep the following hardware constraints and non-obvious architectural details in mind.
- Memory Budget & Free Headroom
- Shared
768 KBScratch Buffer Layout (externalRamScratchBuff) - Copy-on-Write
/Workspace/instruments/, Incremental Project Saver & Hybrid SD Streaming - Synthesizer Engine Architecture & Guidelines (Tracker+ & Tracker Mini)
- Sample Editor &
.ptfxPlugin Constraints - UI, FT812 Display, Config & Bootloader Gotchas
- Conditional Compilation: Targeting Specific Platforms or Devices
| Platform & Memory Region | Total Capacity | Current Usage | Immediately Free | Theoretically Reclaimable | What Lives Here & Developer Notes |
|---|---|---|---|---|---|
Original (MK66) - FLASH |
1,024 KB |
~871 KB (85.1%) |
~153 KB |
— | Code, .rodata, .audio_ram_functions, compressed fonts & bitmaps. |
Original (MK66) - RAM (Internal SRAM) |
256 KB |
~128 KB (50.1%) |
~128 KB |
— | Stack, heap, .data, and real-time .bss. Cold UI/FileManager singletons live in EXTERNAL_RAM. |
Original (MK66) - EXTERNAL_RAM (SDRAM) |
16,384 KB |
~15,222 KB (92.9%) |
~1,162 KB (1.13 MB) |
+3.5–4.0 MB (up to ~5.1 MB total)
|
11.25 MB SAMPLE_MEMORY_SIZE (7.5 MB mono sample pool + 3.75 MB FX edit buffer) + 1.5 MB delay + 768 KB shared externalRamScratchBuff + VoiceStreamManager ring buffers + cold UI singletons. |
Plus / Mini (IMX) - QSPI_FLASH |
~16,200 KB |
~1,620–1,650 KB (10.0–10.2%) |
~14,570 KB |
— | XIP Flash; plenty of room for code, lookup tables, and assets. |
Plus / Mini (IMX) - SRAM_ITC (RAM2) |
128 KB |
~105.4 KB (82.4%) |
~22.5 KB |
— | Zero-wait-state instruction TCM (.ramfunc.$RAM2 / .audio_ram_functions hot DSP loops). |
Plus / Mini (IMX) - SRAM_DTC (RAM) |
352 KB |
~330–331 KB (93.9–94.0%) |
~21–22 KB |
— | Main stack, heap, .data, and real-time .bss. Keep large or non-realtime buffers in EXTERNAL_RAM. |
Plus / Mini (IMX) - SRAM_OC (RAM3) |
32 KB |
~22.7 KB (70.8%) |
~9.3 KB |
— | Non-cacheable OCRAM used for USB/SDMA buffers and audioRecBuff. |
Plus / Mini (IMX) - EXTERNAL_RAM (RAM4) |
65,536 KB |
~65,528 KB (99.99%) |
~8 KB |
+29.0 MB (up to ~29.0 MB total)
|
60 MB SAMPLE_MEMORY_SIZE (45 MB stereo sample pool + 15 MB FX edit buffer) + 1.5 MB delay + 768 KB shared externalRamScratchBuff + VoiceStreamManager ring buffers + 64 KB g_wtEnvelopeBank. |
By default, SAMPLE_MEMORY_SIZE in core/source/mtStructs.h is left at its full initial factory allocation so nothing is restricted out of the box:
-
Original Tracker (
MK66):SAMPLE_MEMORY_SIZE = 45 * 256 * 1024(11.25 MB, comprising a7.5 MBresident mono sample pool plus3.75 MBEDIT_BUFF_SIZEreserved at the top for offline Sample Editor effects). -
Tracker+ & Tracker Mini (
IMX):SAMPLE_MEMORY_SIZE = 60 * 1024 * 1024(60 MB, comprising a45 MBresident stereo sample pool plus15 MB2 * SAMPLE_CHANNELS * EDIT_BUFF_SIZEreserved at the top for offline Sample Editor effects).
However, because Hybrid SD Card Sample Streaming (core/AudioEngine/VoiceStreamManager.cpp) streams samples >= 256 KB (kStreamThresholdBytes) directly from the SD card while only allocating a 32,768-frame (64 KB per channel) pre-cache in externalRamSampleMemory:
-
Future developers can chip away at
SAMPLE_MEMORY_SIZEwhenever a new feature requires additionalEXTERNAL_RAM, simply by loweringSAMPLE_MEMORY_SIZEincore/source/mtStructs.h:- On Tracker+ / Tracker Mini (
IMX), reducingSAMPLE_MEMORY_SIZEfrom60 MBdown to31 MB(31 * 1024 * 1024, keeping the15 MBFX edit buffer + a16 MBresident sample pool for short samples, pre-caches, and Wavetable/Granular instruments) immediately frees~29 MBofEXTERNAL_RAM. - On Original Tracker (
MK66), reducingSAMPLE_MEMORY_SIZEfrom11.25 MB(45 * 256 * 1024) down to7.75 MB(31 * 256 * 1024, keeping the3.75 MBFX edit buffer + a4.0 MBresident sample pool) frees3.5 MBof additionalEXTERNAL_RAMon top of the1.13 MBalready unassigned (~4.63 MBtotal freeEXTERNAL_RAM).
- On Tracker+ / Tracker Mini (
-
Important when adjusting
SAMPLE_MEMORY_SIZE: Always keepSAMPLE_MEMORY_SIZE > 2 * SAMPLE_CHANNELS * EDIT_BUFF_SIZE(> 3.75 MBonMK66,> 15 MBonIMX) becauseEDIT_BUFF_OFFSET(externalRamEffectsBuff) is carved out of the top ofexternalRamSampleMemory.
Important (
SRAM_DTC/ InternalRAMvsEXTERNAL_RAM):
- Default
.bsslands inRAMon Original Tracker (MK66) andSRAM_DTCon Tracker+ / Tracker Mini (IMX), while__NOINIT(EXTERNAL_RAM)lands inEXTERNAL_RAM(.noinit_RAM4).- Because
.noinit_RAM4isNOLOAD(not zeroed by startup code before C++ static constructors run), any C++ singleton or state struct moved to__NOINIT(EXTERNAL_RAM)must be explicitly zeroed (memset) or Placement-newconstructed inTrackerImpl::init()before use.- Modal or mutually-exclusive features that only run when SD audio preview, offline stem export, and
.ptfxoffline execution are idle can shareexternalRamScratchBuff(768 KB) rather than declaring a new static buffer in.bssorEXTERNAL_RAM.
Defined in core/source/Tracker.cpp (SHARED_SCRATCH_MEMORY_SIZE = 768 * 1024 in core/source/mtStructs.h), the 768 KB externalRamScratchBuff array in EXTERNAL_RAM (.scratch_memory) is shared across mutually-exclusive subsystems (PtfxLoader / PtfxManager, mtAudioExport renderBuffer, mtAudioEngine sdStream, cProjectEditor file browser, and cInstrumentEditor synth patch browser).
When .ptfx Modular Sample Editor plugins are active, the 768 KB region is partitioned as:
Offset 0 KB 128 KB 768 KB
├─────────────────────────┼─────────────────────────────┤
│ .ptfx Code │ .ptfx Scratch Working RAM │
│ (128KB IMX / 32KB MK66) │ (640KB) │
└─────────────────────────┴─────────────────────────────┘
-
kPtfxScratchTopOffsetincore/effector/ptfx_loader.hcaps.ptfxplugin scratch usage at768 KB(SHARED_SCRATCH_MEMORY_SIZE), whileg_wtEnvelopeBank(64 KB) resides in its own dedicatedEXTERNAL_RAMarray incore/source/mtWavetableEnvelopes.cpp.
To avoid copying 13–45 MB of PCM sample payloads from /Projects/<Path>/<Name>/instruments/*.pti to /Workspace/instruments/instrument_%02d.pti on every project open and save, the FileManager uses a Header-Only Copy-on-Write (CoW) model paired with Hybrid SD Card Sample Streaming:
-
Project Open (
ProjectOpen::copyInstruments):- Copies only the 392-byte
strInstrumentFileheader (cFileTransfer::copyInstrumentHeader) from/Projects/<Path>/<Name>/instruments/*.ptiinto/Workspace/instruments/instrument_%02d.pti.
- Copies only the 392-byte
-
Sample Streaming & Reload (
WorkspaceProjectLoad&SampleMemoryReload):- In
cFileManager::startNewInstrumentSampleLoad()andcFileManager::loadSampleData(), if a/Workspace/instruments/instrument_%02d.ptifile hasfileSize <= sizeof(strInstrumentFile)(header-only), the loader resolves its backing.ptifile in/Projects/<Path>/<Name>/instruments/viacFileManager::resolveProjectInstrumentPtiPath()and loads or streams the PCM sample data directly from the project folder (respectingcFileManager::getPtiFileDataOffset()for both current 392-byte headers and legacy firmware< v8smaller headers).
- In
-
Copy-on-Write Promotion (
WorkspaceProjectSave& Sample Edits):- Parameter tweaks (
AutoSave/WorkspaceProjectSave) only rewrite the 392-byte header in/Workspace/instruments/instrument_%02d.ptiwhen!isInstrumentSampleChanged(idx), preserving its header-only status. - Whenever an instrument's audio is newly imported, recorded, rendered, copied (
InstrumentCopy), or modified in the Sample Editor (cFileManager::saveSampleDataToWorkspace), a full.ptifile (header + PCM audio) is written to/Workspace/instruments/instrument_%02d.pti.
- Parameter tweaks (
-
Incremental
Save Projectvs. FullSave As(ProjectSave::copyInstruments):-
Same-Project Save (
isSavingToSameProject == true): Deletes deactivated slots, copies full.ptifiles from/Workspace/only for slots whose audio was modified, and for unmodified header-only slots updates the 392-bytestrInstrumentFileheader in-place (skipping the write entirely if all 392 bytes are identical) and renames the file in-place ifsample.file_namechanged. -
Save Asto a New Project (isSavingToSameProject == false): Copies full.ptifiles from/Workspace/where present, and writes the updatedstrInstrumentFileheader plus the raw PCM sample payload directly fromexternalRamSampleMemory(or streams it in chunks from the backing.ptifile for SD-streamed instruments) for header-only slots so the new project folder is completely self-contained.
-
Same-Project Save (
-
Hybrid SD Card Sample Streaming Architecture (
VoiceStreamManager&isPlayModeStreamable):-
Threshold & SDRAM Pre-Cache: Instruments whose PCM payload is
>= 256 KB(kStreamThresholdBytesincore/source/mtStructs.h) and whose play mode satisfiesisPlayModeStreamable(playMode)allocate onlykStreamPreCacheFrames = 32768frames (~743 msat44.1 kHz) per channel (64 KBmono /128 KBstereo) inexternalRamSampleMemory. -
Zero-Latency Trigger & Background Ring Buffers: When a note is triggered, the audio ISR (
AudioPlayMemory::update()incore/libs/Audio/play_memory.cpp) immediately plays from the SDRAM pre-cache whileVoiceStreamManager::update()(core/AudioEngine/VoiceStreamManager.cpp) refills the active voice's16,384-frame (kRingFrames) ring buffer in4,096-frame (kChunkFrames) chunks on the main thread using FatFs FastSeek cluster link maps (CLMT) and direct LBA sector reads. -
Loop Wrap & Direction Support: Supports forward, backward, and ping-pong looping (
VoiceStreamManager::prepareLoopWrappre-fetches the loop boundary before the playhead reaches the wrap point) as well asR(Reverse) andP(Position) pattern step FX. -
Platform Differences (
PLATFORM_IMXvs.MK66):-
Tracker+ & Tracker Mini (
PLATFORM_IMX):isPlayModeStreamable()returnstrueforOne-Shot,Forward Loop,Backward Loop,Ping-Pong Loop,Slice, andBeat Slice, andfalseonly forWavetableandGranular. ForSliceandBeat Sliceinstruments, the32,768-frame SDRAM pre-cache is partitioned into a16,384-frame linear attack region ([0 .. 16383]) plus per-slice SDRAM pre-cache windows across the upper16,384frames (VoiceStreamManager::refreshInstrumentSliceCache/refreshInstrumentSingleSliceCache), allowing any slice to start immediately from SDRAM while the600 MHzCortex-M7 refills the voice ring buffer. -
Original Tracker (
MK66):isPlayModeStreamable()returnstrueforOne-Shot,Forward Loop,Backward Loop, andPing-Pong Loop, andfalseforSlice,Beat Slice,Wavetable, andGranular. Because partitioning16,384frames across10–48slices yields smaller per-slice pre-cache windows (~7.6–37 ms), and the180 MHzCortex-M4 spends~20–35 msper step on FT812 SPI pattern redraws and Song Mode pattern reads, keepingSliceandBeat Sliceinstruments 100% resident in SDRAM onMK66guarantees dropout-free multi-track slice playback while non-sliced instruments enjoy the full743 mslinear pre-cache.
-
Tracker+ & Tracker Mini (
-
Automatic Promotion & Demotion (
Sample Editor&Play ModeSwitching):- Entering the Sample Editor (
cSampleEditor) or switching an instrument to a non-streamable play mode (!isPlayModeStreamable(newPlayMode)infSamplePlay.cpp) callscFileManager::promoteStreamedInstrumentToRam(idx), loading the full PCM payload intoexternalRamSampleMemory. - Applying an offline Sample Editor effect or saving sample edits (
cFileManager::saveSampleDataToWorkspace) writes the updated full.ptito/Workspace/instruments/instrument_%02d.pti, recomputes the600-point waveform peak cache (WaveformPeakPoint), and callscFileManager::demoteRamInstrumentToStream(idx)to return the instrument to hybrid SD streaming.
- Entering the Sample Editor (
-
Threshold & SDRAM Pre-Cache: Instruments whose PCM payload is
-
Binary
.ptiHeader Compatibility (sizeof(strInstrument) == 372) & SharedenvWtPos/envGranLenAutomation Slot:- Because
strInstrumentFile(392bytes) is serialized directly into.ptifiles and Copy-on-Write/Workspace/instruments/headers,sizeof(strInstrument)incore/source/mtStructs.his enforced at372bytes viastatic_assert(sizeof(strInstrument) == 372). - Instrument structure versions
1–7may use the legacy368-byte metadata layout; versions8–9use372bytes. The 4-byte CRC field immediately follows the serialized metadata (though metadata-only legacy files may omit it). Loaders validate the header magic, version bounds, and metadata/file sizes before version translation, rejecting truncated, oversized, malformed, or newer-version metadata. -
Wavetable (
playModeWavetable) and Granular (playModeGranular) are mutually exclusive playback modes on an instrument. Therefore, Granular Length automation (envGranLen) shares envelope/LFO hardware storage slot3(envWtPos = 3,envGranLen = envWtPos) with Wavetable Position:- In the UI (
Instrument Automation 2/2), the 7 destinations are indexed byenAutomationDest(autoDestVolume,autoDestPanning,autoDestCutoff,autoDestWtPos,autoDestGranPos,autoDestGranLen,autoDestFinetune,autoDestCount = 7) and mapped to the 6 underlyingenvelope[6]/lfo[6]storage slots viaautomationDestToEnvSlot(uint8_t destIdx). - Enable state in
envelope[3].enableuses separate bitmask flags (kEnvEnableWtPosBit = 0x01forWavetable Position,kEnvEnableGranLenBit = 0x02forGranular Length) viastrInstrument::isWtPosEnvEnabled(),strInstrument::isGranLenEnvEnabled(),strInstrument::isEnvEnabled(envIdx),strInstrument::isAutomationDestEnabled(destIdx), andstrInstrument::setAutomationDestEnabled(destIdx, enabled). - Because all legacy
.ptifiles only ever wrote0or1(0x01) toenvelope[3].enable, existing.ptifiles load withisGranLenEnvEnabled() == false(Off) while preserving legacy Wavetable Position automation 100%. Always use theenvGranLenalias andisGranLenEnvEnabled()helper in granular code paths rather than rawenvWtPosor.enablechecks.
- In the UI (
- Because
Full details in docs/custom_synth_sdk.md.
-
No Hard Limit on Number of Registered Synth Engines:
-
InstrumentTypeRegistry(synth/include/PolySynth/sdk/InstrumentTypeRegistry.h) stores engines dynamically in astd::unordered_map<int, std::shared_ptr<InstrumentType>>, andInstrumentType::createVoice(synth/include/PolySynth/sdk/InstrumentType.h) instantiates voices on demand viastd::unique_ptr<InstrumentVoice>only for the 3 active synth slots (Synth 1–Synth 3). - This means the community can register any number of new open-source synth engines in
core/synth/registry.cppwithout ever needing to recompilelibPolySynth.aorlibPolyDSP.a.
-
-
Keep Inactive Engine RAM Footprint Near Zero (
CustomSynthVoice/ParamHelper):- Because all registered synth engines exist in
InstrumentTypeRegistryat boot, avoid storing per-parameterstd::functionobjects (32 byteseach inSRAM_DTC) on your voice class. - Inherit from
polysynth::sdk::CustomSynthVoice<VoiceClass, ParamIdEnum>(synth/include/PolySynth/sdk/SynthVoiceSDK.h), which uses a static table of stateless function pointers (4 bytesper parameter) and handles MIDI note stacks (Always/Overlap/Legato) automatically. - Place any large shared wavetables or lookup tables in
QSPI_FLASH(constexpr) or inEXTERNAL_RAM.
- Because all registered synth engines exist in
-
FT812
RAM_GBitmap Budget When Adding Synth Icons:- Each synth engine uses an
80×28(560 BL2, or80×29580 BL2) mini icon and a108×40(1,080 BL2) medium icon incore/libs/NewDisplay/display.cpp, stored in FT812RAM_GbelowcontrolsRamStartAddress(150,000incore/libs/NewDisplay/displayStructs.h). - Currently
RAM_Gbitmaps are allocated up to address128,780, leaving~21,220bytes ofRAM_G(~12additional pairs of mini + medium synth pill icons) beforecontrolsRamStartAddress(150,000) is reached.
- Each synth engine uses an
-
Checklist When Adding a New Synth Engine:
- Add a new enumerator to
InstrumentTypeId(beforekLastSynth, and updatekLastSynth) insynth/include/PolySynth/config.h, and register its factory inInstrumentTypeRegistry::registerInstrumentTypes()incore/synth/registry.cpp. - Add the engine's
InstrumentTypeIdentry toSynth::kSynthTypesincore/synth/Synth.h. - Add the display name and
enDisplayBitmapsmini icon ID tosynthModelNames[]andsynthModelListImages[]incore/interface/instrumentEditor/SynthEditor.cpp, and add the medium icon ID tosynthModelListImages[]incore/interface/instrumentEditor/SynthPatchEditor.cpp. - Register the enum IDs in
enDisplayBitmapsincore/libs/NewDisplay/displayStructs.hand add the80×28(L2) mini and108×40(L2) medium pill bitmaps tobitmaps[]incore/libs/NewDisplay/display.cpp.
- Add a new enumerator to
Full details in docs/modular_effects_system.md.
-
Plugin & Parameter Limits:
- Up to 128
.ptfxplugins (kMaxModularPlugins = 128incore/effector/ptfx_manager.h) are indexed from/Effects/alongside the 17 built-in Sample Editor effects (kBuiltInEffectsCount = 17,145total list items ins_effectDisplayNames). - Each
.ptfxplugin supports up to 12 parameters (PtfxHeader::params[12]incore/effector/tracker_plugin.handeditor-fx-sdk/tracker_plugin.h), displayed in the Sample Editor across up to 3 pages of 4 parameters via theMorescreen button.
- Up to 128
-
.ptfxCode+BSS Limits (32 KBon MK66 vs128 KBon IMX):- Both platforms execute
.ptfxplugin code from the base ofexternalRamScratchBuff([0 .. 32 KB]on Original TrackerMK66with the Kinetis System MPU disabled viaMPU_CESR = 0, and[0 .. 128 KB]on Tracker+ / Tracker MiniIMXafter cleaning L1 D-Cache and invalidating I-Cache inPtfxLoader::syncInstructionCache()). - Working scratch memory (
scratch_mem,640 KB) occupiesexternalRamScratchBuff + 128 KB([128 KB .. 768 KB]) on both platforms. - Plugins with
code_size + bss_size > 32 KB(or requiring 600 MHz Cortex-M7 speeds) should declarePTFX_FLAG_IMX_ONLY.
- Both platforms execute
-
SD Card DMA Alignment Pitfall on IMX (
FatFs+USDHC):- On IMX (
platforms/imx/),FatFs(f_read) bypasses its internal aligned DTCM sector buffer whenever a read request is>= 512bytes (cc = btr / 512 > 0) and passes the caller's destination pointer directly to the USDHC DMA controller. - If the destination buffer is not 4-byte aligned or lies in a non-DMA-accessible TCM region,
f_readfails withFR_DISK_ERR. Always use 4-byte aligned buffers inSRAM_DTC/EXTERNAL_RAM, or read in<= 256-byte chunks to forceFatFsthrough its internal bounce buffer.
- On IMX (
-
Do Not Shift
Interface::modules[]Indices (core/interface/core/interface.cpp):- UI navigation references
mtInterface.modules[]by hardcoded index (modules[9]=performanceMode,modules[10]=imageViewer,modules[12]=masterParams). Slotmodules[11](formerly the NES emulatorgameModule) is intentionally kept asnullptrso higher indices never shift.
- UI navigation references
-
FT812 Font Buffer Cap (
22,396Bytes) & Embedded Hardware Icons:-
kMaxFontBufferSizeincore/libs/NewDisplay/display.cppis22,396bytes (decompressedFontsCommonBuffer). Every individual font slot (both built-in RLE-compressed fonts and.ptfontslots on SD) must decompress to<= 22,396bytes. -
Font Slot 4 (
17px Bold, FT812 Handle 4) embeds 8 custom hardware icons at ASCII0x18..0x1F(24..31:Pause,Stop,Play,Rec,Folder,Up-dir,Loop,Arrow). If these are missing from a font, transport bar and file browser icons will appear blank. -
Font Slot 5 (
12px Regular, FT812 Handle 5) embeds Polish diacritics at ASCII0x11..0x1F(17..31).
-
-
Bootloader
.ptfFilename Filter & 31-Character Limit:- The firmware updater (
enListFileFilter_firmwareinplatforms/mk66/3rdparty/SD/SD.cppandplatforms/imx/sdmmc/sd/SD.cpp) only lists files in/Firmware/that end with.ptf, have total length>= 15, and start with:-
PolyendTrac(Original Tracker) -
TrackerPlus(Tracker+) -
TrackerMini(Tracker Mini)
-
-
31-Character Maximum on Original Tracker:
PlatformImpl::runBootloader()(platforms/mk66/source/PlatformImpl.cpp/platforms/imx/source/PlatformImpl.cpp) writes the selected.ptffilename to/Firmware/_fwinfo. The Original Tracker's on-chip bootloader reads/Firmware/_fwinfointo a 32-bytechar[32]buffer. Filenames of 32+ characters overwrite the trailing\0byte and cause garbage symbols on the bootloader flashing screen. Always keep.ptffilenames<= 31characters.
- The firmware updater (
All three devices share the same core/ codebase and are differentiated at compile time by preprocessor defines set in core/makefile, platforms/mk66/makefile, and platforms/imx/makefile.
| Target Scope | Preprocessor Condition | Matching Hardware & Typical Use Case |
|---|---|---|
| IMX Only (Tracker+ & Mini) | #ifdef PLATFORM_IMX |
600 MHz Cortex-M7, 64 MB SDRAM, stereo samples (SAMPLE_CHANNELS == 2), 16 tracks. |
| MK66 Only (Original Tracker) | #ifndef PLATFORM_IMX |
180 MHz Cortex-M4F, 16 MB SDRAM, mono samples (SAMPLE_CHANNELS == 1), 16 tracks. |
| Tracker Mini Only | #ifdef TRACKER_MINI |
Handheld controls (interfaceButtonMiniMiddle, D-pad, battery gauge, internal mic, no pad grid). |
| Desktop Form Factor (Original & Plus) | #ifndef TRACKER_MINI |
Shared desktop hardware: 48 RGB silicone pads, rotary jog-wheel, FM radio, line/mic inputs. |
| Tracker+ Exclusively | #if defined(PLATFORM_IMX) && !defined(TRACKER_MINI) |
Features requiring both the IMX CPU/RAM and the 48-pad desktop interface. |
| Synth Audio Engine | #ifdef FEATURE_SYNTH |
Defined when PLATFORM=IMX; enables PolySynth and sets kSynthParts = 3 in core/config/config.h. |
| Synth UI Screens | #if GUI_HANDLE_SYNTH |
Defined as 1 (on PLATFORM_IMX) or 0 (on MK66) in core/interface/core/interfaceDefs.h. |
#if defined(PLATFORM_IMX)
// Runs on Tracker+ and Tracker Mini (600 MHz Cortex-M7)
#if defined(TRACKER_MINI)
// Tracker Mini only
#else
// Tracker+ only
#endif
#else
// Runs exclusively on Original Tracker (180 MHz Kinetis MK66)
#endif-
Gotchas with Preprocessor Guards:
-
Never use
#ifdef __MK66FX1M0__insidecore/: For legacy Teensy Audio library compatibility,core/makefiledefines-D__MK66FX1M0__in its baseDEFINESfor bothMK66andIMXbuilds. Always use#ifndef PLATFORM_IMX(or#if !defined(PLATFORM_IMX)) when writing code exclusively for the Original Tracker. -
Use
#if GUI_HANDLE_SYNTH(not#ifdef GUI_HANDLE_SYNTH): Incore/interface/core/interfaceDefs.h,GUI_HANDLE_SYNTHis always defined (1onPLATFORM_IMX,0onMK66), so#ifdef GUI_HANDLE_SYNTHwill mistakenly evaluate to true on the Original Tracker. -
Custom Build Flags (
CUSTOM_DEFINES): You can pass ad-hoc feature flags from the command line without editing makefiles viamake all CUSTOM_DEFINES="-DMY_EXPERIMENTAL_FEATURE". -
Platform-Specific
.ptfxPlugins:.ptfxSample Editor plugins are compiled once for all devices, but can restrict themselves to Tracker+ / Tracker Mini by settingPTFX_FLAG_IMX_ONLYin theirPtfxHeader::flags(editor-fx-sdk/tracker_plugin.h), or adapt dynamically at runtime by checkingchannels(1vs2) inplugin_process_block().
-
Never use