Compare commits

...

12 Commits
v0.1.0 ... main

Author SHA1 Message Date
heck 6b19b06e48 Fix: Samplerate constexpr - update for improved Samplerate representation in libDaisy 9 months ago
heck c3de155e43 Build: Fix wrong usage 9 months ago
heck f6245bf01d Feature: Add CPU BOOST (480MHZ) option 9 months ago
heck 2faf4657dc globals.hh - group audio related constants by prefix 9 months ago
heck 23b1cf4ca3 DOC: README.md - add nice lab-pic 9 months ago
heck e59a2d1dc7 DOC: README.md 9 months ago
heck 6b6dfd5122 examples belong into heck_daisy_template repo 9 months ago
heck 4e84419b6c Build: fix build conf concept 9 months ago
heck e0b3c69417 Build: fix DEBUG is part of the libDaisy/core/Makefile 9 months ago
heck db14196b73 Build: config use defaults that reflect a possible working scenario 9 months ago
heck 85afddf5f4 make typealiases global in types.hh (and remove all the superflous ones) 9 months ago
heck 6eb4111a77 Add 'types.hh' - move stuff from globals there 9 months ago
  1. 20
      Makefile.conf
  2. 129
      README.md
  3. 8
      build.conf.example
  4. BIN
      res/heckmachines_osp_lab_dresden.png
  5. 2
      src/Makefile
  6. 23
      src/globals.hh
  7. 2
      src/instr_abstract.hh
  8. 2
      src/instr_bd2.cc
  9. 3
      src/instr_bd2.hh
  10. 2
      src/instr_fm.cc
  11. 3
      src/instr_fm.hh
  12. 2
      src/instr_grainlet.cc
  13. 3
      src/instr_grainlet.hh
  14. 2
      src/instr_hihat.cc
  15. 3
      src/instr_hihat.hh
  16. 6
      src/instr_kick.cc
  17. 3
      src/instr_kick.hh
  18. 2
      src/instr_noise.cc
  19. 3
      src/instr_noise.hh
  20. 2
      src/instr_zosc.cc
  21. 3
      src/instr_zosc.hh
  22. 16
      src/main_blink.cc
  23. 48
      src/main_perkons.cc
  24. 51
      src/main_testtone.cc
  25. 4
      src/track.hh
  26. 30
      src/types.hh
  27. 44
      src/utils.cc
  28. 4
      src/utils.hh

20
Makefile.conf

@ -1,4 +1,5 @@
HERE:=$(dir $(lastword $(MAKEFILE_LIST)))
-include $(HERE)build.conf
# Project Name
TARGET?=perkons
@ -7,29 +8,20 @@ TARGET?=perkons
# common configurations:
# use DEBUG = 1 and OPT = -Og for debugging
# or DEBUG = 0 and OPT = -O3 for performance
DEBUG=0
OPT=-O3
DEBUG?=0
OPT?=-O3
# (optional) Includes FatFS source files within project.
#USE_FATFS = 1
# Relative to dir 'src'
LIBDAISY_DIR=../../heck_libDaisyWrong
DAISYSP_DIR=../../heck_DaisySPWrong
CXXFLAGS+=-Wall -Wno-unused -Wno-reorder-ctor -Wno-switch
LIBDAISY_DIR?=../../heck_libDaisy
DAISYSP_DIR?=../../heck_DaisySP
######### Overrides from build.conf #########
-include $(HERE)build.conf
CXXFLAGS+=-Wall -Wno-unused -Wno-reorder-ctor -Wno-switch
ifneq (,$(findstring g++,$(CXX)))
CXXFLAGS+=-fdiagnostics-color=always
else ifneq (,$(findstring clang,$(CXX)))
CXXFLAGS+=-fcolor-diagnostics
endif
ifeq ($(DEBUG),1)
CXXFLAGS+=-g -O0
else
CXXFLAGS+=-DNDEBUG=1 -O3
endif

129
README.md

@ -1,27 +1,16 @@
# Heck Daisy Template
# Heck Machines - OSP
The OSP is a hackable, open source drum machine that accidentally got very, very close to the erica perkons hd-01,
which is a real beauty of instrument design that i truly love, except for its unhackable closed source nature.
So, i made a gnu one.
Daisy project template featuring:
* toolchain setup
* dependencies setup
*
* build scripts
* upload (DFU and JTAG)
* debug
* clang-format
* clang-tidy
![](res/heckmachines_osp_lab_dresden.png)
## git started
## Build Instructions
to use git, either die or use hecks git-ui.
heck-git-ui: https://gitea.heck.live/heck/HeckBashSetup/src/branch/master/bash_profile.d/git.sh
### Toolchain Setup
Alternatively, you can avoid using git... TODO
## Toolchain Setup
### Compiler
#### Compiler
compiler used is gcc for arm:
Options:
@ -34,117 +23,23 @@ There is NO libc-nano shipped with it, because its not GPL.
BUT the daisy build scripts specify the use of libc-nano.
### Programmer / Debugger
#### Programmer / Debugger
on macos:
`port install dfu-util openocd`
`dfu-util` is the program that is invoked by the Makefiles to program the thing via DFU.
`openocd` is the program that is invoked by the Makefiles to program the thing via JTAG.
`openocd` also is the debugger we use.
## Flashing
Can be flashed via:
* DFU: all you need is a micro-usb-cable
* JTAG: any JTAG programmer will work, but the STLink v3 is the fastest.
### DFU
No magic, you just need a program called `dfu-util`.
### Dependencies
TODO...
### JTAG
no magic, you just need a programm called `openocd`
TODO:
The JTAG method is heavily recommended since JTAG is faster than DFU, and if you use the (product ad ahead warning, sorry)
STLink v3 its even faster. Its the fastest method i know of.
### Benchmark DFU vs. JTAG
**DFU: 15.725s**
**JTAG: 1.850s**
JTAG is at least **8.5 times** faster (since there is constant time overhead)
``` shell
[heck@YOOROOX::~/src/DaisyExamples/seed/Blink] (master ?M) $ time m program-dfu;
dfu-util -a 0 -s 0x08000000:leave -D build/Blink.bin -d ,0483:df11
blabla...
...
real 0m15.725s
```
``` shell
[heck@YOOROOX::~/src/DaisyExamples/seed/Blink] (master ?M) $ time m program;
openocd -s /opt/local/bin/openocd/ -f interface/stlink.cfg -f target/stm32h7x.cfg -c "program ./build/Blink.elf verify reset exit"
blabla...
...
real 0m1.850s
```
## Debugging
TODO:
## Daisy Coding
* C++ bare metal like any STM32 - needlessly brutal
* C++ and libDaisy - libDaisy is the electro-smith hardware abstraction
* Pure-Data patch compiler
* JUCE
* FAUST for DSP algo
* Max-msp gen~ (proprietary $hit)
### C++ Bare Metal
Just code like for any STM32 - needlessly brutal
TODO: add hecks STM32 project
### C++ and libDaisy
libDaisy is the electro-smith hardware abstraction and is basically what makes the daisy be the daisy.
TODO:
### Pure-Data Patch Compiler
this here: https://github.com/electro-smith/pd2dsy
TODO: Marc? anyone?
### JUCE
TODO: anyone?
e.g. https://github.com/electro-smith/Daisy-Juce-Example
### FAUST
This here: https://faust.grame.fr/
stahl has workflow/project
### Max-Msp gen~
max is the proprietary version of pure-data, but dont want to exclude them just for that.
gen~ alone will cost you extra $$$ after even you paid for max. just so you know, hu?
## Daisy-Hardware
TODO: PLEASE everyone share their hardware HERE!
## Various
Stahl and Marcs fire synthesizer. Now with sausage mode: https://wiki.sgmk-ssam.ch/wiki/F%C3%BC%C3%BCr_Synthie_mit_Daisy_Seed
### Hardware
TODO...

8
build.conf.example

@ -3,10 +3,10 @@
# The program to compile and flash
# the name of the main cxx file without the prefix 'main_'
TARGET=perkons
TARGET?=perkons
DEBUG=0
DEBUG?=0
# Daisy dependencies Relative to dir 'src'
LIBDAISY_DIR=../../heck_libDaisy
DAISYSP_DIR=../../heck_DaisySP
LIBDAISY_DIR?=../../heck_libDaisy
DAISYSP_DIR?=../../heck_DaisySP

BIN
res/heckmachines_osp_lab_dresden.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 828 KiB

2
src/Makefile

@ -12,7 +12,7 @@ $(info TARGET_SRC: $(TARGET_SRC))
$(info CXX_SRC: $(CXX_SRC))
# libDaisy Makefile variables
CPPFLAGS=$(CXXFLAGS)
CFLAGS=$(CXXFLAGS)
SYSTEM_FILES_DIR=$(LIBDAISY_DIR)/core
CPP_SOURCES=$(CXX_SRC)

23
src/globals.hh

@ -4,10 +4,10 @@
#include <cstdint>
#include "daisy_seed.h"
#include "daisysp.h"
#include "types.hh"
namespace Heck {
namespace ld = daisy;
namespace dsp = daisysp;
using Samplerate = ld::SaiHandle::Config::SampleRate;
namespace Constants {
namespace Hardware {
@ -15,8 +15,9 @@ namespace Heck {
constexpr int PIN_BUTTON_CLEAR = 27;
}
constexpr int BUFFERSIZE = 4;
constexpr int SAMPLERATE = 48000;
constexpr bool CPU_BOOST480MHZ = true;
constexpr int AUDIO_BUFFERSIZE = 4;
constexpr Samplerate AUDIO_SAMPLERATE = Samplerate::SAI_48KHZ;
constexpr int TRACK_COUNT = 4;
namespace MIDI_Mapping {
@ -41,20 +42,6 @@ namespace Heck {
}
} // namespace Constants
// Types
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using f32 = float;
using f64 = double;
//Hardware
extern ld::DaisySeed hw;
extern ld::Switch but_rec;

2
src/instr_abstract.hh

@ -5,8 +5,6 @@
namespace Heck {
namespace Instrument {
static int samplerate = Constants::SAMPLERATE;
class AbstractInstrument {
public:
virtual void trigger() = 0;

2
src/instr_bd2.cc

@ -12,7 +12,7 @@ namespace Heck {
void BD2::init()
{
bd2.Init(samplerate);
bd2.Init(Constants::AUDIO_SAMPLERATE);
bd2.SetDecay(1.);
bd2.SetTone(0.4);
bd2.SetAccent(1.);

3
src/instr_bd2.hh

@ -5,9 +5,6 @@
#include "daisy_seed.h"
#include "daisysp.h"
namespace ld = daisy;
namespace dsp = daisysp;
namespace Heck {
namespace Instrument {

2
src/instr_fm.cc

@ -12,7 +12,7 @@ namespace Heck {
void FM::init()
{
osc.Init(samplerate);
osc.Init(Constants::AUDIO_SAMPLERATE);
osc.SetFrequency(40);
osc.SetRatio(0.);
osc.SetIndex(0.);

3
src/instr_fm.hh

@ -5,9 +5,6 @@
#include "daisy_seed.h"
#include "daisysp.h"
namespace ld = daisy;
namespace dsp = daisysp;
namespace Heck {
namespace Instrument {

2
src/instr_grainlet.cc

@ -12,7 +12,7 @@ namespace Heck {
void Grainlet::init()
{
grainlet.Init(samplerate);
grainlet.Init(Constants::AUDIO_SAMPLERATE);
}
void Grainlet::trigger()

3
src/instr_grainlet.hh

@ -5,9 +5,6 @@
#include "daisy_seed.h"
#include "daisysp.h"
namespace ld = daisy;
namespace dsp = daisysp;
namespace Heck {
namespace Instrument {

2
src/instr_hihat.cc

@ -12,7 +12,7 @@ namespace Heck {
void HiHat::init()
{
hihat.Init(samplerate);
hihat.Init(Constants::AUDIO_SAMPLERATE);
hihat.SetDecay(1.);
}

3
src/instr_hihat.hh

@ -5,9 +5,6 @@
#include "daisy_seed.h"
#include "daisysp.h"
namespace ld = daisy;
namespace dsp = daisysp;
namespace Heck {
namespace Instrument {

6
src/instr_kick.cc

@ -12,16 +12,16 @@ namespace Heck {
void Kick::init()
{
osc.Init(samplerate);
osc.Init(Constants::AUDIO_SAMPLERATE);
osc.SetWaveform(dsp::Oscillator::WAVE_TRI);
osc.SetAmp(1);
pitchEnv.Init(samplerate);
pitchEnv.Init(Constants::AUDIO_SAMPLERATE);
pitchEnv.SetTime(dsp::ADENV_SEG_ATTACK, .001);
pitchEnv.SetTime(dsp::ADENV_SEG_DECAY, .01);
chorus.Init(samplerate);
chorus.Init(Constants::AUDIO_SAMPLERATE);
chorus.SetDelay(0.2);
chorus.SetFeedback(0.8);
chorus.SetLfoDepth(0.2);

3
src/instr_kick.hh

@ -5,9 +5,6 @@
#include "daisy_seed.h"
#include "daisysp.h"
namespace ld = daisy;
namespace dsp = daisysp;
namespace Heck {
namespace Instrument {

2
src/instr_noise.cc

@ -12,7 +12,7 @@ namespace Heck {
{
noise.Init();
env.Init(samplerate);
env.Init(Constants::AUDIO_SAMPLERATE);
env.SetTime(dsp::ADENV_SEG_ATTACK, .0001);
env.SetTime(dsp::ADENV_SEG_DECAY, .01);
env.SetMax(1);

3
src/instr_noise.hh

@ -5,9 +5,6 @@
#include "daisy_seed.h"
#include "daisysp.h"
namespace ld = daisy;
namespace dsp = daisysp;
namespace Heck {
namespace Instrument {

2
src/instr_zosc.cc

@ -12,7 +12,7 @@ namespace Heck {
void ZOsc::init()
{
zosc.Init(samplerate);
zosc.Init(Constants::AUDIO_SAMPLERATE);
zosc.SetFreq(40.f);
zosc.SetShape(1.);
zosc.SetFormantFreq(200);

3
src/instr_zosc.hh

@ -5,9 +5,6 @@
#include "daisy_seed.h"
#include "daisysp.h"
namespace ld = daisy;
namespace dsp = daisysp;
namespace Heck {
namespace Instrument {

16
src/main_blink.cc

@ -1,16 +0,0 @@
#include "daisy_seed.h"
using namespace daisy;
static DaisySeed hw{};
int main()
{
hw.Init();
while (true) {
hw.SetLed(true);
hw.DelayMs(100);
hw.SetLed(false);
hw.DelayMs(500);
}
}

48
src/main_perkons.cc

@ -15,9 +15,6 @@
#include "instr_hihat.hh"
#include "instr_zosc.hh"
namespace ld = daisy;
namespace dsp = daisysp;
namespace Heck {
namespace State {
bool record_mode{ false };
@ -63,47 +60,26 @@ namespace Heck {
void init()
{
hw.Configure();
hw.Init();
hw.Init(Constants::CPU_BOOST480MHZ);
hw.StartLog(Constants::Developer::LOG_BLOCKS_BOOT);
but_rec.Init(hw.GetPin(Constants::Hardware::PIN_BUTTON_RECORD), 0);
but_clear.Init(hw.GetPin(Constants::Hardware::PIN_BUTTON_CLEAR), 0);
hw.PrintLine("Setting Blocksize: %i", Constants::BUFFERSIZE);
hw.SetAudioBlockSize(Constants::BUFFERSIZE);
hw.PrintLine("Setting Blocksize: %i", Constants::AUDIO_BUFFERSIZE);
hw.SetAudioBlockSize(Constants::AUDIO_BUFFERSIZE);
hw.PrintLine("Setting Samplerate: %i", Constants::SAMPLERATE);
switch (Constants::SAMPLERATE) {
case 8000:
hw.SetAudioSampleRate(daisy::SaiHandle::Config::SampleRate::SAI_8KHZ);
break;
case 16000:
hw.SetAudioSampleRate(daisy::SaiHandle::Config::SampleRate::SAI_16KHZ);
break;
case 32000:
hw.SetAudioSampleRate(daisy::SaiHandle::Config::SampleRate::SAI_32KHZ);
break;
case 48000:
hw.SetAudioSampleRate(daisy::SaiHandle::Config::SampleRate::SAI_48KHZ);
break;
case 96000:
hw.SetAudioSampleRate(daisy::SaiHandle::Config::SampleRate::SAI_48KHZ);
break;
default:
hw.PrintLine("Samplerate not supported, fallback to 48000");
hw.SetAudioSampleRate(daisy::SaiHandle::Config::SampleRate::SAI_48KHZ);
break;
}
hw.PrintLine("Setting Samplerate: %i", Constants::AUDIO_SAMPLERATE);
hw.SetAudioSampleRate(Constants::AUDIO_SAMPLERATE);
hw.PrintLine("Initializing MIDI");
ld::MidiUartHandler::Config midi_config{};
midi.Init(midi_config);
midi.realtime_callback = &midi_realtime_handler;
init_tracks();
hw.PrintLine("Starting MIDI Receive");
midi.StartReceive();
midi.StartReceiveRt(&midi_realtime_handler);
midi.Listen();
hw.PrintLine("Starting Audio");
@ -135,22 +111,22 @@ namespace Heck {
{
event_log.PushBack(msg);
switch (msg.srt_type) {
case daisy::TimingClock:
case ld::TimingClock:
clock.tick_advance();
break;
case daisy::Start: {
case ld::Start: {
sequencer.reset();
clock.reset();
clock.enable(true);
} break;
case daisy::Stop: {
case ld::Stop: {
clock.enable(false);
clock.reset();
sequencer.reset();
} break;
case daisy::Reset:
case ld::Reset:
break;
case daisy::Continue:
case ld::Continue:
break;
}
}
@ -338,7 +314,7 @@ namespace Heck {
char rttype_str[32];
GetMidiRTTypeAsString(msg, rttype_str);
sprintf(outstr, "RT: type: %s\n", rttype_str);
if (msg.srt_type != daisy::TimingClock) {
if (msg.srt_type != ld::TimingClock) {
hw.PrintLine("%s", outstr);
}
}

51
src/main_testtone.cc

@ -1,51 +0,0 @@
#include "daisy_seed.h"
#include "daisysp.h"
// Use the daisy namespace to prevent having to type
// daisy:: before all libdaisy functions
using namespace daisy;
using namespace daisysp;
// Declare a DaisySeed object called hardware
DaisySeed hardware;
Oscillator osc;
void AudioCallback(
AudioHandle::InterleavingInputBuffer in,
AudioHandle::InterleavingOutputBuffer out,
size_t size)
{
float osc_out;
//Convert floating point knob to midi (0-127)
//Then convert midi to freq. in Hz
osc.SetFreq(1000);
//Fill the block with samples
for (size_t i = 0; i < size; i += 2) {
osc.SetAmp(1.0);
osc_out = osc.Process();
osc_out *= 0.1;
out[i] = osc_out;
out[i + 1] = osc_out;
}
}
int main(void)
{
hardware.Configure();
hardware.Init();
hardware.SetAudioBlockSize(4);
float samplerate = hardware.AudioSampleRate();
osc.Init(samplerate);
osc.SetWaveform(osc.WAVE_SIN);
osc.SetAmp(1.f);
osc.SetFreq(1000);
hardware.StartAudio(AudioCallback);
for (;;) {}
}

4
src/track.hh

@ -16,7 +16,7 @@ namespace Heck {
instrument.reset(&instr);
// Env
decay_.Init(Constants::SAMPLERATE);
decay_.Init(Constants::AUDIO_SAMPLERATE);
decay_.SetTime(dsp::ADENV_SEG_ATTACK, .0001);
decay_.SetTime(dsp::ADENV_SEG_DECAY, 0.1);
decay_.SetMax(1);
@ -27,7 +27,7 @@ namespace Heck {
ctl_volume_ = 0.;
// Filter
ladder_.Init(Constants::SAMPLERATE);
ladder_.Init(Constants::AUDIO_SAMPLERATE);
ladder_.SetFilterMode(daisysp::LadderFilter::FilterMode::LP24);
ladder_.SetRes(0.4);
ladder_.SetInputDrive(1.3);

30
src/types.hh

@ -0,0 +1,30 @@
#ifndef HECK_DAISY_TYPES_HH
#define HECK_DAISY_TYPES_HH
#include <cstdint>
#include "daisy_seed.h"
#include "daisysp.h"
namespace Heck {
// Types
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using f32 = float;
using f64 = double;
// namespace aliases
namespace ld = daisy;
namespace dsp = daisysp;
} // namespace Heck
#endif

44
src/utils.cc

@ -1,40 +1,38 @@
#include "utils.hh"
using namespace daisy;
namespace Heck {
void GetMidiTypeAsString(MidiEvent& msg, char* str)
void GetMidiTypeAsString(ld::MidiEvent& msg, char* str)
{
switch (msg.type) {
case NoteOff:
case ld::NoteOff:
strcpy(str, "NoteOff");
break;
case NoteOn:
case ld::NoteOn:
strcpy(str, "NoteOn");
break;
case PolyphonicKeyPressure:
case ld::PolyphonicKeyPressure:
strcpy(str, "PolyKeyPres.");
break;
case ControlChange:
case ld::ControlChange:
strcpy(str, "CC");
break;
case ProgramChange:
case ld::ProgramChange:
strcpy(str, "Prog. Change");
break;
case ChannelPressure:
case ld::ChannelPressure:
strcpy(str, "Chn. Pressure");
break;
case PitchBend:
case ld::PitchBend:
strcpy(str, "PitchBend");
break;
case SystemCommon:
case ld::SystemCommon:
strcpy(str, "Sys. Common");
break;
case SystemRealTime:
case ld::SystemRealTime:
strcpy(str, "Sys. Realtime");
break;
case ChannelMode:
case ld::ChannelMode:
strcpy(str, "Chn. Mode");
break;
default:
@ -43,34 +41,34 @@ namespace Heck {
}
}
void GetMidiRTTypeAsString(MidiEvent& msg, char* str)
void GetMidiRTTypeAsString(ld::MidiEvent& msg, char* str)
{
switch (msg.srt_type) {
case TimingClock:
case ld::TimingClock:
strcpy(str, "TimingClock");
break;
case SRTUndefined0:
case ld::SRTUndefined0:
strcpy(str, "SRTUndefined0");
break;
case Start:
case ld::Start:
strcpy(str, "Start");
break;
case Continue:
case ld::Continue:
strcpy(str, "Continue");
break;
case Stop:
case ld::Stop:
strcpy(str, "Stop");
break;
case SRTUndefined1:
case ld::SRTUndefined1:
strcpy(str, "SRTUndefined1");
break;
case ActiveSensing:
case ld::ActiveSensing:
strcpy(str, "ActiveSensing");
break;
case Reset:
case ld::Reset:
strcpy(str, "Reset");
break;
case SystemRealTimeLast:
case ld::SystemRealTimeLast:
strcpy(str, "SystemRealTimeLast");
break;
default:

4
src/utils.hh

@ -5,8 +5,8 @@
#include "globals.hh"
namespace Heck {
void GetMidiTypeAsString(daisy::MidiEvent& msg, char* str);
void GetMidiRTTypeAsString(daisy::MidiEvent& msg, char* str);
void GetMidiTypeAsString(ld::MidiEvent& msg, char* str);
void GetMidiRTTypeAsString(ld::MidiEvent& msg, char* str);
float scalen_min_max(float val, float min, float max);
float scalen_center_range(float val, float center, float range);

Loading…
Cancel
Save