diff --git a/.gitmodules b/.gitmodules index 064ffe4..96cb8bb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "CMSIS_5"] path = CMSIS_5 url = https://github.com/ARM-software/CMSIS_5 +[submodule "u8g2"] + path = u8g2 + url = https://github.com/olikraus/u8g2.git diff --git a/.vscode/configurationCache.log b/.vscode/configurationCache.log new file mode 100644 index 0000000..bab9054 --- /dev/null +++ b/.vscode/configurationCache.log @@ -0,0 +1 @@ +{"buildTargets":[],"launchTargets":[],"customConfigurationProvider":{"workspaceBrowse":{"browsePath":[],"compilerArgs":[]},"fileIndex":[]}} \ No newline at end of file diff --git a/.vscode/dryrun.log b/.vscode/dryrun.log new file mode 100644 index 0000000..ed74b6a --- /dev/null +++ b/.vscode/dryrun.log @@ -0,0 +1,4 @@ +make.exe --dry-run --keep-going --print-directory +'make.exe' is not recognized as an internal or external command, +operable program or batch file. + diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..65e1ec0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "makefile.extensionOutputFolder": "./.vscode" +} \ No newline at end of file diff --git a/.vscode/targets.log b/.vscode/targets.log new file mode 100644 index 0000000..04f2128 --- /dev/null +++ b/.vscode/targets.log @@ -0,0 +1,4 @@ +make.exe all --print-data-base --no-builtin-variables --no-builtin-rules --question +'make.exe' is not recognized as an internal or external command, +operable program or batch file. + diff --git a/README.md b/README.md index 8070e57..ecd020b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,10 @@ -# MiniDexed ![](https://github.com/probonopd/MiniDexed/actions/workflows/build.yml/badge.svg) +# MaxiDexed ![](https://github.com/probonopd/MiniDexed/actions/workflows/build.yml/badge.svg) + +This project aims at increasing the marvelous job done with MiniDexed focusing on the user interface as I believe that FM synthesis is difficult enough to deserve a simple but more confortable user interface to replace the 2x16 chars displays and the one button with click, double clicks and triple clicks! As you guessed it, I want to make it autonomous from computer assistance. + +I added at the tip of the feature list the few features I would like to contribute in this fork. + +For the moment this fork will concentrate on Raspberry PI 4B and potentialy above. I do not intent to test the code on any other lower versions. ![minidexed](https://user-images.githubusercontent.com/2480569/161813414-bb156a1c-efec-44c0-802a-8926412a08e0.jpg) @@ -6,6 +12,32 @@ MiniDexed is a FM synthesizer closely modeled on the famous DX7 by a well-known ## Features +### Maxi Dexed features backlog +- [ ] DEV01 - Change build structure so that object and other bin files go away from the sources directories +- [x] PRESET01 - Preset browsing: changing bak automaticallw when reaching the left or right preset boundary so that: +``` + - Bank 1 Preset 1 + 1 -> Bank 1 Preset 2 + - Bank 1 Preset 1 - 1 -> Bank 1 Preset 1 + - Bank n Preset 32 + 1 -> Bank n+1 Preset 1 + - Bank n Preset 1 - 1 -> Bank n-1 Preset 32 +``` +- [x] PRESET02 - Support more than 127 banks adding the support MIDI CC0 [Bank Select (MSB)] et MIDI CC32 [Bank Select (LSB)] to allow a maximum of 2^14 = 16384 so that: +``` + - Bank ID bin: nn nnnn nnnn nnnn + - MIDI CC 0: nn nnnn nxxx xxxx + - MIDI CC 32: xx xxxx xnnn nnnn +``` +- [x] PRESET03 - Add bank sysex material to complement the current one +- [ ] PRESET04 - Add performance support and edit to leverage the 8 Tone Generators +- [ ] SYNTH01 - Add Delay FX +- [ ] SYNTH02 - Add Chorus FX +- [ ] SYNTH03 - Add Flanger FX +- [ ] SYNTH04 - Add Distortion FX +- [-] HW01 - Create a 3D printable enclosure for the synth that uses the Raspaudio option +- [ ] HW02 - Add support for I2C screen interface (4pins) +- [ ] HW03 - Build PCB to ease the inclusion of all encoders, the screen and the audio sound card and include passive heat dissipation (OOTS Raspberry PI heatsink such as [GeeekPi Raspberry Pi 4](https://www.amazon.fr/gp/product/B07WQT1RRZ/ref=sw_img_1?smid=A187Y4UVM6ZA0X&th=1)) +- [ ] HW04 - Design a metal enclosure with real size inputs and outputs +### MiniDexed feature backlog - [x] Uses [Synth_Dexed](https://codeberg.org/dcoredump/Synth_Dexed) with [circle-stdlib](https://github.com/smuehlst/circle-stdlib) - [x] SD card contents can be downloaded from [GitHub Releases](../../releases) - [x] Runs on all Raspberry Pi models (except Pico); see below for details diff --git a/analysis/MenuStructure.xlsx b/analysis/MenuStructure.xlsx new file mode 100644 index 0000000..800c1f0 Binary files /dev/null and b/analysis/MenuStructure.xlsx differ diff --git a/analysis/algorithms.jpg b/analysis/algorithms.jpg new file mode 100644 index 0000000..320a19b Binary files /dev/null and b/analysis/algorithms.jpg differ diff --git a/getsysex.sh b/getsysex.sh index fa73153..b7b5085 100755 --- a/getsysex.sh +++ b/getsysex.sh @@ -7,10 +7,10 @@ mkdir -p sysex/voice/ DIR="https://yamahablackboxes.com/patches/dx7/factory" -# wget -c "${DIR}"/rom1a.syx -O sysex/voice/000000_rom1a.syx -# wget -c "${DIR}"/rom1b.syx -O sysex/voice/000001_rom1b.syx -# wget -c "${DIR}"/rom2a.syx -O sysex/voice/000002_rom2a.syx -# wget -c "${DIR}"/rom2b.syx -O sysex/voice/000003_rom2b.syx +wget -c "${DIR}"/rom1a.syx -O sysex/voice/000000_rom1a.syx +wget -c "${DIR}"/rom1b.syx -O sysex/voice/000001_rom1b.syx +wget -c "${DIR}"/rom2a.syx -O sysex/voice/000002_rom2a.syx +wget -c "${DIR}"/rom2b.syx -O sysex/voice/000003_rom2b.syx wget -c "${DIR}"/rom3a.syx -O sysex/voice/000000_rom3a.syx wget -c "${DIR}"/rom3b.syx -O sysex/voice/000001_rom3b.syx wget -c "${DIR}"/rom4a.syx -O sysex/voice/000002_rom4a.syx @@ -41,3 +41,510 @@ wget -c "${DIR}"/vrc111a.syx -O sysex/voice/000023_vrc111a.syx wget -c "${DIR}"/vrc111b.syx -O sysex/voice/000024_vrc111b.syx wget -c "${DIR}"/vrc112a.syx -O sysex/voice/000025_vrc112a.syx wget -c "${DIR}"/vrc112b.syx -O sysex/voice/000026_vrc112b.syx + +DIR="http://dxsysex.com/SYSEX_DX7/Misc" + +wget -c "${DIR}"/actualbk.syx -O sysex/voice/000027_actualbk.syx +wget -c "${DIR}"/aegix.syx -O sysex/voice/000028_aegix.syx +wget -c "${DIR}"/analog1.syx -O sysex/voice/000029_analog1.syx +wget -c "${DIR}"/analog3.syx -O sysex/voice/000030_analog3.syx +wget -c "${DIR}"/analog4.syx -O sysex/voice/000031_analog4.syx +wget -c "${DIR}"/analog_1.syx -O sysex/voice/000032_analog_1.syx +wget -c "${DIR}"/analog_2.syx -O sysex/voice/000033_analog_2.syx +wget -c "${DIR}"/analog_3.syx -O sysex/voice/000034_analog_3.syx +wget -c "${DIR}"/angelo.syx -O sysex/voice/000035_angelo.syx +wget -c "${DIR}"/atsu_4.syx -O sysex/voice/000036_atsu_4.syx +wget -c "${DIR}"/atsu_5.syx -O sysex/voice/000037_atsu_5.syx +wget -c "${DIR}"/b1.syx -O sysex/voice/000038_b1.syx +wget -c "${DIR}"/b2.syx -O sysex/voice/000039_b2.syx +wget -c "${DIR}"/b3.syx -O sysex/voice/000040_b3.syx +wget -c "${DIR}"/b4.syx -O sysex/voice/000041_b4.syx +wget -c "${DIR}"/bank0000.syx -O sysex/voice/000042_bank0000.syx +wget -c "${DIR}"/bank0006.syx -O sysex/voice/000043_bank0006.syx +wget -c "${DIR}"/bank0008.syx -O sysex/voice/000044_bank0008.syx +wget -c "${DIR}"/bank0009.syx -O sysex/voice/000045_bank0009.syx +wget -c "${DIR}"/bank0023.syx -O sysex/voice/000046_bank0023.syx +wget -c "${DIR}"/bank0024.syx -O sysex/voice/000047_bank0024.syx +wget -c "${DIR}"/bank0042.syx -O sysex/voice/000048_bank0042.syx +wget -c "${DIR}"/bank0043.syx -O sysex/voice/000049_bank0043.syx +wget -c "${DIR}"/bank0044.syx -O sysex/voice/000050_bank0044.syx +wget -c "${DIR}"/bank0045.syx -O sysex/voice/000051_bank0045.syx +wget -c "${DIR}"/bank0046.syx -O sysex/voice/000052_bank0046.syx +wget -c "${DIR}"/bank0047.syx -O sysex/voice/000053_bank0047.syx +wget -c "${DIR}"/bank0048.syx -O sysex/voice/000054_bank0048.syx +wget -c "${DIR}"/bank0049.syx -O sysex/voice/000055_bank0049.syx +wget -c "${DIR}"/bank0050.syx -O sysex/voice/000056_bank0050.syx +wget -c "${DIR}"/bank0054.syx -O sysex/voice/000057_bank0054.syx +wget -c "${DIR}"/bank0056.syx -O sysex/voice/000058_bank0056.syx +wget -c "${DIR}"/bank01.syx -O sysex/voice/000059_bank01.syx +wget -c "${DIR}"/bank05.syx -O sysex/voice/000060_bank05.syx +wget -c "${DIR}"/bank08.syx -O sysex/voice/000061_bank08.syx +wget -c "${DIR}"/bank1.syx -O sysex/voice/000062_bank1.syx +wget -c "${DIR}"/bank11.syx -O sysex/voice/000063_bank11.syx +wget -c "${DIR}"/bank14.syx -O sysex/voice/000064_bank14.syx +wget -c "${DIR}"/bank18.syx -O sysex/voice/000065_bank18.syx +wget -c "${DIR}"/bank2.syx -O sysex/voice/000066_bank2.syx +wget -c "${DIR}"/bank3.syx -O sysex/voice/000067_bank3.syx +wget -c "${DIR}"/bass3.syx -O sysex/voice/000068_bass3.syx +wget -c "${DIR}"/bass_01.syx -O sysex/voice/000069_bass_01.syx +wget -c "${DIR}"/bass_02.syx -O sysex/voice/000070_bass_02.syx +wget -c "${DIR}"/bass_03.syx -O sysex/voice/000071_bass_03.syx +wget -c "${DIR}"/bass_04.syx -O sysex/voice/000072_bass_04.syx +wget -c "${DIR}"/bass_05.syx -O sysex/voice/000073_bass_05.syx +wget -c "${DIR}"/bass_06.syx -O sysex/voice/000074_bass_06.syx +wget -c "${DIR}"/bass_07.syx -O sysex/voice/000075_bass_07.syx +wget -c "${DIR}"/bass_08.syx -O sysex/voice/000076_bass_08.syx +wget -c "${DIR}"/bass_09.syx -O sysex/voice/000077_bass_09.syx +wget -c "${DIR}"/bass_10.syx -O sysex/voice/000078_bass_10.syx +wget -c "${DIR}"/bass_11.syx -O sysex/voice/000079_bass_11.syx +wget -c "${DIR}"/bass_12.syx -O sysex/voice/000080_bass_12.syx +wget -c "${DIR}"/bass_13.syx -O sysex/voice/000081_bass_13.syx +wget -c "${DIR}"/bass_14.syx -O sysex/voice/000082_bass_14.syx +wget -c "${DIR}"/bass_15.syx -O sysex/voice/000083_bass_15.syx +wget -c "${DIR}"/bassea.syx -O sysex/voice/000084_bassea.syx +wget -c "${DIR}"/bassics.syx -O sysex/voice/000085_bassics.syx +wget -c "${DIR}"/bbank1.syx -O sysex/voice/000086_bbank1.syx +wget -c "${DIR}"/bbank2.syx -O sysex/voice/000087_bbank2.syx +wget -c "${DIR}"/bell1.syx -O sysex/voice/000088_bell1.syx +wget -c "${DIR}"/bells.syx -O sysex/voice/000089_bells.syx +wget -c "${DIR}"/bells_01.syx -O sysex/voice/000090_bells_01.syx +wget -c "${DIR}"/bells_02.syx -O sysex/voice/000091_bells_02.syx +wget -c "${DIR}"/bells_03.syx -O sysex/voice/000092_bells_03.syx +wget -c "${DIR}"/belltel.syx -O sysex/voice/000093_belltel.syx +wget -c "${DIR}"/blanks.syx -O sysex/voice/000094_blanks.syx +wget -c "${DIR}"/boruff.syx -O sysex/voice/000095_boruff.syx +wget -c "${DIR}"/brass.syx -O sysex/voice/000096_brass.syx +wget -c "${DIR}"/brass2.syx -O sysex/voice/000097_brass2.syx +wget -c "${DIR}"/brass3.syx -O sysex/voice/000098_brass3.syx +wget -c "${DIR}"/brass_01.syx -O sysex/voice/000099_brass_01.syx +wget -c "${DIR}"/brass_02.syx -O sysex/voice/000100_brass_02.syx +wget -c "${DIR}"/brass_03.syx -O sysex/voice/000101_brass_03.syx +wget -c "${DIR}"/brass_04.syx -O sysex/voice/000102_brass_04.syx +wget -c "${DIR}"/brass_05.syx -O sysex/voice/000103_brass_05.syx +wget -c "${DIR}"/brass_06.syx -O sysex/voice/000104_brass_06.syx +wget -c "${DIR}"/brass_07.syx -O sysex/voice/000105_brass_07.syx +wget -c "${DIR}"/brass_08.syx -O sysex/voice/000106_brass_08.syx +wget -c "${DIR}"/brass_09.syx -O sysex/voice/000107_brass_09.syx +wget -c "${DIR}"/brass_10.syx -O sysex/voice/000108_brass_10.syx +wget -c "${DIR}"/brass_11.syx -O sysex/voice/000109_brass_11.syx +wget -c "${DIR}"/brass_12.syx -O sysex/voice/000110_brass_12.syx +wget -c "${DIR}"/brass_13.syx -O sysex/voice/000111_brass_13.syx +wget -c "${DIR}"/brass_14.syx -O sysex/voice/000112_brass_14.syx +wget -c "${DIR}"/brass_15.syx -O sysex/voice/000113_brass_15.syx +wget -c "${DIR}"/brass_16.syx -O sysex/voice/000114_brass_16.syx +wget -c "${DIR}"/brass_17.syx -O sysex/voice/000115_brass_17.syx +wget -c "${DIR}"/brass_18.syx -O sysex/voice/000116_brass_18.syx +wget -c "${DIR}"/bstx.syx -O sysex/voice/000117_bstx.syx +wget -c "${DIR}"/buck-1.syx -O sysex/voice/000118_buck-1.syx +wget -c "${DIR}"/buck-2.syx -O sysex/voice/000119_buck-2.syx +wget -c "${DIR}"/c-lab_1.syx -O sysex/voice/000120_c-lab_1.syx +wget -c "${DIR}"/cello_01.syx -O sysex/voice/000121_cello_01.syx +wget -c "${DIR}"/cello_02.syx -O sysex/voice/000122_cello_02.syx +wget -c "${DIR}"/church.syx -O sysex/voice/000123_church.syx +wget -c "${DIR}"/ciani.syx -O sysex/voice/000124_ciani.syx +wget -c "${DIR}"/clang1.syx -O sysex/voice/000125_clang1.syx +wget -c "${DIR}"/clarinet.syx -O sysex/voice/000126_clarinet.syx +wget -c "${DIR}"/claude.syx -O sysex/voice/000127_claude.syx +wget -c "${DIR}"/clav1.syx -O sysex/voice/000128_clav1.syx +wget -c "${DIR}"/clav_01.syx -O sysex/voice/000129_clav_01.syx +wget -c "${DIR}"/clav_02.syx -O sysex/voice/000130_clav_02.syx +wget -c "${DIR}"/clav_03.syx -O sysex/voice/000131_clav_03.syx +wget -c "${DIR}"/clav_04.syx -O sysex/voice/000132_clav_04.syx +wget -c "${DIR}"/clav_05.syx -O sysex/voice/000133_clav_05.syx +wget -c "${DIR}"/clav_06.syx -O sysex/voice/000134_clav_06.syx +wget -c "${DIR}"/clavs.syx -O sysex/voice/000135_clavs.syx +wget -c "${DIR}"/combo.syx -O sysex/voice/000136_combo.syx +wget -c "${DIR}"/compuerr.syx -O sysex/voice/000137_compuerr.syx +wget -c "${DIR}"/contemp.syx -O sysex/voice/000138_contemp.syx +wget -c "${DIR}"/country.syx -O sysex/voice/000139_country.syx +wget -c "${DIR}"/czeiszpe.syx -O sysex/voice/000140_czeiszpe.syx +wget -c "${DIR}"/dave1.syx -O sysex/voice/000141_dave1.syx +wget -c "${DIR}"/deckard.syx -O sysex/voice/000142_deckard.syx +wget -c "${DIR}"/dg1.syx -O sysex/voice/000143_dg1.syx +wget -c "${DIR}"/dg2.syx -O sysex/voice/000144_dg2.syx +wget -c "${DIR}"/divers.syx -O sysex/voice/000145_divers.syx +wget -c "${DIR}"/djw001.syx -O sysex/voice/000146_djw001.syx +wget -c "${DIR}"/drm2.syx -O sysex/voice/000147_drm2.syx +wget -c "${DIR}"/drm2a.syx -O sysex/voice/000148_drm2a.syx +wget -c "${DIR}"/drmoct.syx -O sysex/voice/000149_drmoct.syx +wget -c "${DIR}"/drt1.syx -O sysex/voice/000150_drt1.syx +wget -c "${DIR}"/drt2.syx -O sysex/voice/000151_drt2.syx +wget -c "${DIR}"/dx100.syx -O sysex/voice/000152_dx100.syx +wget -c "${DIR}"/dx101.syx -O sysex/voice/000153_dx101.syx +wget -c "${DIR}"/dx103.syx -O sysex/voice/000154_dx103.syx +wget -c "${DIR}"/dx104.syx -O sysex/voice/000155_dx104.syx +wget -c "${DIR}"/dx105.syx -O sysex/voice/000156_dx105.syx +wget -c "${DIR}"/dx106.syx -O sysex/voice/000157_dx106.syx +wget -c "${DIR}"/dx107.syx -O sysex/voice/000158_dx107.syx +wget -c "${DIR}"/dx109.syx -O sysex/voice/000159_dx109.syx +wget -c "${DIR}"/dx110.syx -O sysex/voice/000160_dx110.syx +wget -c "${DIR}"/dx111.syx -O sysex/voice/000161_dx111.syx +wget -c "${DIR}"/dx112.syx -O sysex/voice/000162_dx112.syx +wget -c "${DIR}"/dx113.syx -O sysex/voice/000163_dx113.syx +wget -c "${DIR}"/dx114.syx -O sysex/voice/000164_dx114.syx +wget -c "${DIR}"/dx116.syx -O sysex/voice/000165_dx116.syx +wget -c "${DIR}"/dx117.syx -O sysex/voice/000166_dx117.syx +wget -c "${DIR}"/dx118.syx -O sysex/voice/000167_dx118.syx +wget -c "${DIR}"/dx119.syx -O sysex/voice/000168_dx119.syx +wget -c "${DIR}"/dx120.syx -O sysex/voice/000169_dx120.syx +wget -c "${DIR}"/dx121.syx -O sysex/voice/000170_dx121.syx +wget -c "${DIR}"/dx122.syx -O sysex/voice/000171_dx122.syx +wget -c "${DIR}"/dx123.syx -O sysex/voice/000172_dx123.syx +wget -c "${DIR}"/dx124.syx -O sysex/voice/000173_dx124.syx +wget -c "${DIR}"/dx7bank.syx -O sysex/voice/000174_dx7bank.syx +wget -c "${DIR}"/dx9.syx -O sysex/voice/000175_dx9.syx +wget -c "${DIR}"/dxbasic5.syx -O sysex/voice/000176_dxbasic5.syx +wget -c "${DIR}"/dxdxmi.syx -O sysex/voice/000177_dxdxmi.syx +wget -c "${DIR}"/dxmik2.syx -O sysex/voice/000178_dxmik2.syx +wget -c "${DIR}"/dxoc01.syx -O sysex/voice/000179_dxoc01.syx +wget -c "${DIR}"/dxoc02.syx -O sysex/voice/000180_dxoc02.syx +wget -c "${DIR}"/dxoc03.syx -O sysex/voice/000181_dxoc03.syx +wget -c "${DIR}"/dxoc04.syx -O sysex/voice/000182_dxoc04.syx +wget -c "${DIR}"/dxoc05.syx -O sysex/voice/000183_dxoc05.syx +wget -c "${DIR}"/dxoc06.syx -O sysex/voice/000184_dxoc06.syx +wget -c "${DIR}"/dxoc07.syx -O sysex/voice/000185_dxoc07.syx +wget -c "${DIR}"/dxoc08.syx -O sysex/voice/000186_dxoc08.syx +wget -c "${DIR}"/dxoc09.syx -O sysex/voice/000187_dxoc09.syx +wget -c "${DIR}"/dxoc10.syx -O sysex/voice/000188_dxoc10.syx +wget -c "${DIR}"/dxoc11.syx -O sysex/voice/000189_dxoc11.syx +wget -c "${DIR}"/dxoc12.syx -O sysex/voice/000190_dxoc12.syx +wget -c "${DIR}"/dxoc13.syx -O sysex/voice/000191_dxoc13.syx +wget -c "${DIR}"/dxoc14.syx -O sysex/voice/000192_dxoc14.syx +wget -c "${DIR}"/dxoc15.syx -O sysex/voice/000193_dxoc15.syx +wget -c "${DIR}"/dxoc16.syx -O sysex/voice/000194_dxoc16.syx +wget -c "${DIR}"/dxoc17.syx -O sysex/voice/000195_dxoc17.syx +wget -c "${DIR}"/dxoc18.syx -O sysex/voice/000196_dxoc18.syx +wget -c "${DIR}"/dxoc19.syx -O sysex/voice/000197_dxoc19.syx +wget -c "${DIR}"/dxoc20.syx -O sysex/voice/000198_dxoc20.syx +wget -c "${DIR}"/dxoc21.syx -O sysex/voice/000199_dxoc21.syx +wget -c "${DIR}"/dxoc22.syx -O sysex/voice/000200_dxoc22.syx +wget -c "${DIR}"/dxoc23.syx -O sysex/voice/000201_dxoc23.syx +wget -c "${DIR}"/dxoc24.syx -O sysex/voice/000202_dxoc24.syx +wget -c "${DIR}"/dxoc25.syx -O sysex/voice/000203_dxoc25.syx +wget -c "${DIR}"/dxoc26.syx -O sysex/voice/000204_dxoc26.syx +wget -c "${DIR}"/dxoc27.syx -O sysex/voice/000205_dxoc27.syx +wget -c "${DIR}"/dxoc28.syx -O sysex/voice/000206_dxoc28.syx +wget -c "${DIR}"/dxoc29.syx -O sysex/voice/000207_dxoc29.syx +wget -c "${DIR}"/dxoc30.syx -O sysex/voice/000208_dxoc30.syx +wget -c "${DIR}"/dxorgans.syx -O sysex/voice/000209_dxorgans.syx +wget -c "${DIR}"/dxpluk.syx -O sysex/voice/000210_dxpluk.syx +wget -c "${DIR}"/effect-1.syx -O sysex/voice/000211_effect-1.syx +wget -c "${DIR}"/effect-2.syx -O sysex/voice/000212_effect-2.syx +wget -c "${DIR}"/effects1.syx -O sysex/voice/000213_effects1.syx +wget -c "${DIR}"/effects2.syx -O sysex/voice/000214_effects2.syx +wget -c "${DIR}"/effects3.syx -O sysex/voice/000215_effects3.syx +wget -c "${DIR}"/effects4.syx -O sysex/voice/000216_effects4.syx +wget -c "${DIR}"/effects5.syx -O sysex/voice/000217_effects5.syx +wget -c "${DIR}"/effects6.syx -O sysex/voice/000218_effects6.syx +wget -c "${DIR}"/effects7.syx -O sysex/voice/000219_effects7.syx +wget -c "${DIR}"/effects8.syx -O sysex/voice/000220_effects8.syx +wget -c "${DIR}"/efx.syx -O sysex/voice/000221_efx.syx +wget -c "${DIR}"/esipa.syx -O sysex/voice/000222_esipa.syx +wget -c "${DIR}"/ethnic.syx -O sysex/voice/000223_ethnic.syx +wget -c "${DIR}"/fatstuff.syx -O sysex/voice/000224_fatstuff.syx +wget -c "${DIR}"/flute.syx -O sysex/voice/000225_flute.syx +wget -c "${DIR}"/foo.syx -O sysex/voice/000226_foo.syx +wget -c "${DIR}"/gig-1.syx -O sysex/voice/000227_gig-1.syx +wget -c "${DIR}"/gregeea.syx -O sysex/voice/000228_gregeea.syx +wget -c "${DIR}"/gregeeb.syx -O sysex/voice/000229_gregeeb.syx +wget -c "${DIR}"/gregeec.syx -O sysex/voice/000230_gregeec.syx +wget -c "${DIR}"/gregeed.syx -O sysex/voice/000231_gregeed.syx +wget -c "${DIR}"/gtrs_01.syx -O sysex/voice/000232_gtrs_01.syx +wget -c "${DIR}"/gtrs_a-d.syx -O sysex/voice/000233_gtrs_a-d.syx +wget -c "${DIR}"/gtrs_d.syx -O sysex/voice/000234_gtrs_d.syx +wget -c "${DIR}"/gtrs_el.syx -O sysex/voice/000235_gtrs_el.syx +wget -c "${DIR}"/gtrs_g-j.syx -O sysex/voice/000236_gtrs_g-j.syx +wget -c "${DIR}"/gtrs_j-k.syx -O sysex/voice/000237_gtrs_j-k.syx +wget -c "${DIR}"/gtrs_l-n.syx -O sysex/voice/000238_gtrs_l-n.syx +wget -c "${DIR}"/gtrs_n-r.syx -O sysex/voice/000239_gtrs_n-r.syx +wget -c "${DIR}"/gtrs_s-v.syx -O sysex/voice/000240_gtrs_s-v.syx +wget -c "${DIR}"/gtrsonus.syx -O sysex/voice/000241_gtrsonus.syx +wget -c "${DIR}"/guitar1.syx -O sysex/voice/000242_guitar1.syx +wget -c "${DIR}"/guitar2.syx -O sysex/voice/000243_guitar2.syx +wget -c "${DIR}"/harmonic.syx -O sysex/voice/000244_harmonic.syx +wget -c "${DIR}"/harp_1.syx -O sysex/voice/000245_harp_1.syx +wget -c "${DIR}"/harp_2.syx -O sysex/voice/000246_harp_2.syx +wget -c "${DIR}"/harpsi_1.syx -O sysex/voice/000247_harpsi_1.syx +wget -c "${DIR}"/harpsi_2.syx -O sysex/voice/000248_harpsi_2.syx +wget -c "${DIR}"/italian2.syx -O sysex/voice/000249_italian2.syx +wget -c "${DIR}"/italian3.syx -O sysex/voice/000250_italian3.syx +wget -c "${DIR}"/jb001.syx -O sysex/voice/000251_jb001.syx +wget -c "${DIR}"/jb002.syx -O sysex/voice/000252_jb002.syx +wget -c "${DIR}"/jfd001.syx -O sysex/voice/000253_jfd001.syx +wget -c "${DIR}"/keybds01.syx -O sysex/voice/000254_keybds01.syx +wget -c "${DIR}"/keyboard.syx -O sysex/voice/000255_keyboard.syx +wget -c "${DIR}"/king.syx -O sysex/voice/000256_king.syx +wget -c "${DIR}"/koto.syx -O sysex/voice/000257_koto.syx +wget -c "${DIR}"/kq_sampl.syx -O sysex/voice/000258_kq_sampl.syx +wget -c "${DIR}"/laser.syx -O sysex/voice/000259_laser.syx +wget -c "${DIR}"/magazine.syx -O sysex/voice/000260_magazine.syx +wget -c "${DIR}"/mallets1.syx -O sysex/voice/000261_mallets1.syx +wget -c "${DIR}"/mallets2.syx -O sysex/voice/000262_mallets2.syx +wget -c "${DIR}"/massey.syx -O sysex/voice/000263_massey.syx +wget -c "${DIR}"/metal.syx -O sysex/voice/000264_metal.syx +wget -c "${DIR}"/mf.syx -O sysex/voice/000265_mf.syx +wget -c "${DIR}"/misc_01.syx -O sysex/voice/000266_misc_01.syx +wget -c "${DIR}"/misc_02.syx -O sysex/voice/000267_misc_02.syx +wget -c "${DIR}"/misc_03.syx -O sysex/voice/000268_misc_03.syx +wget -c "${DIR}"/misc_04.syx -O sysex/voice/000269_misc_04.syx +wget -c "${DIR}"/misc_05.syx -O sysex/voice/000270_misc_05.syx +wget -c "${DIR}"/misc_06.syx -O sysex/voice/000271_misc_06.syx +wget -c "${DIR}"/misc_07.syx -O sysex/voice/000272_misc_07.syx +wget -c "${DIR}"/misc_08.syx -O sysex/voice/000273_misc_08.syx +wget -c "${DIR}"/misc_09.syx -O sysex/voice/000274_misc_09.syx +wget -c "${DIR}"/misc_10.syx -O sysex/voice/000275_misc_10.syx +wget -c "${DIR}"/misc_11.syx -O sysex/voice/000276_misc_11.syx +wget -c "${DIR}"/misc_12.syx -O sysex/voice/000277_misc_12.syx +wget -c "${DIR}"/misc_13.syx -O sysex/voice/000278_misc_13.syx +wget -c "${DIR}"/misc_14.syx -O sysex/voice/000279_misc_14.syx +wget -c "${DIR}"/misc_15.syx -O sysex/voice/000280_misc_15.syx +wget -c "${DIR}"/misc_16.syx -O sysex/voice/000281_misc_16.syx +wget -c "${DIR}"/misc_17.syx -O sysex/voice/000282_misc_17.syx +wget -c "${DIR}"/misc_18.syx -O sysex/voice/000283_misc_18.syx +wget -c "${DIR}"/misc_19.syx -O sysex/voice/000284_misc_19.syx +wget -c "${DIR}"/misc_20.syx -O sysex/voice/000285_misc_20.syx +wget -c "${DIR}"/misc_21.syx -O sysex/voice/000286_misc_21.syx +wget -c "${DIR}"/misc_22.syx -O sysex/voice/000287_misc_22.syx +wget -c "${DIR}"/misc_23.syx -O sysex/voice/000288_misc_23.syx +wget -c "${DIR}"/misc_24.syx -O sysex/voice/000289_misc_24.syx +wget -c "${DIR}"/misc_25.syx -O sysex/voice/000290_misc_25.syx +wget -c "${DIR}"/misc_26.syx -O sysex/voice/000291_misc_26.syx +wget -c "${DIR}"/misc_27.syx -O sysex/voice/000292_misc_27.syx +wget -c "${DIR}"/misc_28.syx -O sysex/voice/000293_misc_28.syx +wget -c "${DIR}"/misc_29.syx -O sysex/voice/000294_misc_29.syx +wget -c "${DIR}"/misc_30.syx -O sysex/voice/000295_misc_30.syx +wget -c "${DIR}"/misc_31.syx -O sysex/voice/000296_misc_31.syx +wget -c "${DIR}"/misc_32.syx -O sysex/voice/000297_misc_32.syx +wget -c "${DIR}"/misc_33.syx -O sysex/voice/000298_misc_33.syx +wget -c "${DIR}"/misc_34.syx -O sysex/voice/000299_misc_34.syx +wget -c "${DIR}"/mjfdx7a.syx -O sysex/voice/000300_mjfdx7a.syx +wget -c "${DIR}"/mjfdx7b.syx -O sysex/voice/000301_mjfdx7b.syx +wget -c "${DIR}"/mjfdx7c.syx -O sysex/voice/000302_mjfdx7c.syx +wget -c "${DIR}"/mjfdx7d.syx -O sysex/voice/000303_mjfdx7d.syx +wget -c "${DIR}"/mjfdx7e.syx -O sysex/voice/000304_mjfdx7e.syx +wget -c "${DIR}"/mjfdx7f.syx -O sysex/voice/000305_mjfdx7f.syx +wget -c "${DIR}"/mjfdx7g.syx -O sysex/voice/000306_mjfdx7g.syx +wget -c "${DIR}"/mjfdx7h.syx -O sysex/voice/000307_mjfdx7h.syx +wget -c "${DIR}"/monteleo.syx -O sysex/voice/000308_monteleo.syx +wget -c "${DIR}"/moog.syx -O sysex/voice/000309_moog.syx +wget -c "${DIR}"/mortega.syx -O sysex/voice/000310_mortega.syx +wget -c "${DIR}"/newsnd.syx -O sysex/voice/000311_newsnd.syx +wget -c "${DIR}"/oboe_bas.syx -O sysex/voice/000312_oboe_bas.syx +wget -c "${DIR}"/orch_1.syx -O sysex/voice/000313_orch_1.syx +wget -c "${DIR}"/orchestr.syx -O sysex/voice/000314_orchestr.syx +wget -c "${DIR}"/org_clav.syx -O sysex/voice/000315_org_clav.syx +wget -c "${DIR}"/organ1.syx -O sysex/voice/000316_organ1.syx +wget -c "${DIR}"/organ2.syx -O sysex/voice/000317_organ2.syx +wget -c "${DIR}"/organ3.syx -O sysex/voice/000318_organ3.syx +wget -c "${DIR}"/organ_01.syx -O sysex/voice/000319_organ_01.syx +wget -c "${DIR}"/organ_02.syx -O sysex/voice/000320_organ_02.syx +wget -c "${DIR}"/organ_03.syx -O sysex/voice/000321_organ_03.syx +wget -c "${DIR}"/organ_04.syx -O sysex/voice/000322_organ_04.syx +wget -c "${DIR}"/organ_05.syx -O sysex/voice/000323_organ_05.syx +wget -c "${DIR}"/organ_06.syx -O sysex/voice/000324_organ_06.syx +wget -c "${DIR}"/organ_07.syx -O sysex/voice/000325_organ_07.syx +wget -c "${DIR}"/organ_08.syx -O sysex/voice/000326_organ_08.syx +wget -c "${DIR}"/organ_b3.syx -O sysex/voice/000327_organ_b3.syx +wget -c "${DIR}"/organham.syx -O sysex/voice/000328_organham.syx +wget -c "${DIR}"/orgpipe1.syx -O sysex/voice/000329_orgpipe1.syx +wget -c "${DIR}"/orgpipe2.syx -O sysex/voice/000330_orgpipe2.syx +wget -c "${DIR}"/patches.syx -O sysex/voice/000331_patches.syx +wget -c "${DIR}"/pddx701a.syx -O sysex/voice/000332_pddx701a.syx +wget -c "${DIR}"/pddx701b.syx -O sysex/voice/000333_pddx701b.syx +wget -c "${DIR}"/pddx701c.syx -O sysex/voice/000334_pddx701c.syx +wget -c "${DIR}"/pddx701d.syx -O sysex/voice/000335_pddx701d.syx +wget -c "${DIR}"/pearson.syx -O sysex/voice/000336_pearson.syx +wget -c "${DIR}"/pedanna.syx -O sysex/voice/000337_pedanna.syx +wget -c "${DIR}"/perc1.syx -O sysex/voice/000338_perc1.syx +wget -c "${DIR}"/perc2.syx -O sysex/voice/000339_perc2.syx +wget -c "${DIR}"/perc_a.syx -O sysex/voice/000340_perc_a.syx +wget -c "${DIR}"/perc_b.syx -O sysex/voice/000341_perc_b.syx +wget -c "${DIR}"/percus01.syx -O sysex/voice/000342_percus01.syx +wget -c "${DIR}"/percus02.syx -O sysex/voice/000343_percus02.syx +wget -c "${DIR}"/percus03.syx -O sysex/voice/000344_percus03.syx +wget -c "${DIR}"/percus04.syx -O sysex/voice/000345_percus04.syx +wget -c "${DIR}"/percus05.syx -O sysex/voice/000346_percus05.syx +wget -c "${DIR}"/percus06.syx -O sysex/voice/000347_percus06.syx +wget -c "${DIR}"/percus07.syx -O sysex/voice/000348_percus07.syx +wget -c "${DIR}"/percus08.syx -O sysex/voice/000349_percus08.syx +wget -c "${DIR}"/percus09.syx -O sysex/voice/000350_percus09.syx +wget -c "${DIR}"/percus10.syx -O sysex/voice/000351_percus10.syx +wget -c "${DIR}"/percvibe.syx -O sysex/voice/000352_percvibe.syx +wget -c "${DIR}"/personus.syx -O sysex/voice/000353_personus.syx +wget -c "${DIR}"/piano1.syx -O sysex/voice/000354_piano1.syx +wget -c "${DIR}"/piano_01.syx -O sysex/voice/000355_piano_01.syx +wget -c "${DIR}"/piano_02.syx -O sysex/voice/000356_piano_02.syx +wget -c "${DIR}"/piano_03.syx -O sysex/voice/000357_piano_03.syx +wget -c "${DIR}"/piano_04.syx -O sysex/voice/000358_piano_04.syx +wget -c "${DIR}"/piano_05.syx -O sysex/voice/000359_piano_05.syx +wget -c "${DIR}"/piano_06.syx -O sysex/voice/000360_piano_06.syx +wget -c "${DIR}"/piano_07.syx -O sysex/voice/000361_piano_07.syx +wget -c "${DIR}"/piano_08.syx -O sysex/voice/000362_piano_08.syx +wget -c "${DIR}"/piano_09.syx -O sysex/voice/000363_piano_09.syx +wget -c "${DIR}"/piano_10.syx -O sysex/voice/000364_piano_10.syx +wget -c "${DIR}"/piano_11.syx -O sysex/voice/000365_piano_11.syx +wget -c "${DIR}"/piano_12.syx -O sysex/voice/000366_piano_12.syx +wget -c "${DIR}"/piano_13.syx -O sysex/voice/000367_piano_13.syx +wget -c "${DIR}"/piano_a1.syx -O sysex/voice/000368_piano_a1.syx +wget -c "${DIR}"/piano_e1.syx -O sysex/voice/000369_piano_e1.syx +wget -c "${DIR}"/piano_e2.syx -O sysex/voice/000370_piano_e2.syx +wget -c "${DIR}"/piano_e3.syx -O sysex/voice/000371_piano_e3.syx +wget -c "${DIR}"/piano_e4.syx -O sysex/voice/000372_piano_e4.syx +wget -c "${DIR}"/piano_e5.syx -O sysex/voice/000373_piano_e5.syx +wget -c "${DIR}"/plucked.syx -O sysex/voice/000374_plucked.syx +wget -c "${DIR}"/powerply.syx -O sysex/voice/000375_powerply.syx +wget -c "${DIR}"/pr01.syx -O sysex/voice/000376_pr01.syx +wget -c "${DIR}"/pr02.syx -O sysex/voice/000377_pr02.syx +wget -c "${DIR}"/pr03.syx -O sysex/voice/000378_pr03.syx +wget -c "${DIR}"/pro2.syx -O sysex/voice/000379_pro2.syx +wget -c "${DIR}"/ram_bank.syx -O sysex/voice/000380_ram_bank.syx +wget -c "${DIR}"/ram_cart.syx -O sysex/voice/000381_ram_cart.syx +wget -c "${DIR}"/rambank1.syx -O sysex/voice/000382_rambank1.syx +wget -c "${DIR}"/ramcart.syx -O sysex/voice/000383_ramcart.syx +wget -c "${DIR}"/ramcartp.syx -O sysex/voice/000384_ramcartp.syx +wget -c "${DIR}"/ramnbank.syx -O sysex/voice/000385_ramnbank.syx +wget -c "${DIR}"/ray-1.syx -O sysex/voice/000386_ray-1.syx +wget -c "${DIR}"/ray-10.syx -O sysex/voice/000387_ray-10.syx +wget -c "${DIR}"/ray-11.syx -O sysex/voice/000388_ray-11.syx +wget -c "${DIR}"/ray-12.syx -O sysex/voice/000389_ray-12.syx +wget -c "${DIR}"/ray-13.syx -O sysex/voice/000390_ray-13.syx +wget -c "${DIR}"/ray-14.syx -O sysex/voice/000391_ray-14.syx +wget -c "${DIR}"/ray-15.syx -O sysex/voice/000392_ray-15.syx +wget -c "${DIR}"/ray-16.syx -O sysex/voice/000393_ray-16.syx +wget -c "${DIR}"/ray-17.syx -O sysex/voice/000394_ray-17.syx +wget -c "${DIR}"/ray-18.syx -O sysex/voice/000395_ray-18.syx +wget -c "${DIR}"/ray-19.syx -O sysex/voice/000396_ray-19.syx +wget -c "${DIR}"/ray-2.syx -O sysex/voice/000397_ray-2.syx +wget -c "${DIR}"/ray-20.syx -O sysex/voice/000398_ray-20.syx +wget -c "${DIR}"/ray-21.syx -O sysex/voice/000399_ray-21.syx +wget -c "${DIR}"/ray-3.syx -O sysex/voice/000400_ray-3.syx +wget -c "${DIR}"/ray-4.syx -O sysex/voice/000401_ray-4.syx +wget -c "${DIR}"/ray-5.syx -O sysex/voice/000402_ray-5.syx +wget -c "${DIR}"/ray-6.syx -O sysex/voice/000403_ray-6.syx +wget -c "${DIR}"/ray-7.syx -O sysex/voice/000404_ray-7.syx +wget -c "${DIR}"/ray-8.syx -O sysex/voice/000405_ray-8.syx +wget -c "${DIR}"/ray-9.syx -O sysex/voice/000406_ray-9.syx +wget -c "${DIR}"/rhodes1.syx -O sysex/voice/000407_rhodes1.syx +wget -c "${DIR}"/rhodes2.syx -O sysex/voice/000408_rhodes2.syx +wget -c "${DIR}"/rlegnini.syx -O sysex/voice/000409_rlegnini.syx +wget -c "${DIR}"/rm0001.syx -O sysex/voice/000410_rm0001.syx +wget -c "${DIR}"/rom-1.syx -O sysex/voice/000411_rom-1.syx +wget -c "${DIR}"/rom-2.syx -O sysex/voice/000412_rom-2.syx +wget -c "${DIR}"/rom-3.syx -O sysex/voice/000413_rom-3.syx +wget -c "${DIR}"/rom-4.syx -O sysex/voice/000414_rom-4.syx +wget -c "${DIR}"/sax_01.syx -O sysex/voice/000415_sax_01.syx +wget -c "${DIR}"/sax_02.syx -O sysex/voice/000416_sax_02.syx +wget -c "${DIR}"/sitar.syx -O sysex/voice/000417_sitar.syx +wget -c "${DIR}"/solange.syx -O sysex/voice/000418_solange.syx +wget -c "${DIR}"/solange0.syx -O sysex/voice/000419_solange0.syx +wget -c "${DIR}"/solange1.syx -O sysex/voice/000420_solange1.syx +wget -c "${DIR}"/solange2.syx -O sysex/voice/000421_solange2.syx +wget -c "${DIR}"/solange3.syx -O sysex/voice/000422_solange3.syx +wget -c "${DIR}"/solange4.syx -O sysex/voice/000423_solange4.syx +wget -c "${DIR}"/solange5.syx -O sysex/voice/000424_solange5.syx +wget -c "${DIR}"/solange6.syx -O sysex/voice/000425_solange6.syx +wget -c "${DIR}"/sonus1.syx -O sysex/voice/000426_sonus1.syx +wget -c "${DIR}"/spangler.syx -O sysex/voice/000427_spangler.syx +wget -c "${DIR}"/splits.syx -O sysex/voice/000428_splits.syx +wget -c "${DIR}"/starma.syx -O sysex/voice/000429_starma.syx +wget -c "${DIR}"/steinber.syx -O sysex/voice/000430_steinber.syx +wget -c "${DIR}"/steph1.syx -O sysex/voice/000431_steph1.syx +wget -c "${DIR}"/steph2.syx -O sysex/voice/000432_steph2.syx +wget -c "${DIR}"/steph3.syx -O sysex/voice/000433_steph3.syx +wget -c "${DIR}"/steph4.syx -O sysex/voice/000434_steph4.syx +wget -c "${DIR}"/steve.syx -O sysex/voice/000435_steve.syx +wget -c "${DIR}"/string1.syx -O sysex/voice/000436_string1.syx +wget -c "${DIR}"/string2.syx -O sysex/voice/000437_string2.syx +wget -c "${DIR}"/stringb.syx -O sysex/voice/000438_stringb.syx +wget -c "${DIR}"/strnga-a.syx -O sysex/voice/000439_strnga-a.syx +wget -c "${DIR}"/strnga-b.syx -O sysex/voice/000440_strnga-b.syx +wget -c "${DIR}"/strngb-d.syx -O sysex/voice/000441_strngb-d.syx +wget -c "${DIR}"/strngd-h.syx -O sysex/voice/000442_strngd-h.syx +wget -c "${DIR}"/strngh-k.syx -O sysex/voice/000443_strngh-k.syx +wget -c "${DIR}"/strngk-o.syx -O sysex/voice/000444_strngk-o.syx +wget -c "${DIR}"/strngs01.syx -O sysex/voice/000445_strngs01.syx +wget -c "${DIR}"/strngs02.syx -O sysex/voice/000446_strngs02.syx +wget -c "${DIR}"/strngs03.syx -O sysex/voice/000447_strngs03.syx +wget -c "${DIR}"/strngs04.syx -O sysex/voice/000448_strngs04.syx +wget -c "${DIR}"/strngs05.syx -O sysex/voice/000449_strngs05.syx +wget -c "${DIR}"/strngs06.syx -O sysex/voice/000450_strngs06.syx +wget -c "${DIR}"/strngs07.syx -O sysex/voice/000451_strngs07.syx +wget -c "${DIR}"/strngs08.syx -O sysex/voice/000452_strngs08.syx +wget -c "${DIR}"/strngs09.syx -O sysex/voice/000453_strngs09.syx +wget -c "${DIR}"/strngs10.syx -O sysex/voice/000454_strngs10.syx +wget -c "${DIR}"/strngs12.syx -O sysex/voice/000455_strngs12.syx +wget -c "${DIR}"/strngs13.syx -O sysex/voice/000456_strngs13.syx +wget -c "${DIR}"/strngs14.syx -O sysex/voice/000457_strngs14.syx +wget -c "${DIR}"/strngs15.syx -O sysex/voice/000458_strngs15.syx +wget -c "${DIR}"/strngs16.syx -O sysex/voice/000459_strngs16.syx +wget -c "${DIR}"/strngs17.syx -O sysex/voice/000460_strngs17.syx +wget -c "${DIR}"/strngs18.syx -O sysex/voice/000461_strngs18.syx +wget -c "${DIR}"/strngs19.syx -O sysex/voice/000462_strngs19.syx +wget -c "${DIR}"/strngs20.syx -O sysex/voice/000463_strngs20.syx +wget -c "${DIR}"/sustain1.syx -O sysex/voice/000464_sustain1.syx +wget -c "${DIR}"/synth_01.syx -O sysex/voice/000465_synth_01.syx +wget -c "${DIR}"/synth_02.syx -O sysex/voice/000466_synth_02.syx +wget -c "${DIR}"/synth_03.syx -O sysex/voice/000467_synth_03.syx +wget -c "${DIR}"/synth_04.syx -O sysex/voice/000468_synth_04.syx +wget -c "${DIR}"/synth_05.syx -O sysex/voice/000469_synth_05.syx +wget -c "${DIR}"/synth_06.syx -O sysex/voice/000470_synth_06.syx +wget -c "${DIR}"/synth_07.syx -O sysex/voice/000471_synth_07.syx +wget -c "${DIR}"/synth_08.syx -O sysex/voice/000472_synth_08.syx +wget -c "${DIR}"/synth_09.syx -O sysex/voice/000473_synth_09.syx +wget -c "${DIR}"/synth_10.syx -O sysex/voice/000474_synth_10.syx +wget -c "${DIR}"/synth_11.syx -O sysex/voice/000475_synth_11.syx +wget -c "${DIR}"/synth_12.syx -O sysex/voice/000476_synth_12.syx +wget -c "${DIR}"/synth_13.syx -O sysex/voice/000477_synth_13.syx +wget -c "${DIR}"/synth_14.syx -O sysex/voice/000478_synth_14.syx +wget -c "${DIR}"/synth_15.syx -O sysex/voice/000479_synth_15.syx +wget -c "${DIR}"/synth_16.syx -O sysex/voice/000480_synth_16.syx +wget -c "${DIR}"/synth_17.syx -O sysex/voice/000481_synth_17.syx +wget -c "${DIR}"/synth_18.syx -O sysex/voice/000482_synth_18.syx +wget -c "${DIR}"/synth_19.syx -O sysex/voice/000483_synth_19.syx +wget -c "${DIR}"/synth_20.syx -O sysex/voice/000484_synth_20.syx +wget -c "${DIR}"/synth_21.syx -O sysex/voice/000485_synth_21.syx +wget -c "${DIR}"/synth_22.syx -O sysex/voice/000486_synth_22.syx +wget -c "${DIR}"/synths.syx -O sysex/voice/000487_synths.syx +wget -c "${DIR}"/syx_0628.syx -O sysex/voice/000488_syx_0628.syx +wget -c "${DIR}"/textures.syx -O sysex/voice/000489_textures.syx +wget -c "${DIR}"/tfi5.syx -O sysex/voice/000490_tfi5.syx +wget -c "${DIR}"/tfi6.syx -O sysex/voice/000491_tfi6.syx +wget -c "${DIR}"/tfi7.syx -O sysex/voice/000492_tfi7.syx +wget -c "${DIR}"/tfi8.syx -O sysex/voice/000493_tfi8.syx +wget -c "${DIR}"/tfrack01.syx -O sysex/voice/000494_tfrack01.syx +wget -c "${DIR}"/tfrack02.syx -O sysex/voice/000495_tfrack02.syx +wget -c "${DIR}"/theatre.syx -O sysex/voice/000496_theatre.syx +wget -c "${DIR}"/things.syx -O sysex/voice/000497_things.syx +wget -c "${DIR}"/trumpet.syx -O sysex/voice/000498_trumpet.syx +wget -c "${DIR}"/tx7a.syx -O sysex/voice/000499_tx7a.syx +wget -c "${DIR}"/violin_1.syx -O sysex/voice/000500_violin_1.syx +wget -c "${DIR}"/voices_1.syx -O sysex/voice/000501_voices_1.syx +wget -c "${DIR}"/voices_2.syx -O sysex/voice/000502_voices_2.syx +wget -c "${DIR}"/voices_3.syx -O sysex/voice/000503_voices_3.syx +wget -c "${DIR}"/voices_5.syx -O sysex/voice/000504_voices_5.syx +wget -c "${DIR}"/voices_6.syx -O sysex/voice/000505_voices_6.syx +wget -c "${DIR}"/voices_7.syx -O sysex/voice/000506_voices_7.syx +wget -c "${DIR}"/voices_8.syx -O sysex/voice/000507_voices_8.syx +wget -c "${DIR}"/voices_9.syx -O sysex/voice/000508_voices_9.syx +wget -c "${DIR}"/weird1.syx -O sysex/voice/000509_weird1.syx +wget -c "${DIR}"/weird2.syx -O sysex/voice/000510_weird2.syx +wget -c "${DIR}"/weird3.syx -O sysex/voice/000511_weird3.syx +wget -c "${DIR}"/wheatley.syx -O sysex/voice/000512_wheatley.syx +wget -c "${DIR}"/white.syx -O sysex/voice/000513_white.syx +wget -c "${DIR}"/wodwind1.syx -O sysex/voice/000514_wodwind1.syx +wget -c "${DIR}"/wodwind2.syx -O sysex/voice/000515_wodwind2.syx +wget -c "${DIR}"/wodwind3.syx -O sysex/voice/000516_wodwind3.syx +wget -c "${DIR}"/wodwind4.syx -O sysex/voice/000517_wodwind4.syx +wget -c "${DIR}"/wodwind5.syx -O sysex/voice/000518_wodwind5.syx +wget -c "${DIR}"/wodwind6.syx -O sysex/voice/000519_wodwind6.syx +wget -c "${DIR}"/woodwind.syx -O sysex/voice/000520_woodwind.syx +wget -c "${DIR}"/wurlizer.syx -O sysex/voice/000521_wurlizer.syx +wget -c "${DIR}"/wwind1.syx -O sysex/voice/000522_wwind1.syx +wget -c "${DIR}"/wwind2.syx -O sysex/voice/000523_wwind2.syx +wget -c "${DIR}"/wwind3.syx -O sysex/voice/000524_wwind3.syx +wget -c "${DIR}"/wwind4.syx -O sysex/voice/000525_wwind4.syx +wget -c "${DIR}"/wyatt.syx -O sysex/voice/000526_wyatt.syx +wget -c "${DIR}"/xylos.syx -O sysex/voice/000527_xylos.syx +wget -c "${DIR}"/yam-26.syx -O sysex/voice/000528_yam-26.syx +wget -c "${DIR}"/yamaha.syx -O sysex/voice/000529_yamaha.syx +wget -c "${DIR}"/zone3.syx -O sysex/voice/000530_zone3.syx diff --git a/incrementalBuild.sh b/incrementalBuild.sh new file mode 100644 index 0000000..6dd6a14 --- /dev/null +++ b/incrementalBuild.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +set -e +set -x + +if [ -z "${RPI}" ] ; then +# echo "\$RPI missing, exting" +# exit 1 + export RPI=4 +fi + +if [ "${RPI}" -gt "2" ]; then + export TOOLCHAIN_PREFIX="aarch64-none-elf-" +else + export TOOLCHAIN_PREFIX="arm-none-eabi-" +fi + +# Define system options +OPTIONS="-o USE_PWM_AUDIO_ON_ZERO -o SAVE_VFP_REGS_ON_IRQ -o REALTIME -o SCREEN_DMA_BURST_LENGTH=1" +if [ "${RPI}" -gt "1" ]; then + OPTIONS="${OPTIONS} -o ARM_ALLOW_MULTI_CORE" +fi + +# Build circle-stdlib library +# cd circle-stdlib/ +# make mrproper || true +# ./configure -r ${RPI} --prefix "${TOOLCHAIN_PREFIX}" ${OPTIONS} -o KERNEL_MAX_SIZE=0x400000 +# make -j + +# Build additional libraries +# cd libs/circle/addon/display/ +# make clean || true +# make -j +# cd ../sensor/ +# make clean || true +# make -j +# cd ../Properties/ +# make clean || true +# make -j +# cd ../../../.. + +# cd .. + +# Build MiniDexed +cd src +# make clean || true +make -j +ls *.img +cd .. diff --git a/rebuild.sh b/rebuild.sh new file mode 100644 index 0000000..827d87f --- /dev/null +++ b/rebuild.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +set -e +set -x + +export RPI=4 + +export PATH=$(readlink -f ./gcc-*/bin/):$PATH + +./incrementalBuild.sh +cp ./src/kernel*.img ./kernels/ + +# Make zip that contains Raspberry Pi 4 boot files. The contents can be copied to a FAT32 formatted partition on a microSD card +cp -r ./circle-stdlib/libs/circle/boot/* sdcard +rm -rf sdcard/config*.txt sdcard/README sdcard/Makefile sdcard/armstub sdcard/COPYING.linux +cp ./src/config.txt ./src/minidexed.ini ./src/*img ./src/performance.ini sdcard/ +echo "usbspeed=full" > sdcard/cmdline.txt +cd sdcard +cp ../kernels/* . || true +zip -r ../MiniDexed_$GITHUB_RUN_NUMBER_$(date +%Y-%m-%d).zip * +cd - + +echo "DONE!!!" \ No newline at end of file diff --git a/setup_dev_env.sh b/setup_dev_env.sh new file mode 100644 index 0000000..6457c7d --- /dev/null +++ b/setup_dev_env.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# this script install the dev environment and assume that the repositorw is alreadw cloned + +# Choose your RPi +export RPI=4 + +#git clone https://github.com/probonopd/MiniDexed +#cd MiniDexed +mkdir -p kernels sdcard + +# Get develop branch of circle +cd circle-stdlib/libs/circle +git checkout ae22928 # develop +cd - + +# Recursively pull git submodules +git submodule update --init --recursive + +# Install toolchain +if [ "${RPI}" -gt 2 ] +then + wget https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz +else + wget https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-arm-none-eabi.tar.xz +fi +tar xvf gcc-arm-*-*.tar.xz +export PATH=$(readlink -f ./gcc-*/bin/):$PATH + +# Build dependencies and MiniDexed +./build.sh +cp ./src/kernel*.img ./kernels/ + +# Get Raspberry Pi boot files +cd ./circle-stdlib/libs/circle/boot +make +if [ "${RPI}" -gt 2 ] +then + make armstub64 +fi +cd - + +# Make zip that contains Raspberry Pi 4 boot files. The contents can be copied to a FAT32 formatted partition on a microSD card +cd sdcard +../getsysex.sh +cd .. +cp -r ./circle-stdlib/libs/circle/boot/* sdcard +rm -rf sdcard/config*.txt sdcard/README sdcard/Makefile sdcard/armstub sdcard/COPYING.linux +cp ./src/config.txt ./src/minidexed.ini ./src/*img ./src/performance.ini sdcard/ +echo "usbspeed=full" > sdcard/cmdline.txt +cd sdcard +cp ../kernels/* . || true +zip -r ../MaxiDexed_$GITHUB_RUN_NUMBER_$(date +%Y-%m-%d).zip * +cd - + +# # Optionally, create a RPi image. This can be written to a microSD card using tools like Etcher or dd +# sudo apt install --yes mount parted +# IMG="`date +%Y-%m-%d`_minidexed-RPi${RPI}.img" +# dd of="${IMG}" seek=50MiB bs=1 count=0 +# sudo parted "${IMG}" mktable msdos +# sudo parted "${IMG}" mkpart primary fat32 2048s 100% +# DEV=`sudo losetup --find --partscan --show "${IMG}"` +# sudo mkfs.vfat -F 32 -n BOOT "${DEV}p1" +# mkdir boot +# sudo mount "${DEV}p1" boot +# sudo cp -R sdcard/* boot +# sudo umount boot +# sudo losetup -d "${DEV}" +# rm -r boot + +# # Write to SD card +# sudo dd if="${IMG}" of=/dev/mmcblk0 bs=512k status=progress && sync \ No newline at end of file diff --git a/src/Makefile b/src/Makefile index 3ea9c78..e983896 100644 --- a/src/Makefile +++ b/src/Makefile @@ -5,11 +5,29 @@ CIRCLE_STDLIB_DIR = ../circle-stdlib SYNTH_DEXED_DIR = ../Synth_Dexed/src CMSIS_DIR = ../CMSIS_5/CMSIS +U8G2_DIR = ../u8g2 -OBJS = main.o kernel.o minidexed.o config.o userinterface.o uimenu.o \ - mididevice.o midikeyboard.o serialmididevice.o pckeyboard.o \ - sysexfileloader.o performanceconfig.o perftimer.o \ - effect_compressor.o effect_platervbstereo.o +BUILD_DIR = ../build +BUILD_OBJ_DIR = $(BUILD_DIR)/objs + +OBJS = main.o \ + kernel.o \ + minidexed.o \ + config.o \ + userinterface.o \ + uimenu.o \ + mididevice.o \ + midikeyboard.o \ + serialmididevice.o \ + pckeyboard.o \ + sysexfileloader.o \ + performanceconfig.o \ + perftimer.o \ + effect_compressor.o \ + effect_platervbstereo.o \ + ui.o \ + screens.o \ + userinterfaceext.o OPTIMIZE = -O3 diff --git a/src/Rules.mk b/src/Rules.mk index 39b9f25..5559f15 100644 --- a/src/Rules.mk +++ b/src/Rules.mk @@ -11,7 +11,9 @@ include $(CIRCLEHOME)/Rules.mk INCLUDE += \ -I $(CIRCLE_STDLIB_DIR)/include \ - -I $(NEWLIBDIR)/include + -I $(NEWLIBDIR)/include \ + -I $(U8H2_DIR)/csrc \ + -I $(U8H2_DIR)/cppsrc LIBS += \ $(NEWLIBDIR)/lib/libm.a \ diff --git a/src/Synth_Dexed.mk b/src/Synth_Dexed.mk index 443d606..9309fed 100644 --- a/src/Synth_Dexed.mk +++ b/src/Synth_Dexed.mk @@ -9,6 +9,119 @@ CMSIS_DSP_COMPUTELIB_INCLUDE_DIR = $(CMSIS_DIR)/DSP/ComputeLibrary/Include CMSIS_DSP_SOURCE_DIR = $(CMSIS_DIR)/DSP/Source CMSIS_DSP_COMPUTELIB_SRC_DIR = $(CMSIS_DIR)/DSP/ComputeLibrary/Source +U8G2_OBJS += \ + $(U8G2_DIR)/cppsrc/U8g2lib.o \ + $(U8G2_DIR)/csrc/mui.o \ + $(U8G2_DIR)/csrc/mui_u8g2.o \ + $(U8G2_DIR)/csrc/u8g2_bitmap.o \ + $(U8G2_DIR)/csrc/u8g2_box.o \ + $(U8G2_DIR)/csrc/u8g2_buffer.o \ + $(U8G2_DIR)/csrc/u8g2_button.o \ + $(U8G2_DIR)/csrc/u8g2_circle.o \ + $(U8G2_DIR)/csrc/u8g2_cleardisplay.o \ + $(U8G2_DIR)/csrc/u8g2_d_memory.o \ + $(U8G2_DIR)/csrc/u8g2_d_setup.o \ + $(U8G2_DIR)/csrc/u8g2_font.o \ + $(U8G2_DIR)/csrc/u8g2_fonts.o \ + $(U8G2_DIR)/csrc/u8g2_hvline.o \ + $(U8G2_DIR)/csrc/u8g2_input_value.o \ + $(U8G2_DIR)/csrc/u8g2_intersection.o \ + $(U8G2_DIR)/csrc/u8g2_kerning.o \ + $(U8G2_DIR)/csrc/u8g2_line.o \ + $(U8G2_DIR)/csrc/u8g2_ll_hvline.o \ + $(U8G2_DIR)/csrc/u8g2_message.o \ + $(U8G2_DIR)/csrc/u8g2_polygon.o \ + $(U8G2_DIR)/csrc/u8g2_selection_list.o \ + $(U8G2_DIR)/csrc/u8g2_setup.o \ + $(U8G2_DIR)/csrc/u8log.o \ + $(U8G2_DIR)/csrc/u8log_u8g2.o \ + $(U8G2_DIR)/csrc/u8log_u8x8.o \ + $(U8G2_DIR)/csrc/u8x8_8x8.o \ + $(U8G2_DIR)/csrc/u8x8_byte.o \ + $(U8G2_DIR)/csrc/u8x8_cad.o \ + $(U8G2_DIR)/csrc/u8x8_capture.o \ + $(U8G2_DIR)/csrc/u8x8_d_a2printer.o \ + $(U8G2_DIR)/csrc/u8x8_d_gu800.o \ + $(U8G2_DIR)/csrc/u8x8_d_hd44102.o \ + $(U8G2_DIR)/csrc/u8x8_d_il3820_296x128.o \ + $(U8G2_DIR)/csrc/u8x8_d_ist3020.o \ + $(U8G2_DIR)/csrc/u8x8_d_ist7920.o \ + $(U8G2_DIR)/csrc/u8x8_d_ks0108.o \ + $(U8G2_DIR)/csrc/u8x8_d_lc7981.o \ + $(U8G2_DIR)/csrc/u8x8_d_ld7032_60x32.o \ + $(U8G2_DIR)/csrc/u8x8_d_ls013b7dh03.o \ + $(U8G2_DIR)/csrc/u8x8_d_max7219.o \ + $(U8G2_DIR)/csrc/u8x8_d_pcd8544_84x48.o \ + $(U8G2_DIR)/csrc/u8x8_d_pcf8812.o \ + $(U8G2_DIR)/csrc/u8x8_d_pcf8814_hx1230.o \ + $(U8G2_DIR)/csrc/u8x8_d_s1d15721.o \ + $(U8G2_DIR)/csrc/u8x8_d_s1d15e06.o \ + $(U8G2_DIR)/csrc/u8x8_d_sbn1661.o \ + $(U8G2_DIR)/csrc/u8x8_d_sed1330.o \ + $(U8G2_DIR)/csrc/u8x8_d_sh1106_64x32.o \ + $(U8G2_DIR)/csrc/u8x8_d_sh1106_72x40.o \ + $(U8G2_DIR)/csrc/u8x8_d_sh1107.o \ + $(U8G2_DIR)/csrc/u8x8_d_sh1108.o \ + $(U8G2_DIR)/csrc/u8x8_d_sh1122.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1305.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1306_128x32.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1306_128x64_noname.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1306_2040x16.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1306_48x64.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1306_64x32.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1306_64x48.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1306_72x40.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1306_96x16.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1306_96x40.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1309.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1316.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1317.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1318.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1320.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1322.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1325.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1326.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1327.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1329.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1606_172x72.o \ + $(U8G2_DIR)/csrc/u8x8_d_ssd1607_200x200.o \ + $(U8G2_DIR)/csrc/u8x8_d_st7511.o \ + $(U8G2_DIR)/csrc/u8x8_d_st75160.o \ + $(U8G2_DIR)/csrc/u8x8_d_st75256.o \ + $(U8G2_DIR)/csrc/u8x8_d_st7528.o \ + $(U8G2_DIR)/csrc/u8x8_d_st75320.o \ + $(U8G2_DIR)/csrc/u8x8_d_st7565.o \ + $(U8G2_DIR)/csrc/u8x8_d_st7567.o \ + $(U8G2_DIR)/csrc/u8x8_d_st7571.o \ + $(U8G2_DIR)/csrc/u8x8_d_st7586s_erc240160.o \ + $(U8G2_DIR)/csrc/u8x8_d_st7586s_s028hn118a.o \ + $(U8G2_DIR)/csrc/u8x8_d_st7586s_ymc240160.o \ + $(U8G2_DIR)/csrc/u8x8_d_st7588.o \ + $(U8G2_DIR)/csrc/u8x8_d_st7920.o \ + $(U8G2_DIR)/csrc/u8x8_d_stdio.o \ + $(U8G2_DIR)/csrc/u8x8_d_t6963.o \ + $(U8G2_DIR)/csrc/u8x8_d_uc1601.o \ + $(U8G2_DIR)/csrc/u8x8_d_uc1604.o \ + $(U8G2_DIR)/csrc/u8x8_d_uc1608.o \ + $(U8G2_DIR)/csrc/u8x8_d_uc1609.o \ + $(U8G2_DIR)/csrc/u8x8_d_uc1610.o \ + $(U8G2_DIR)/csrc/u8x8_d_uc1611.o \ + $(U8G2_DIR)/csrc/u8x8_d_uc1617.o \ + $(U8G2_DIR)/csrc/u8x8_d_uc1638.o \ + $(U8G2_DIR)/csrc/u8x8_d_uc1701_dogs102.o \ + $(U8G2_DIR)/csrc/u8x8_d_uc1701_mini12864.o \ + $(U8G2_DIR)/csrc/u8x8_debounce.o \ + $(U8G2_DIR)/csrc/u8x8_display.o \ + $(U8G2_DIR)/csrc/u8x8_fonts.o \ + $(U8G2_DIR)/csrc/u8x8_gpio.o \ + $(U8G2_DIR)/csrc/u8x8_input_value.o \ + $(U8G2_DIR)/csrc/u8x8_message.o \ + $(U8G2_DIR)/csrc/u8x8_selection_list.o \ + $(U8G2_DIR)/csrc/u8x8_setup.o \ + $(U8G2_DIR)/csrc/u8x8_string.o \ + $(U8G2_DIR)/csrc/u8x8_u16toa.o \ + $(U8G2_DIR)/csrc/u8x8_u8toa.o + OBJS += \ $(SYNTH_DEXED_DIR)/PluginFx.o \ $(SYNTH_DEXED_DIR)/dexed.o \ @@ -27,19 +140,22 @@ OBJS += \ $(CMSIS_DSP_SOURCE_DIR)/FastMathFunctions/FastMathFunctions.o \ $(CMSIS_DSP_SOURCE_DIR)/FilteringFunctions/FilteringFunctions.o \ $(CMSIS_DSP_SOURCE_DIR)/CommonTables/CommonTables.o \ - $(CMSIS_DSP_COMPUTELIB_SRC_DIR)/arm_cl_tables.o + $(CMSIS_DSP_COMPUTELIB_SRC_DIR)/arm_cl_tables.o \ + $(U8G2_OBJS) INCLUDE += -I $(SYNTH_DEXED_DIR) INCLUDE += -I $(CMSIS_CORE_INCLUDE_DIR) INCLUDE += -I $(CMSIS_DSP_INCLUDE_DIR) INCLUDE += -I $(CMSIS_DSP_PRIVATE_INCLUDE_DIR) INCLUDE += -I $(CMSIS_DSP_COMPUTELIB_INCLUDE_DIR) +INCLUDE += -I $(U8G2_DIR)/csrc +INCLUDE += -I $(U8G2_DIR)/cppsrc -DEFINE += -DUSE_FX +DEFINE += -DUSE_FX -DU8X8_USE_PINS ifeq ($(strip $(AARCH)),64) DEFINE += -DARM_MATH_NEON DEFINE += -DHAVE_NEON endif -EXTRACLEAN = $(SYNTH_DEXED_DIR)/*.[od] $(CMSIS_DSP_SOURCE_DIR)/SupportFunctions/*.[od] $(CMSIS_DSP_SOURCE_DIR)/SupportFunctions/*.[od] $(CMSIS_DSP_SOURCE_DIR)/BasicMathFunctions/*.[od] $(CMSIS_DSP_SOURCE_DIR)/FastMathFunctions/*.[od] $(CMSIS_DSP_SOURCE_DIR)/FilteringFunctions/*.[od] $(CMSIS_DSP_SOURCE_DIR)/CommonTables/*.[od] $(CMSIS_DSP_COMPUTELIB_SRC_DIR)/*.[od] +EXTRACLEAN = $(SYNTH_DEXED_DIR)/*.[od] $(CMSIS_DSP_SOURCE_DIR)/SupportFunctions/*.[od] $(CMSIS_DSP_SOURCE_DIR)/SupportFunctions/*.[od] $(CMSIS_DSP_SOURCE_DIR)/BasicMathFunctions/*.[od] $(CMSIS_DSP_SOURCE_DIR)/FastMathFunctions/*.[od] $(CMSIS_DSP_SOURCE_DIR)/FilteringFunctions/*.[od] $(CMSIS_DSP_SOURCE_DIR)/CommonTables/*.[od] $(CMSIS_DSP_COMPUTELIB_SRC_DIR)/*.[od] $(U8G2_DIR)/cppsrc/*.[od] $(U8G2_DIR)/csrc/*.[od] diff --git a/src/mididevice.cpp b/src/mididevice.cpp index 4e15cf1..23f53f9 100644 --- a/src/mididevice.cpp +++ b/src/mididevice.cpp @@ -20,42 +20,27 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . // - -#include #include "mididevice.h" #include "minidexed.h" #include "config.h" #include #include -LOGMODULE ("mididevice"); - #define MIDI_NOTE_OFF 0b1000 #define MIDI_NOTE_ON 0b1001 #define MIDI_AFTERTOUCH 0b1010 // TODO #define MIDI_CONTROL_CHANGE 0b1011 #define MIDI_CC_BANK_SELECT_MSB 0 // TODO - #define MIDI_CC_MODULATION 1 - #define MIDI_CC_VOLUME 7 - #define MIDI_CC_PAN_POSITION 10 + #define MIDI_CC_MODULATION 1 + #define MIDI_CC_VOLUME 7 #define MIDI_CC_BANK_SELECT_LSB 32 #define MIDI_CC_BANK_SUSTAIN 64 - #define MIDI_CC_RESONANCE 71 - #define MIDI_CC_FREQUENCY_CUTOFF 74 - #define MIDI_CC_REVERB_LEVEL 91 - #define MIDI_CC_DETUNE_LEVEL 94 - #define MIDI_CC_ALL_SOUND_OFF 120 - #define MIDI_CC_ALL_NOTES_OFF 123 #define MIDI_PROGRAM_CHANGE 0b1100 #define MIDI_PITCH_BEND 0b1110 -#define MIDI_SYSTEM_EXCLUSIVE_BEGIN 0xF0 -#define MIDI_SYSTEM_EXCLUSIVE_END 0xF7 #define MIDI_TIMING_CLOCK 0xF8 #define MIDI_ACTIVE_SENSING 0xFE -CMIDIDevice::TDeviceMap CMIDIDevice::s_DeviceMap; - CMIDIDevice::CMIDIDevice (CMiniDexed *pSynthesizer, CConfig *pConfig) : m_pSynthesizer (pSynthesizer), m_pConfig (pConfig) @@ -85,6 +70,8 @@ u8 CMIDIDevice::GetChannel (unsigned nTG) const void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsigned nCable) { + assert (m_pSynthesizer != 0); + // The packet contents are just normal MIDI data - see // https://www.midi.org/specifications/item/table-1-summary-of-midi-message @@ -110,366 +97,113 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign (unsigned) pMessage[0], (unsigned) pMessage[1], (unsigned) pMessage[2]); break; - default: - switch(pMessage[0]) - { - case MIDI_SYSTEM_EXCLUSIVE_BEGIN: - printf("MIDI%u: SysEx data length: [%d]:",nCable, uint16_t(nLength)); - for (uint16_t i = 0; i < nLength; i++) - { - if((i % 16) == 0) - printf("\n%04d:",i); - printf(" 0x%02x",pMessage[i]); - } - printf("\n"); - break; - default: - printf("MIDI%u: Unhandled MIDI event type %0x02x\n",nCable,pMessage[0]); - } - break; - } - } - - // Only for debugging: -/* - if(pMessage[0]==MIDI_SYSTEM_EXCLUSIVE_BEGIN) - { - printf("MIDI%u: SysEx data length: [%d]:",nCable, uint16_t(nLength)); - for (uint16_t i = 0; i < nLength; i++) - { - if((i % 16) == 0) - printf("\n%04d:",i); - printf(" 0x%02x",pMessage[i]); - } - printf("\n"); - } -*/ - - // Handle MIDI Thru - if (m_DeviceName.compare (m_pConfig->GetMIDIThruIn ()) == 0) - { - TDeviceMap::const_iterator Iterator; - - Iterator = s_DeviceMap.find (m_pConfig->GetMIDIThruOut ()); - if (Iterator != s_DeviceMap.end ()) - { - Iterator->second->Send (pMessage, nLength, nCable); } } if (nLength < 2) { - LOGERR("MIDI message is shorter than 2 bytes!"); return; } - m_MIDISpinLock.Acquire (); - u8 ucStatus = pMessage[0]; u8 ucChannel = ucStatus & 0x0F; u8 ucType = ucStatus >> 4; - // GLOBAL MIDI SYSEX - if (pMessage[0] == MIDI_SYSTEM_EXCLUSIVE_BEGIN && pMessage[3] == 0x04 && pMessage[4] == 0x01 && pMessage[nLength-1] == MIDI_SYSTEM_EXCLUSIVE_END) // MASTER VOLUME - { - float32_t nMasterVolume=((pMessage[5] & 0x7c) & ((pMessage[6] & 0x7c) <<7))/(1<<14); - LOGNOTE("Master volume: %f",nMasterVolume); - m_pSynthesizer->setMasterVolume(nMasterVolume); - } - else + for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) { - for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) + if ( m_ChannelMap[nTG] == ucChannel + || m_ChannelMap[nTG] == OmniMode) { - if (ucStatus == MIDI_SYSTEM_EXCLUSIVE_BEGIN) + switch (ucType) { - // MIDI SYSEX per MIDI channel - uint8_t ucSysExChannel = (pMessage[2] & 0x07); - if (m_ChannelMap[nTG] == ucSysExChannel || m_ChannelMap[nTG] == OmniMode) + case MIDI_NOTE_ON: + if (nLength < 3) { - LOGNOTE("MIDI-SYSEX: channel: %u, len: %u, TG: %u",m_ChannelMap[nTG],nLength,nTG); - HandleSystemExclusive(pMessage, nLength, nCable, nTG); + break; } - } - else - { - if ( m_ChannelMap[nTG] == ucChannel - || m_ChannelMap[nTG] == OmniMode) + + if (pMessage[2] > 0) { - switch (ucType) + if (pMessage[2] <= 127) { - case MIDI_NOTE_ON: - if (nLength < 3) - { - break; - } - - if (pMessage[2] > 0) - { - if (pMessage[2] <= 127) - { - m_pSynthesizer->keydown (pMessage[1], - pMessage[2], nTG); - } - } - else - { - m_pSynthesizer->keyup (pMessage[1], nTG); - } - break; - - case MIDI_NOTE_OFF: - if (nLength < 3) - { - break; - } - - m_pSynthesizer->keyup (pMessage[1], nTG); - break; - - case MIDI_CONTROL_CHANGE: - if (nLength < 3) - { - break; - } - - switch (pMessage[1]) - { - case MIDI_CC_MODULATION: - m_pSynthesizer->setModWheel (pMessage[2], nTG); - m_pSynthesizer->ControllersRefresh (nTG); - break; - - case MIDI_CC_VOLUME: - m_pSynthesizer->SetVolume (pMessage[2], nTG); - break; - - case MIDI_CC_PAN_POSITION: - m_pSynthesizer->SetPan (pMessage[2], nTG); - break; - - case MIDI_CC_BANK_SELECT_LSB: - m_pSynthesizer->BankSelectLSB (pMessage[2], nTG); - break; - - case MIDI_CC_BANK_SUSTAIN: - m_pSynthesizer->setSustain (pMessage[2] >= 64, nTG); - break; - - case MIDI_CC_RESONANCE: - m_pSynthesizer->SetResonance (maplong (pMessage[2], 0, 127, 0, 99), nTG); - break; - - case MIDI_CC_FREQUENCY_CUTOFF: - m_pSynthesizer->SetCutoff (maplong (pMessage[2], 0, 127, 0, 99), nTG); - break; - - case MIDI_CC_REVERB_LEVEL: - m_pSynthesizer->SetReverbSend (maplong (pMessage[2], 0, 127, 0, 99), nTG); - break; - - case MIDI_CC_DETUNE_LEVEL: - if (pMessage[2] == 0) - { - // "0 to 127, with 0 being no celeste (detune) effect applied at all." - m_pSynthesizer->SetMasterTune (0, nTG); - } - else - { - m_pSynthesizer->SetMasterTune (maplong (pMessage[2], 1, 127, -99, 99), nTG); - } - break; - - case MIDI_CC_ALL_SOUND_OFF: - m_pSynthesizer->panic (pMessage[2], nTG); - break; - - case MIDI_CC_ALL_NOTES_OFF: - m_pSynthesizer->notesOff (pMessage[2], nTG); - break; - } - break; - - case MIDI_PROGRAM_CHANGE: - // do program change only if enabled in config - if( m_pConfig->GetMIDIRXProgramChange() ) - m_pSynthesizer->ProgramChange (pMessage[1], nTG); - break; - - case MIDI_PITCH_BEND: { - if (nLength < 3) - { - break; - } - - s16 nValue = pMessage[1]; - nValue |= (s16) pMessage[2] << 7; - nValue -= 0x2000; - - m_pSynthesizer->setPitchbend (nValue, nTG); - } break; - - default: - break; + m_pSynthesizer->keydown (pMessage[1], + pMessage[2], nTG); } } - } - } - } - m_MIDISpinLock.Release (); -} + else + { + m_pSynthesizer->keyup (pMessage[1], nTG); + } + break; -void CMIDIDevice::AddDevice (const char *pDeviceName) -{ - assert (pDeviceName); + case MIDI_NOTE_OFF: + if (nLength < 3) + { + break; + } - assert (m_DeviceName.empty ()); - m_DeviceName = pDeviceName; - assert (!m_DeviceName.empty ()); + m_pSynthesizer->keyup (pMessage[1], nTG); + break; - s_DeviceMap.insert (std::pair (pDeviceName, this)); -} + case MIDI_CONTROL_CHANGE: + if (nLength < 3) + { + break; + } -void CMIDIDevice::HandleSystemExclusive(const uint8_t* pMessage, const size_t nLength, const unsigned nCable, const uint8_t nTG) -{ - int16_t sysex_return; + switch (pMessage[1]) + { + case MIDI_CC_MODULATION: + m_pSynthesizer->setModWheel (pMessage[2], nTG); + m_pSynthesizer->ControllersRefresh (nTG); + break; - sysex_return = m_pSynthesizer->checkSystemExclusive(pMessage, nLength, nTG); - LOGDBG("SYSEX handler return value: %d", sysex_return); + case MIDI_CC_VOLUME: + m_pSynthesizer->SetVolume (pMessage[2], nTG); + break; - switch (sysex_return) - { - case -1: - LOGERR("SysEx end status byte not detected."); - break; - case -2: - LOGERR("SysEx vendor not Yamaha."); - break; - case -3: - LOGERR("Unknown SysEx parameter change."); - break; - case -4: - LOGERR("Unknown SysEx voice or function."); - break; - case -5: - LOGERR("Not a SysEx voice bulk upload."); - break; - case -6: - LOGERR("Wrong length for SysEx voice bulk upload (not 155)."); - break; - case -7: - LOGERR("Checksum error for one voice."); - break; - case -8: - LOGERR("Not a SysEx bank bulk upload."); - break; - case -9: - LOGERR("Wrong length for SysEx bank bulk upload (not 4096)."); - case -10: - LOGERR("Checksum error for bank."); - break; - case -11: - LOGERR("Unknown SysEx message."); - break; - case 64: - LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); - m_pSynthesizer->setMonoMode(pMessage[5],nTG); - break; - case 65: - LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); - m_pSynthesizer->setPitchbendRange(pMessage[5],nTG); - break; - case 66: - LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); - m_pSynthesizer->setPitchbendStep(pMessage[5],nTG); - break; - case 67: - LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); - m_pSynthesizer->setPortamentoMode(pMessage[5],nTG); - break; - case 68: - LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); - m_pSynthesizer->setPortamentoGlissando(pMessage[5],nTG); - break; - case 69: - LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); - m_pSynthesizer->setPortamentoTime(pMessage[5],nTG); - break; - case 70: - LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); - m_pSynthesizer->setModWheelRange(pMessage[5],nTG); - break; - case 71: - LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); - m_pSynthesizer->setModWheelTarget(pMessage[5],nTG); - break; - case 72: - LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); - m_pSynthesizer->setFootControllerRange(pMessage[5],nTG); - break; - case 73: - LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); - m_pSynthesizer->setFootControllerTarget(pMessage[5],nTG); - break; - case 74: - LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); - m_pSynthesizer->setBreathControllerRange(pMessage[5],nTG); - break; - case 75: - LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); - m_pSynthesizer->setBreathControllerTarget(pMessage[5],nTG); - break; - case 76: - LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); - m_pSynthesizer->setAftertouchRange(pMessage[5],nTG); - break; - case 77: - LOGDBG("SysEx Function parameter change: %d Value %d",pMessage[4],pMessage[5]); - m_pSynthesizer->setAftertouchTarget(pMessage[5],nTG); - break; - case 100: - // load sysex-data into voice memory - LOGDBG("One Voice bulk upload"); - m_pSynthesizer->loadVoiceParameters(pMessage,nTG); - break; - case 200: - LOGDBG("Bank bulk upload."); - //TODO: add code for storing a bank bulk upload - LOGNOTE("Currently code for storing a bulk bank upload is missing!"); - break; - default: - if(sysex_return >= 300 && sysex_return < 500) - { - LOGDBG("SysEx voice parameter change: Parameter %d value: %d",pMessage[4] + ((pMessage[3] & 0x03) * 128), pMessage[5]); - m_pSynthesizer->setVoiceDataElement(pMessage[4] + ((pMessage[3] & 0x03) * 128), pMessage[5],nTG); - switch(pMessage[4] + ((pMessage[3] & 0x03) * 128)) - { - case 134: - m_pSynthesizer->notesOff(0,nTG); - break; - } - } - else if(sysex_return >= 500 && sysex_return < 600) - { - LOGDBG("SysEx send voice %u request",sysex_return-500); - SendSystemExclusiveVoice(sysex_return-500, nCable, nTG); - } - break; - } -} + case MIDI_CC_BANK_SELECT_MSB: + { + int bank = m_pSynthesizer->GetTGParameter (CMiniDexed::TGParameterVoiceBank, nTG); + bank = (pMessage[2] << 7) + (bank & 0b01111111); + m_pSynthesizer->BankSelect (bank, nTG); + } + break; -void CMIDIDevice::SendSystemExclusiveVoice(uint8_t nVoice, const unsigned nCable, uint8_t nTG) -{ - uint8_t voicedump[163]; + case MIDI_CC_BANK_SELECT_LSB: + { + int bank = m_pSynthesizer->GetTGParameter (CMiniDexed::TGParameterVoiceBank, nTG); + bank = (bank & 0b011111110000000) + pMessage[2]; + m_pSynthesizer->BankSelect (bank, nTG); + } + break; + + case MIDI_CC_BANK_SUSTAIN: + m_pSynthesizer->setSustain (pMessage[2] >= 64, nTG); + break; + } + break; + + case MIDI_PROGRAM_CHANGE: + m_pSynthesizer->ProgramChange (pMessage[1], nTG); + break; - // Get voice sysex dump from TG - m_pSynthesizer->getSysExVoiceDump(voicedump, nTG); + case MIDI_PITCH_BEND: { + if (nLength < 3) + { + break; + } + + s16 nValue = pMessage[1]; + nValue |= (s16) pMessage[2] << 7; + nValue -= 0x2000; - TDeviceMap::const_iterator Iterator; + m_pSynthesizer->setPitchbend (nValue, nTG); + } break; - // send voice dump to all MIDI interfaces - for(Iterator = s_DeviceMap.begin(); Iterator != s_DeviceMap.end(); ++Iterator) - { - Iterator->second->Send (voicedump, sizeof(voicedump)*sizeof(uint8_t)); - LOGDBG("Send SYSEX voice dump %u to \"%s\"",nVoice,Iterator->first.c_str()); - } -} + default: + break; + } + } + } +} diff --git a/src/minidexed.cpp b/src/minidexed.cpp index c09eb42..2211bc4 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -37,7 +36,7 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, CMultiCoreSupport (CMemorySystem::Get ()), #endif m_pConfig (pConfig), - m_UI (this, pGPIOManager, pI2CMaster, pConfig), + m_UI (this, pGPIOManager, pConfig), m_PerformanceConfig (pFileSystem), m_PCKeyboard (this, pConfig), m_SerialMIDI (this, pInterrupt, pConfig), @@ -49,10 +48,7 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, #endif m_GetChunkTimer ("GetChunk", 1000000U * pConfig->GetChunkSize ()/2 / pConfig->GetSampleRate ()), - m_bProfileEnabled (m_pConfig->GetProfileEnabled ()), - m_bSavePerformance (false), - m_bSavePerformanceNewFile (false), - m_bSetNewPerformance (false) + m_bProfileEnabled (m_pConfig->GetProfileEnabled ()) { assert (m_pConfig); @@ -66,18 +62,12 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, m_nCutoff[i] = 99; m_nResonance[i] = 0; m_nMIDIChannel[i] = CMIDIDevice::Disabled; - m_nPitchBendRange[i] = 2; - m_nPitchBendStep[i] = 0; - m_nPortamentoMode[i] = 0; - m_nPortamentoGlissando[i] = 0; - m_nPortamentoTime[i] = 0; m_nNoteLimitLow[i] = 0; m_nNoteLimitHigh[i] = 127; m_nNoteShift[i] = 0; m_nReverbSend[i] = 0; - m_uchOPMask[i] = 0b111111; // All operators on m_pTG[i] = new CDexedAdapter (CConfig::MaxNotes, pConfig->GetSampleRate ()); assert (m_pTG[i]); @@ -127,8 +117,6 @@ CMiniDexed::CMiniDexed (CConfig *pConfig, CInterruptSystem *pInterrupt, } #endif - setMasterVolume(1.0); - // BEGIN setup tg_mixer tg_mixer = new AudioStereoMixer(pConfig->GetChunkSize()/2); // END setup tgmixer @@ -158,6 +146,7 @@ bool CMiniDexed::Initialize (void) return false; } + m_UI.ImmediateLCDWrite("Loading all banks & presets."); m_SysExFileLoader.Load (); if (m_SerialMIDI.Initialize ()) @@ -176,7 +165,7 @@ bool CMiniDexed::Initialize (void) m_pTG[i]->setTranspose (24); - m_pTG[i]->setPBController (2, 0); + m_pTG[i]->setPBController (12, 1); m_pTG[i]->setMWController (99, 7, 0); tg_mixer->pan(i,mapfloat(m_nPan[i],0,127,0.0f,1.0f)); @@ -187,19 +176,39 @@ bool CMiniDexed::Initialize (void) if (m_PerformanceConfig.Load ()) { - LoadPerformanceParameters(); + for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) + { + BankSelect (m_PerformanceConfig.GetBankNumber (nTG), nTG); + ProgramChange (m_PerformanceConfig.GetVoiceNumber (nTG), nTG); + SetMIDIChannel (m_PerformanceConfig.GetMIDIChannel (nTG), nTG); + SetVolume (m_PerformanceConfig.GetVolume (nTG), nTG); + SetPan (m_PerformanceConfig.GetPan (nTG), nTG); + SetMasterTune (m_PerformanceConfig.GetDetune (nTG), nTG); + SetCutoff (m_PerformanceConfig.GetCutoff (nTG), nTG); + SetResonance (m_PerformanceConfig.GetResonance (nTG), nTG); + + m_nNoteLimitLow[nTG] = m_PerformanceConfig.GetNoteLimitLow (nTG); + m_nNoteLimitHigh[nTG] = m_PerformanceConfig.GetNoteLimitHigh (nTG); + m_nNoteShift[nTG] = m_PerformanceConfig.GetNoteShift (nTG); + + SetReverbSend (m_PerformanceConfig.GetReverbSend (nTG), nTG); + } + + // Effects + SetParameter (ParameterCompressorEnable, m_PerformanceConfig.GetCompressorEnable () ? 1 : 0); + SetParameter (ParameterReverbEnable, m_PerformanceConfig.GetReverbEnable () ? 1 : 0); + SetParameter (ParameterReverbSize, m_PerformanceConfig.GetReverbSize ()); + SetParameter (ParameterReverbHighDamp, m_PerformanceConfig.GetReverbHighDamp ()); + SetParameter (ParameterReverbLowDamp, m_PerformanceConfig.GetReverbLowDamp ()); + SetParameter (ParameterReverbLowPass, m_PerformanceConfig.GetReverbLowPass ()); + SetParameter (ParameterReverbDiffusion, m_PerformanceConfig.GetReverbDiffusion ()); + SetParameter (ParameterReverbLevel, m_PerformanceConfig.GetReverbLevel ()); } else { SetMIDIChannel (CMIDIDevice::OmniMode, 0); } - - // load performances file list, and attempt to create the performance folder - if (!m_PerformanceConfig.ListPerformances()) - { - LOGERR ("Cannot create internal Performance folder, new performances can't be created"); - } - + // setup and start the sound device if (!m_pSoundDevice->AllocateQueueFrames (m_pConfig->GetChunkSize ())) { @@ -250,25 +259,6 @@ void CMiniDexed::Process (bool bPlugAndPlayUpdated) m_UI.Process (); - if (m_bSavePerformance) - { - DoSavePerformance (); - - m_bSavePerformance = false; - } - - if (m_bSavePerformanceNewFile) - { - DoSavePerformanceNewFile (); - m_bSavePerformanceNewFile = false; - } - - if (m_bSetNewPerformance) - { - DoSetNewPerformance (); - m_bSetNewPerformance = false; - } - if (m_bProfileEnabled) { m_GetChunkTimer.Dump (); @@ -340,12 +330,12 @@ CSysExFileLoader *CMiniDexed::GetSysExFileLoader (void) return &m_SysExFileLoader; } -void CMiniDexed::BankSelectLSB (unsigned nBankLSB, unsigned nTG) +void CMiniDexed::BankSelect (unsigned nBank, unsigned nTG) { - nBankLSB=constrain((int)nBankLSB,0,127); + nBank=constrain((int)nBank,0,1 << 14 - 1); assert (nTG < CConfig::ToneGenerators); - m_nVoiceBankID[nTG] = nBankLSB; + m_nVoiceBankID[nTG] = nBank; m_UI.ParameterChanged (); } @@ -362,7 +352,6 @@ void CMiniDexed::ProgramChange (unsigned nProgram, unsigned nTG) assert (m_pTG[nTG]); m_pTG[nTG]->loadVoiceParameters (Buffer); - m_SerialMIDI.SendSystemExclusiveVoice(nProgram,0,nTG); m_UI.ParameterChanged (); } @@ -444,8 +433,6 @@ void CMiniDexed::SetResonance (int nResonance, unsigned nTG) m_UI.ParameterChanged (); } - - void CMiniDexed::SetMIDIChannel (uint8_t uchChannel, unsigned nTG) { assert (nTG < CConfig::ToneGenerators); @@ -534,24 +521,6 @@ void CMiniDexed::setSustain(bool sustain, unsigned nTG) m_pTG[nTG]->setSustain (sustain); } -void CMiniDexed::panic(uint8_t value, unsigned nTG) -{ - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - if (value == 0) { - m_pTG[nTG]->panic (); - } -} - -void CMiniDexed::notesOff(uint8_t value, unsigned nTG) -{ - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - if (value == 0) { - m_pTG[nTG]->notesOff (); - } -} - void CMiniDexed::setModWheel (uint8_t value, unsigned nTG) { assert (nTG < CConfig::ToneGenerators); @@ -657,18 +626,13 @@ void CMiniDexed::SetTGParameter (TTGParameter Parameter, int nValue, unsigned nT switch (Parameter) { - case TGParameterVoiceBank: BankSelectLSB (nValue, nTG); break; + case TGParameterVoiceBank: BankSelect (nValue, nTG); break; case TGParameterProgram: ProgramChange (nValue, nTG); break; case TGParameterVolume: SetVolume (nValue, nTG); break; case TGParameterPan: SetPan (nValue, nTG); break; case TGParameterMasterTune: SetMasterTune (nValue, nTG); break; case TGParameterCutoff: SetCutoff (nValue, nTG); break; case TGParameterResonance: SetResonance (nValue, nTG); break; - case TGParameterPitchBendRange: setPitchbendRange (nValue, nTG); break; - case TGParameterPitchBendStep: setPitchbendStep (nValue, nTG); break; - case TGParameterPortamentoMode: setPortamentoMode (nValue, nTG); break; - case TGParameterPortamentoGlissando: setPortamentoGlissando (nValue, nTG); break; - case TGParameterPortamentoTime: setPortamentoTime (nValue, nTG); break; case TGParameterMIDIChannel: assert (0 <= nValue && nValue <= 255); @@ -698,11 +662,6 @@ int CMiniDexed::GetTGParameter (TTGParameter Parameter, unsigned nTG) case TGParameterResonance: return m_nResonance[nTG]; case TGParameterMIDIChannel: return m_nMIDIChannel[nTG]; case TGParameterReverbSend: return m_nReverbSend[nTG]; - case TGParameterPitchBendRange: return m_nPitchBendRange[nTG]; - case TGParameterPitchBendStep: return m_nPitchBendStep[nTG]; - case TGParameterPortamentoMode: return m_nPortamentoMode[nTG]; - case TGParameterPortamentoGlissando: return m_nPortamentoGlissando[nTG]; - case TGParameterPortamentoTime: return m_nPortamentoTime[nTG]; default: assert (0); @@ -718,22 +677,6 @@ void CMiniDexed::SetVoiceParameter (uint8_t uchOffset, uint8_t uchValue, unsigne if (nOP < 6) { - if (uchOffset == DEXED_OP_ENABLE) - { - if (uchValue) - { - m_uchOPMask[nTG] |= 1 << nOP; - } - else - { - m_uchOPMask[nTG] &= ~(1 << nOP); - } - - m_pTG[nTG]->setOPAll (m_uchOPMask[nTG]); - - return; - } - nOP = 5 - nOP; // OPs are in reverse order } @@ -751,11 +694,6 @@ uint8_t CMiniDexed::GetVoiceParameter (uint8_t uchOffset, unsigned nOP, unsigned if (nOP < 6) { - if (uchOffset == DEXED_OP_ENABLE) - { - return !!(m_uchOPMask[nTG] & (1 << nOP)); - } - nOP = 5 - nOP; // OPs are in reverse order } @@ -867,70 +805,56 @@ void CMiniDexed::ProcessSound (void) } // BEGIN TG mixing - float32_t tmp_float[nFrames*2]; - int16_t tmp_int[nFrames*2]; + for (uint8_t i = 0; i < CConfig::ToneGenerators; i++) + { + tg_mixer->doAddMix(i,m_OutputLevel[i]); + reverb_send_mixer->doAddMix(i,m_OutputLevel[i]); + } + // END TG mixing + + // BEGIN create SampleBuffer for holding audio data + float32_t SampleBuffer[2][nFrames]; + // END create SampleBuffer for holding audio data - if(nMasterVolume > 0.0) + // get the mix of all TGs + tg_mixer->getMix(SampleBuffer[indexL], SampleBuffer[indexR]); + + // BEGIN adding reverb + if (m_nParameter[ParameterReverbEnable]) { - for (uint8_t i = 0; i < CConfig::ToneGenerators; i++) - { - tg_mixer->doAddMix(i,m_OutputLevel[i]); - reverb_send_mixer->doAddMix(i,m_OutputLevel[i]); - } - // END TG mixing - - // BEGIN create SampleBuffer for holding audio data - float32_t SampleBuffer[2][nFrames]; - // END create SampleBuffer for holding audio data + float32_t ReverbBuffer[2][nFrames]; + float32_t ReverbSendBuffer[2][nFrames]; - // get the mix of all TGs - tg_mixer->getMix(SampleBuffer[indexL], SampleBuffer[indexR]); + arm_fill_f32(0.0f, ReverbBuffer[indexL], nFrames); + arm_fill_f32(0.0f, ReverbBuffer[indexR], nFrames); + arm_fill_f32(0.0f, ReverbSendBuffer[indexR], nFrames); + arm_fill_f32(0.0f, ReverbSendBuffer[indexL], nFrames); - // BEGIN adding reverb - if (m_nParameter[ParameterReverbEnable]) - { - float32_t ReverbBuffer[2][nFrames]; - float32_t ReverbSendBuffer[2][nFrames]; + m_ReverbSpinLock.Acquire (); - arm_fill_f32(0.0f, ReverbBuffer[indexL], nFrames); - arm_fill_f32(0.0f, ReverbBuffer[indexR], nFrames); - arm_fill_f32(0.0f, ReverbSendBuffer[indexR], nFrames); - arm_fill_f32(0.0f, ReverbSendBuffer[indexL], nFrames); - - m_ReverbSpinLock.Acquire (); - - reverb_send_mixer->getMix(ReverbSendBuffer[indexL], ReverbSendBuffer[indexR]); - reverb->doReverb(ReverbSendBuffer[indexL],ReverbSendBuffer[indexR],ReverbBuffer[indexL], ReverbBuffer[indexR],nFrames); - - // scale down and add left reverb buffer by reverb level - arm_scale_f32(ReverbBuffer[indexL], reverb->get_level(), ReverbBuffer[indexL], nFrames); - arm_add_f32(SampleBuffer[indexL], ReverbBuffer[indexL], SampleBuffer[indexL], nFrames); - // scale down and add right reverb buffer by reverb level - arm_scale_f32(ReverbBuffer[indexR], reverb->get_level(), ReverbBuffer[indexR], nFrames); - arm_add_f32(SampleBuffer[indexR], ReverbBuffer[indexR], SampleBuffer[indexR], nFrames); - - m_ReverbSpinLock.Release (); - } - // END adding reverb - - // Convert dual float array (left, right) to single int16 array (left/right) - for(uint16_t i=0; i0.0 && nMasterVolume <1.0) - { - tmp_float[i*2]=SampleBuffer[indexL][i] * nMasterVolume; - tmp_float[(i*2)+1]=SampleBuffer[indexR][i] * nMasterVolume; - } - else if(nMasterVolume == 1.0) - { - tmp_float[i*2]=SampleBuffer[indexL][i]; - tmp_float[(i*2)+1]=SampleBuffer[indexR][i]; - } - } - arm_float_to_q15(tmp_float,tmp_int,nFrames*2); + reverb_send_mixer->getMix(ReverbSendBuffer[indexL], ReverbSendBuffer[indexR]); + reverb->doReverb(ReverbSendBuffer[indexL],ReverbSendBuffer[indexR],ReverbBuffer[indexL], ReverbBuffer[indexR],nFrames); + + // scale down and add left reverb buffer by reverb level + arm_scale_f32(ReverbBuffer[indexL], reverb->get_level(), ReverbBuffer[indexL], nFrames); + arm_add_f32(SampleBuffer[indexL], ReverbBuffer[indexL], SampleBuffer[indexL], nFrames); + // scale down and add right reverb buffer by reverb level + arm_scale_f32(ReverbBuffer[indexR], reverb->get_level(), ReverbBuffer[indexR], nFrames); + arm_add_f32(SampleBuffer[indexR], ReverbBuffer[indexR], SampleBuffer[indexR], nFrames); + + m_ReverbSpinLock.Release (); } - else - arm_fill_q15(0, tmp_int, nFrames * 2); + // END adding reverb + + // Convert dual float array (left, right) to single int16 array (left/right) + float32_t tmp_float[nFrames*2]; + int16_t tmp_int[nFrames*2]; + for(uint16_t i=0; iWrite (tmp_int, sizeof(tmp_int)) != (int) sizeof(tmp_int)) { @@ -947,13 +871,6 @@ void CMiniDexed::ProcessSound (void) #endif bool CMiniDexed::SavePerformance (void) -{ - m_bSavePerformance = true; - - return true; -} - -bool CMiniDexed::DoSavePerformance (void) { for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) { @@ -965,18 +882,11 @@ bool CMiniDexed::DoSavePerformance (void) m_PerformanceConfig.SetDetune (m_nMasterTune[nTG], nTG); m_PerformanceConfig.SetCutoff (m_nCutoff[nTG], nTG); m_PerformanceConfig.SetResonance (m_nResonance[nTG], nTG); - m_PerformanceConfig.SetPitchBendRange (m_nPitchBendRange[nTG], nTG); - m_PerformanceConfig.SetPitchBendStep (m_nPitchBendStep[nTG], nTG); - m_PerformanceConfig.SetPortamentoMode (m_nPortamentoMode[nTG], nTG); - m_PerformanceConfig.SetPortamentoGlissando (m_nPortamentoGlissando[nTG], nTG); - m_PerformanceConfig.SetPortamentoTime (m_nPortamentoTime[nTG], nTG); m_PerformanceConfig.SetNoteLimitLow (m_nNoteLimitLow[nTG], nTG); m_PerformanceConfig.SetNoteLimitHigh (m_nNoteLimitHigh[nTG], nTG); m_PerformanceConfig.SetNoteShift (m_nNoteShift[nTG], nTG); - m_pTG[nTG]->getVoiceData(m_nRawVoiceData); - m_PerformanceConfig.SetVoiceDataToTxt (m_nRawVoiceData, nTG); - + m_PerformanceConfig.SetReverbSend (m_nReverbSend[nTG], nTG); } @@ -991,364 +901,3 @@ bool CMiniDexed::DoSavePerformance (void) return m_PerformanceConfig.Save (); } - -void CMiniDexed::setMonoMode(uint8_t mono, uint8_t nTG) -{ - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - - m_pTG[nTG]->setMonoMode(constrain(mono, 0, 1)); - m_pTG[nTG]->doRefreshVoice(); - m_UI.ParameterChanged (); -} - -void CMiniDexed::setPitchbendRange(uint8_t range, uint8_t nTG) -{ - range = constrain (range, 0, 12); - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - m_nPitchBendRange[nTG] = range; - - m_pTG[nTG]->setPitchbendRange(range); - m_pTG[nTG]->ControllersRefresh(); - m_UI.ParameterChanged (); -} - -void CMiniDexed::setPitchbendStep(uint8_t step, uint8_t nTG) -{ - step= constrain (step, 0, 12); - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - m_nPitchBendStep[nTG] = step; - - m_pTG[nTG]->setPitchbendStep(step); - m_pTG[nTG]->ControllersRefresh(); - m_UI.ParameterChanged (); -} - -void CMiniDexed::setPortamentoMode(uint8_t mode, uint8_t nTG) -{ - mode= constrain (mode, 0, 1); - - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - m_nPortamentoMode[nTG] = mode; - - m_pTG[nTG]->setPortamentoMode(mode); - m_pTG[nTG]->ControllersRefresh(); - m_UI.ParameterChanged (); -} - -void CMiniDexed::setPortamentoGlissando(uint8_t glissando, uint8_t nTG) -{ - glissando = constrain (glissando, 0, 1); - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - m_nPortamentoGlissando[nTG] = glissando; - - m_pTG[nTG]->setPortamentoGlissando(glissando); - m_pTG[nTG]->ControllersRefresh(); - m_UI.ParameterChanged (); -} - -void CMiniDexed::setPortamentoTime(uint8_t time, uint8_t nTG) -{ - time = constrain (time, 0, 99); - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - m_nPortamentoTime[nTG] = time; - - m_pTG[nTG]->setPortamentoTime(time); - m_pTG[nTG]->ControllersRefresh(); - m_UI.ParameterChanged (); -} - -void CMiniDexed::setModWheelRange(uint8_t range, uint8_t nTG) -{ - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - - m_pTG[nTG]->setModWheelRange(constrain(range, 0, 99)); - m_pTG[nTG]->ControllersRefresh(); - m_UI.ParameterChanged (); -} - -void CMiniDexed::setModWheelTarget(uint8_t target, uint8_t nTG) -{ - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - - m_pTG[nTG]->setModWheelTarget(constrain(target, 0, 7)); - m_pTG[nTG]->ControllersRefresh(); - m_UI.ParameterChanged (); -} - -void CMiniDexed::setFootControllerRange(uint8_t range, uint8_t nTG) -{ - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - - m_pTG[nTG]->setFootControllerRange(constrain(range, 0, 99)); - m_pTG[nTG]->ControllersRefresh(); - m_UI.ParameterChanged (); -} - -void CMiniDexed::setFootControllerTarget(uint8_t target, uint8_t nTG) -{ - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - - m_pTG[nTG]->setFootControllerTarget(constrain(target, 0, 7)); - m_pTG[nTG]->ControllersRefresh(); - m_UI.ParameterChanged (); -} - -void CMiniDexed::setBreathControllerRange(uint8_t range, uint8_t nTG) -{ - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - - m_pTG[nTG]->setBreathControllerRange(constrain(range, 0, 99)); - m_pTG[nTG]->ControllersRefresh(); - m_UI.ParameterChanged (); -} - -void CMiniDexed::setBreathControllerTarget(uint8_t target, uint8_t nTG) -{ - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - - m_pTG[nTG]->setBreathControllerTarget(constrain(target, 0, 7)); - m_pTG[nTG]->ControllersRefresh(); - m_UI.ParameterChanged (); -} - -void CMiniDexed::setAftertouchRange(uint8_t range, uint8_t nTG) -{ - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - - m_pTG[nTG]->setAftertouchRange(constrain(range, 0, 99)); - m_pTG[nTG]->ControllersRefresh(); - m_UI.ParameterChanged (); -} - -void CMiniDexed::setAftertouchTarget(uint8_t target, uint8_t nTG) -{ - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - - m_pTG[nTG]->setAftertouchTarget(constrain(target, 0, 7)); - m_pTG[nTG]->ControllersRefresh(); - m_UI.ParameterChanged (); -} - -void CMiniDexed::loadVoiceParameters(const uint8_t* data, uint8_t nTG) -{ - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - - uint8_t voice[161]; - - memcpy(voice, data, sizeof(uint8_t)*161); - - // fix voice name - for (uint8_t i = 0; i < 10; i++) - { - if (voice[151 + i] > 126) // filter characters - voice[151 + i] = 32; - } - - m_pTG[nTG]->loadVoiceParameters(&voice[6]); - m_pTG[nTG]->doRefreshVoice(); - m_UI.ParameterChanged (); -} - -void CMiniDexed::setVoiceDataElement(uint8_t data, uint8_t number, uint8_t nTG) -{ - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - - m_pTG[nTG]->setVoiceDataElement(constrain(data, 0, 155),constrain(number, 0, 99)); - //m_pTG[nTG]->doRefreshVoice(); - m_UI.ParameterChanged (); -} - -int16_t CMiniDexed::checkSystemExclusive(const uint8_t* pMessage,const uint16_t nLength, uint8_t nTG) -{ - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - - return(m_pTG[nTG]->checkSystemExclusive(pMessage, nLength)); -} - -void CMiniDexed::getSysExVoiceDump(uint8_t* dest, uint8_t nTG) -{ - uint8_t checksum = 0; - uint8_t data[155]; - - assert (nTG < CConfig::ToneGenerators); - assert (m_pTG[nTG]); - - m_pTG[nTG]->getVoiceData(data); - - dest[0] = 0xF0; // SysEx start - dest[1] = 0x43; // ID=Yamaha - dest[2] = GetTGParameter(TGParameterMIDIChannel, nTG); // Sub-status and MIDI channel - dest[3] = 0x00; // Format number (0=1 voice) - dest[4] = 0x01; // Byte count MSB - dest[5] = 0x1B; // Byte count LSB - for (uint8_t n = 0; n < 155; n++) - { - checksum -= data[n]; - dest[6 + n] = data[n]; - } - dest[161] = checksum & 0x7f; // Checksum - dest[162] = 0xF7; // SysEx end -} - -void CMiniDexed::setMasterVolume (float32_t vol) -{ - if(vol < 0.0) - vol = 0.0; - else if(vol > 1.0) - vol = 1.0; - - nMasterVolume=vol; -} - -std::string CMiniDexed::GetPerformanceFileName(unsigned nID) -{ - return m_PerformanceConfig.GetPerformanceFileName(nID); -} - -std::string CMiniDexed::GetPerformanceName(unsigned nID) -{ - return m_PerformanceConfig.GetPerformanceName(nID); -} - -unsigned CMiniDexed::GetLastPerformance() -{ - return m_PerformanceConfig.GetLastPerformance(); -} - - - -unsigned CMiniDexed::GetActualPerformanceID() -{ - return m_PerformanceConfig.GetActualPerformanceID(); -} - -void CMiniDexed::SetActualPerformanceID(unsigned nID) -{ - m_PerformanceConfig.SetActualPerformanceID(nID); -} - -unsigned CMiniDexed::GetMenuSelectedPerformanceID() -{ - return m_PerformanceConfig.GetMenuSelectedPerformanceID(); -} - -void CMiniDexed::SetMenuSelectedPerformanceID(unsigned nID) -{ - m_PerformanceConfig.SetMenuSelectedPerformanceID(nID); -} - - -bool CMiniDexed::SetNewPerformance(unsigned nID) -{ - m_bSetNewPerformance = true; - m_nSetNewPerformanceID = nID; - - return true; -} - -bool CMiniDexed::DoSetNewPerformance (void) -{ - unsigned nID = m_nSetNewPerformanceID; - m_PerformanceConfig.SetNewPerformance(nID); - - if (m_PerformanceConfig.Load ()) - { - LoadPerformanceParameters(); - return true; - } - else - { - SetMIDIChannel (CMIDIDevice::OmniMode, 0); - return false; - } -} - -bool CMiniDexed::SavePerformanceNewFile () -{ - m_bSavePerformanceNewFile = m_PerformanceConfig.GetInternalFolderOk(); - return m_bSavePerformanceNewFile; -} - -bool CMiniDexed::DoSavePerformanceNewFile (void) -{ - std::string nPerformanceName=""; // for future enhacements: capability to write performance name - if (m_PerformanceConfig.CreateNewPerformanceFile(nPerformanceName)) - { - if(SavePerformance()) - { - return true; - } - else - { - return false; - } - } - else - { - return false; - } - -} - - -void CMiniDexed::LoadPerformanceParameters(void) -{ - for (unsigned nTG = 0; nTG < CConfig::ToneGenerators; nTG++) - { - - BankSelectLSB (m_PerformanceConfig.GetBankNumber (nTG), nTG); - ProgramChange (m_PerformanceConfig.GetVoiceNumber (nTG), nTG); - SetMIDIChannel (m_PerformanceConfig.GetMIDIChannel (nTG), nTG); - SetVolume (m_PerformanceConfig.GetVolume (nTG), nTG); - SetPan (m_PerformanceConfig.GetPan (nTG), nTG); - SetMasterTune (m_PerformanceConfig.GetDetune (nTG), nTG); - SetCutoff (m_PerformanceConfig.GetCutoff (nTG), nTG); - SetResonance (m_PerformanceConfig.GetResonance (nTG), nTG); - setPitchbendRange (m_PerformanceConfig.GetPitchBendRange (nTG), nTG); - setPitchbendStep (m_PerformanceConfig.GetPitchBendStep (nTG), nTG); - setPortamentoMode (m_PerformanceConfig.GetPortamentoMode (nTG), nTG); - setPortamentoGlissando (m_PerformanceConfig.GetPortamentoGlissando (nTG), nTG); - setPortamentoTime (m_PerformanceConfig.GetPortamentoTime (nTG), nTG); - - m_nNoteLimitLow[nTG] = m_PerformanceConfig.GetNoteLimitLow (nTG); - m_nNoteLimitHigh[nTG] = m_PerformanceConfig.GetNoteLimitHigh (nTG); - m_nNoteShift[nTG] = m_PerformanceConfig.GetNoteShift (nTG); - - if(m_PerformanceConfig.VoiceDataFilled(nTG)) - { - uint8_t* tVoiceData = m_PerformanceConfig.GetVoiceDataFromTxt(nTG); - m_pTG[nTG]->loadVoiceParameters(tVoiceData); - } - - SetReverbSend (m_PerformanceConfig.GetReverbSend (nTG), nTG); - - } - - // Effects - SetParameter (ParameterCompressorEnable, m_PerformanceConfig.GetCompressorEnable () ? 1 : 0); - SetParameter (ParameterReverbEnable, m_PerformanceConfig.GetReverbEnable () ? 1 : 0); - SetParameter (ParameterReverbSize, m_PerformanceConfig.GetReverbSize ()); - SetParameter (ParameterReverbHighDamp, m_PerformanceConfig.GetReverbHighDamp ()); - SetParameter (ParameterReverbLowDamp, m_PerformanceConfig.GetReverbLowDamp ()); - SetParameter (ParameterReverbLowPass, m_PerformanceConfig.GetReverbLowPass ()); - SetParameter (ParameterReverbDiffusion, m_PerformanceConfig.GetReverbDiffusion ()); - SetParameter (ParameterReverbLevel, m_PerformanceConfig.GetReverbLevel ()); -} - diff --git a/src/minidexed.h b/src/minidexed.h index 6945845..96740ad 100644 --- a/src/minidexed.h +++ b/src/minidexed.h @@ -63,7 +63,7 @@ public: CSysExFileLoader *GetSysExFileLoader (void); - void BankSelectLSB (unsigned nBankLSB, unsigned nTG); + void BankSelect (unsigned nBank, unsigned nTG); void ProgramChange (unsigned nProgram, unsigned nTG); void SetVolume (unsigned nVolume, unsigned nTG); void SetPan (unsigned nPan, unsigned nTG); // 0 .. 127 @@ -76,47 +76,12 @@ public: void keydown (int16_t pitch, uint8_t velocity, unsigned nTG); void setSustain (bool sustain, unsigned nTG); - void panic (uint8_t value, unsigned nTG); - void notesOff (uint8_t value, unsigned nTG); void setModWheel (uint8_t value, unsigned nTG); void setPitchbend (int16_t value, unsigned nTG); void ControllersRefresh (unsigned nTG); void SetReverbSend (unsigned nReverbSend, unsigned nTG); // 0 .. 127 - void setMonoMode(uint8_t mono, uint8_t nTG); - void setPitchbendRange(uint8_t range, uint8_t nTG); - void setPitchbendStep(uint8_t step, uint8_t nTG); - void setPortamentoMode(uint8_t mode, uint8_t nTG); - void setPortamentoGlissando(uint8_t glissando, uint8_t nTG); - void setPortamentoTime(uint8_t time, uint8_t nTG); - void setModWheelRange(uint8_t range, uint8_t nTG); - void setModWheelTarget(uint8_t target, uint8_t nTG); - void setFootControllerRange(uint8_t range, uint8_t nTG); - void setFootControllerTarget(uint8_t target, uint8_t nTG); - void setBreathControllerRange(uint8_t range, uint8_t nTG); - void setBreathControllerTarget(uint8_t target, uint8_t nTG); - void setAftertouchRange(uint8_t range, uint8_t nTG); - void setAftertouchTarget(uint8_t target, uint8_t nTG); - void loadVoiceParameters(const uint8_t* data, uint8_t nTG); - void setVoiceDataElement(uint8_t data, uint8_t number, uint8_t nTG); - void getSysExVoiceDump(uint8_t* dest, uint8_t nTG); - - int16_t checkSystemExclusive(const uint8_t* pMessage, const uint16_t nLength, uint8_t nTG); - - std::string GetPerformanceFileName(unsigned nID); - std::string GetPerformanceName(unsigned nID); - unsigned GetLastPerformance(); - unsigned GetActualPerformanceID(); - void SetActualPerformanceID(unsigned nID); - bool SetNewPerformance(unsigned nID); - bool SavePerformanceNewFile (); - unsigned GetMenuSelectedPerformanceID(); - void SetMenuSelectedPerformanceID(unsigned nID); - - bool DoSavePerformanceNewFile (void); - bool DoSetNewPerformance (void); - enum TParameter { ParameterCompressorEnable, @@ -144,11 +109,6 @@ public: TGParameterResonance, TGParameterMIDIChannel, TGParameterReverbSend, - TGParameterPitchBendRange, - TGParameterPitchBendStep, - TGParameterPortamentoMode, - TGParameterPortamentoGlissando, - TGParameterPortamentoTime, TGParameterUnknown }; @@ -163,14 +123,10 @@ public: std::string GetVoiceName (unsigned nTG); bool SavePerformance (void); - bool DoSavePerformance (void); - - void setMasterVolume (float32_t vol); private: int16_t ApplyNoteLimits (int16_t pitch, unsigned nTG); // returns < 0 to ignore note - uint8_t m_uchOPMask[CConfig::ToneGenerators]; - void LoadPerformanceParameters(void); + void ProcessSound (void); #ifdef ARM_ALLOW_MULTI_CORE @@ -199,28 +155,12 @@ private: int m_nCutoff[CConfig::ToneGenerators]; int m_nResonance[CConfig::ToneGenerators]; unsigned m_nMIDIChannel[CConfig::ToneGenerators]; - unsigned m_nPitchBendRange[CConfig::ToneGenerators]; - unsigned m_nPitchBendStep[CConfig::ToneGenerators]; - unsigned m_nPortamentoMode[CConfig::ToneGenerators]; - unsigned m_nPortamentoGlissando[CConfig::ToneGenerators]; - unsigned m_nPortamentoTime[CConfig::ToneGenerators]; unsigned m_nNoteLimitLow[CConfig::ToneGenerators]; unsigned m_nNoteLimitHigh[CConfig::ToneGenerators]; int m_nNoteShift[CConfig::ToneGenerators]; unsigned m_nReverbSend[CConfig::ToneGenerators]; - - uint8_t m_nRawVoiceData[156]; - - - bool m_bSavePerformanceNewFile; - bool m_bSetNewPerformance; - unsigned m_nSetNewPerformanceID; - - float32_t nMasterVolume; - - CUserInterface m_UI; CSysExFileLoader m_SysExFileLoader; @@ -250,8 +190,6 @@ private: AudioStereoMixer* reverb_send_mixer; CSpinLock m_ReverbSpinLock; - - bool m_bSavePerformance; }; #endif diff --git a/src/screens.cpp b/src/screens.cpp new file mode 100644 index 0000000..1ad838c --- /dev/null +++ b/src/screens.cpp @@ -0,0 +1,64 @@ +#include "screens.h" + +CPerformanceScreen::CPerformanceScreen() : + CScreen(PerformanceScreen, "Performance", PerformanceScreenPageCount) +{ +} + +CPerformanceScreen::~CPerformanceScreen() +{ +} + +CPerformanceEditScreen::CPerformanceEditScreen() : + CScreen(PerformanceEditScreen, "Perf. edit", PerformanceEditScreenPageCount) +{ +} + +CPerformanceEditScreen::~CPerformanceEditScreen() +{ +} + +CVoiceScreen::CVoiceScreen() : + CScreen(VoiceScreen, "Voice", VoiceScreenPageCount) +{ +} + +CVoiceScreen::~CVoiceScreen() +{ +} + +CVoiceEditScreen::CVoiceEditScreen() : + CScreen(VoiceEditScreen, "Voice edit", VoiceEditScreenPageCount) +{ +} + +CVoiceEditScreen::~CVoiceEditScreen() +{ +} + +COperatorScreen::COperatorScreen() : + CScreen(OperatorScreen, "Op. edit", OperatorScreenPageCount) +{ +} + +COperatorScreen::~COperatorScreen() +{ +} + +CFxScreen::CFxScreen() : + CScreen(FxScreen, "FX", FxScreenPageCount) +{ +} + +CFxScreen::~CFxScreen() +{ +} + +CNameEditScreen::CNameEditScreen(const char* pszScreenName) : + CScreen(NameEditScreen, pszScreenName, NameEditScreenPageCount) +{ +} + +CNameEditScreen::~CNameEditScreen() +{ +} diff --git a/src/screens.h b/src/screens.h new file mode 100644 index 0000000..74cdd20 --- /dev/null +++ b/src/screens.h @@ -0,0 +1,97 @@ +// +// minidexed.h +// +// MiniDexed - Dexed FM synthesizer for bare metal Raspberry Pi +// Copyright (C) 2022 The MiniDexed Team +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#ifndef _screens_h +#define _screens_h + +#include +#include + +enum ScreenID +{ + PerformanceScreen = 0, + PerformanceEditScreen, + VoiceScreen, + VoiceEditScreen, + OperatorScreen, + FxScreen, + NameEditScreen +}; + +enum ScreenPageCount +{ + PerformanceScreenPageCount = 1, + PerformanceEditScreenPageCount = 3, + VoiceScreenPageCount = 1, + VoiceEditScreenPageCount = 3, + OperatorScreenPageCount = 1, + FxScreenPageCount = 1, + NameEditScreen = 1 +}; + +class CPerformanceScreen : public CScreen +{ +public: + CPerformanceScreen(); + virtual ~CPerformanceScreen(); +}; + +class CPerformanceEditScreen : public CScreen +{ +public: + CPerformanceEditScreen(); + virtual ~CPerformanceEditScreen(); +}; + +class CVoiceScreen : public CScreen +{ +public: + CVoiceScreen(); + virtual ~CVoiceScreen(); +}; + +class CVoiceEditScreen : public CScreen +{ +public: + CVoiceEditScreen(); + virtual ~CVoiceEditScreen(); +}; + +class COperatorScreen : public CScreen +{ +public: + COperatorScreen(); + virtual ~COperatorScreen(); +}; + +class CFxScreen : public CScreen +{ +public: + CFxScreen(); + ~CFxScreen(); +}; + +class CNameEditScreen : public CScreen +{ +public: + CNameEditScreen(); + ~CNameEditScreen(); +}; + +#endif \ No newline at end of file diff --git a/src/sysexfileloader.h b/src/sysexfileloader.h index bf7c918..658f2b0 100644 --- a/src/sysexfileloader.h +++ b/src/sysexfileloader.h @@ -29,7 +29,7 @@ class CSysExFileLoader // Loader for DX7 .syx files { public: - static const unsigned MaxVoiceBankID = 127; // TODO? 16383 + static const unsigned MaxVoiceBankID = 1 << 14; // TODO? 16383 static const unsigned VoicesPerBank = 32; static const size_t SizePackedVoice = 128; static const size_t SizeSingleVoice = 156; diff --git a/src/ui.cpp b/src/ui.cpp new file mode 100644 index 0000000..f08e9b8 --- /dev/null +++ b/src/ui.cpp @@ -0,0 +1,614 @@ +#include "ui.h" + +#include + +LOGMODULE ("ui"); + +/* CPaint */ +CPaint::CPaint(uint8_t sdi, uint8_t sda, uint8_t reset) : m_display(U8G2_R0, reset, sdi, sda) +{ +} + +CPaint::~CPaint() +{ + this->m_display.clearDisplay(); +} + +void CPaint::Initialize() +{ + this->m_display.initDisplay(); +} + +uint32_t CPaint::GetBusClock() +{ + return this->m_display.getBusClock(); +} + +void CPaint::SetBusClock(uint32_t clock_speed) +{ + this->m_display.setBusClock(clock_speed); +} + +void CPaint::SetI2CAddress(uint8_t adr) +{ + this->m_display.setI2CAddress(adr); +} + +void CPaint::EnableUTF8Print() +{ + this->m_display.enableUTF8Print(); +} + +void CPaint::DisableUTF8Print() +{ + this->m_display.disableUTF8Print(); +} + +unsigned CPaint::Width() +{ + return this->m_display.getDisplayWidth(); +} + +unsigned CPaint::Height() +{ + return this->m_display.getDisplayHeight(); +} + +void CPaint::Clear() +{ + this->m_display.clearDisplay(); +} + +void CPaint::SetPowerSave(uint8_t is_enable) +{ + this->m_display.setPowerSave(is_enable); +} + +void CPaint::SetFlipMode(uint8_t mode) +{ + this->m_display.setFlipMode(mode); +} + +void CPaint::SetContrast(uint8_t value) +{ + this->m_display.setContrast(value); +} + +bool CPaint::Begin() +{ + this->m_display.begin(); +} + +void CPaint::BeginSimple() +{ + this->m_display.beginSimple(); +} + +void CPaint::SetMaxClipWindow() +{ + this->m_display.setMaxClipWindow(); +} + +void CPaint::SetClipWindow(uint8_t clip_x0, uint8_t clip_y0, uint8_t clip_x1, uint8_t clip_y1) +{ + this->m_display.setClipWindow(clip_x0, clip_y0, clip_x1, clip_y1); +} + +void CPaint::SendBuffer() +{ + this->m_display.sendBuffer(); +} +void CPaint::ClearBuffer() +{ + this->m_display.clearBuffer(); +} + +void CPaint::FirstPage() +{ + this->m_display.firstPage(); +} +uint8_t CPaint::NextPage() +{ + this->m_display.nextPage(); +} + +uint8_t* CPaint::GetBufferPtr() +{ + return this->m_display.getBufferPtr(); +} + +uint8_t CPaint::GetBufferTileHeight() +{ + return this->m_display.getBufferTileHeight(); +} + +uint8_t CPaint::GetBufferTileWidth() +{ + return this->m_display.getBufferTileWidth(); +} + +uint8_t CPaint::GetPageCurrTileRow() +{ + return this->m_display.getPageCurrTileRow(); +} + +void CPaint::SetPageCurrTileRow(uint8_t row) +{ + this->m_display.setPageCurrTileRow(row); +} + +uint8_t CPaint::GetBufferCurrTileRow() +{ + return this->m_display.getBufferCurrTileRow(); +} + +void CPaint::SetBufferCurrTileRow(uint8_t row) +{ + this->m_display.setBufferCurrTileRow(row); +} + +void CPaint::SetBufferAutoClear(uint8_t mode) +{ + this->m_display.setAutoPageClear(mode); +} + +void CPaint::UpdateDisplayArea(uint8_t tx, uint8_t ty, uint8_t tw, uint8_t th) +{ + this->m_display.updateDisplayArea(tx, ty, tw, th); +} + +void CPaint::UpdateDisplay() +{ + this->m_display.updateDisplay(); +} + +void CPaint::RefreshDisplay() +{ + this->m_display.refreshDisplay(); +} + +void CPaint::SetDrawColor(uint8_t color_index) +{ + this->m_display.setDrawColor(color_index); +} + +uint8_t CPaint::GetDrawColor() +{ + this->m_display.getDrawColor(); +} + +void CPaint::DrawPixel(uint8_t x, uint8_t y) +{ + this->m_display.drawPixel(x, y); +} + +void CPaint::DrawHLine(uint8_t x, uint8_t y, uint8_t w) +{ + this->m_display.drawHLine(x, y, w); +} + +void CPaint::DrawVLine(uint8_t x, uint8_t y, uint8_t h) +{ + this->m_display.drawVLine(x, y, h); +} + +void CPaint::DrawHVLine(uint8_t x, uint8_t y, uint8_t len, uint8_t dir) +{ + this->m_display.drawHVLine(x, y, len, dir); +} + +void CPaint::DrawFrame(uint8_t x, uint8_t y, uint8_t w, uint8_t h) +{ + this->m_display.drawFrame(x, y, w, h); +} + +void CPaint::DrawRFrame(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t r) +{ + this->m_display.drawRFrame(x, y, w, h, r); +} + +void CPaint::DrawBox(uint8_t x, uint8_t y, uint8_t w, uint8_t h) +{ + this->m_display.drawBox(x, y, w, h); +} + +void CPaint::DrawRBox(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t r) +{ + this->m_display.drawRBox(x, y, w, h, r); +} + +void CPaint::DrawButtonUTF8(uint8_t x, uint8_t y, uint8_t flags, uint8_t width, uint8_t padding_h, uint8_t padding_v, const char* text) +{ + this->m_display.drawButtonUTF8(x, y, flags, width, padding_h, padding_v, text); +} + +void CPaint::DrawCircle(uint8_t x0, uint8_t y0, uint8_t rad, uint8_t opt) +{ + this->m_display.drawCircle(x0, y0, rad, opt); +} + +void CPaint::DrawDisc(uint8_t x0, uint8_t y0, uint8_t rad, uint8_t opt) +{ + this->m_display.drawDisc(x0, y0, rad, opt); +} + +void CPaint::DrawEllipse(uint8_t x0, uint8_t y0, uint8_t rx, uint8_t ry, uint8_t opt) +{ + this->m_display.drawEllipse(x0, y0, rx, ry, opt); +} + +void CPaint::DrawFilledEllipse(uint8_t x0, uint8_t y0, uint8_t rx, uint8_t ry, uint8_t opt) +{ + this->m_display.drawFilledEllipse(x0, y0, rx, ry, opt); +} + +void CPaint::DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) +{ + this->m_display.drawLine(x1, y1, x2, y2); +} + +void CPaint::SetBitmapMode(uint8_t is_transparent) +{ + this->m_display.setBitmapMode(is_transparent); +} + +void CPaint::DrawBitmap(uint8_t x, uint8_t y, uint8_t cnt, uint8_t h, const uint8_t* bitmap) +{ + this->m_display.drawBitmap(x, y, cnt, h, bitmap); +} + +void CPaint::DrawXBM(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t* bitmap) +{ + this->m_display.drawXBM(x, y, w, h, bitmap); +} + +void CPaint::DrawXBMP(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t* bitmap) +{ + this->m_display.drawXBMP(x, y, w, h, bitmap); +} + +void CPaint::DrawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2) +{ + this->m_display.drawTriangle(x0, y0, x1, y1, x2, y2); +} + +void CPaint::SetFont(const uint8_t* font) +{ + this->m_display.setFont(font); +} + +void CPaint::SetFontMode(uint8_t is_transparent) +{ + this->m_display.setFontMode(is_transparent); +} + +void CPaint::SetFontDirection(uint8_t dir) +{ + this->m_display.setFontDirection(dir); +} + +int8_t CPaint::GetAscent() +{ + return this->m_display.getAscent(); +} + +int8_t CPaint::GetDescent() +{ + return this->m_display.getDescent(); +} + +void CPaint::SetFontPosBaseline() +{ + this->m_display.setFontPosBaseline(); +} + +void CPaint::SetFontPosBottom() +{ + this->m_display.setFontPosBottom(); +} + +void CPaint::SetFontPosTop() +{ + this->m_display.setFontPosTop(); +} + +void CPaint::SetFontPosCenter() +{ + this->m_display.setFontPosCenter(); +} + +void CPaint::SetFontRefHeightText() +{ + this->m_display.setFontRefHeightText(); +} + +void CPaint::SetFontRefHeightExtendedText() +{ + this->m_display.setFontRefHeightExtendedText(); +} + +void CPaint::SetFontRefHeightAll() +{ + this->m_display.setFontRefHeightAll(); +} + +uint8_t CPaint::DrawGlyph(uint8_t x, uint8_t y, uint16_t encoding) +{ + this->m_display.drawGlyph(x, y, encoding); +} + +uint8_t CPaint::DrawStr(uint8_t x, uint8_t y, const char* s) +{ + this->m_display.drawStr(x, y, s); +} + +uint8_t CPaint::DrawUTF8(uint8_t x, uint8_t y, const char* s) +{ + this->m_display.drawUTF8(x, y, s); +} + +uint8_t CPaint::DrawExtUTF8(uint8_t x, uint8_t y, uint8_t to_left, const uint16_t *kerning_table, const char* s) +{ + this->m_display.drawExtUTF8(x, y, to_left, kerning_table, s); +} + +uint8_t CPaint::GetStrWidth(const char* s) +{ + return this->m_display.getStrWidth(s); +} + +uint8_t CPaint::GetUTF8Width(const char* s) +{ + return this->m_display.getUTF8Width(s); +} + +uint8_t CPaint::UISelectionList(const char* title, uint8_t start_pos, const char* sl) +{ + this->m_display.userInterfaceSelectionList(title, start_pos, sl); +} + +uint8_t CPaint::UIMessage(const char* title1, const char* title2, const char* title3, const char* buttons) +{ + this->m_display.userInterfaceMessage(title1, title2, title3, buttons); +} + +uint8_t CPaint::UIInputValue(const char* title, const char* pre, uint8_t* value, uint8_t lo, uint8_t hi, uint8_t digits, const char* post) +{ + return this->m_display.userInterfaceInputValue(title, pre, value, lo, hi, digits, post); +} + +void CPaint::LCDHome() +{ + this->m_display.home(); +} + +void CPaint::LCDClear() +{ + this->m_display.clear(); +} + +void CPaint::LCDNoDisplay() +{ + this->m_display.noDisplay(); +} + +void CPaint::LCDDisplay() +{ + this->m_display.display(); +} + +void CPaint::LCDSetCursor(uint8_t x, uint8_t y) +{ + this->m_display.setCursor(x, y); +} + +uint8_t CPaint::LCDGetCursorX() +{ + this->m_display.getCursorX(); +} + +uint8_t CPaint::LCDGetCursorY() +{ + this->m_display.getCursorY(); +} + +void CPaint::SleepOn() +{ + this->m_display.sleepOn(); +} + +void CPaint::SleepOff() +{ + this->m_display.sleepOff(); +} + +void CPaint::SetColorIndex(uint8_t color_index) +{ + this->m_display.setColorIndex(color_index); +} + +uint8_t CPaint::GetColorIndex() +{ + this->m_display.getColorIndex(); +} + +int8_t CPaint::GetFontAscent() +{ + this->m_display.getFontAscent(); +} + +int8_t CPaint::GetFontDescent() +{ + this->m_display.getFontDescent(); +} + +int8_t CPaint::GetMaxCharHeight() +{ + this->m_display.getMaxCharHeight(); +} + +int8_t CPaint::GetMaxCharWidth() +{ + this->m_display.getMaxCharWidth(); +} + +/* CControl */ +CControl::CControl(CMiniDexed *pMiniDexed, CGPIOManager *pGPIOManager, CConfig *pConfig) : + m_pMiniDexed(pMiniDexed), + m_pGPIOManager(pGPIOManager), + m_pConfig(pConfig), + m_ppRotaryEncoders(nullptr) +{ +} + +CControl::~CControl() +{ + if(this->m_ppRotaryEncoders) + { + for(int i = 0; i < NUM_CONTROLS; i++) + { + delete this->m_ppRotaryEncoders[i]; + } + + delete []this->m_ppRotaryEncoders; + } +} + +bool CControl::Initialize() +{ + assert(this->m_pConfig); + + if(this->m_pConfig->GetEncoderEnabled()) + { + this->m_ppRotaryEncoders = new CKY040*[4]; + for(int i = 0; i < NUM_CONTROLS; i++) { + this->m_ppRotaryEncoders[i] = new CKY040( + this->m_pConfig->GetEncoderPinClock(), + this->m_pConfig->GetEncoderPinData(), + this->m_pConfig->GetEncoderPinSwitch(), + this->m_pGPIOManager + ); + } + } + + return true; +} + +CKY040& CControl::operator[](size_t index) +{ + return *this->m_ppRotaryEncoders[index % NUM_CONTROLS]; +} + +/* CScreen */ +CScreen::CScreen(unsigned id, const char* name, unsigned nPages) : + m_id(id), + m_name(name), + m_nPages(nPages), + m_currentScrollPage(0), + m_isDirty(false) +{ +} + +CScreen::~CScreen() +{ +} + +void CScreen::Activate(CScreen& nxtScreen) +{ + nxtScreen.SetDirty(true); +} + +void CScreen::Activate() +{ + CScreen::Activate(*this); +} + +unsigned CScreen::ScrollLeftPage() +{ + unsigned nxPage = (this->m_currentScrollPage + 1) % this->m_nPages; + this->Dirty(this->m_currentScrollPage != nxPage); + this->m_currentScrollPage = nxPage; + + return this->m_currentScrollPage; +} + +unsigned CScreen::ScrollRightPage() +{ + unsigned nxPage = (this->m_currentScrollPage + this->m_nPages - 1) % this->m_nPages; + this->Dirty(this->m_currentScrollPage != nxPage); + this->m_currentScrollPage = nxPage; + + return this->m_currentScrollPage; +} + +unsigned CScreen::CurrentScrollPage() +{ + return this->m_currentScrollPage; +} + +unsigned CScreen::ScrollToPage(unsigned pageNum) +{ + unsigned nxPage = pageNum % this->m_nPages; + this->Dirty(this->m_currentScrollPage != nxPage); + this->m_currentScrollPage = nxPage; + + return this->m_currentScrollPage; +} + +void CScreen::SetDirty(bool isDirty) +{ + this->m_isDirty = isDirty; +} + +void CScreen::Dirty(bool isDirty) +{ + this->m_isDirty |= isDirty; +} + +bool CScreen::IsDirty() +{ + return this->m_isDirty; +} + +void CScreen::Display(CPaint& paint) +{ + if(this->IsDirty()) + { + this->Paint(paint); + } +} + + +CScreenManager& CScreenManager::GetInstance() +{ + static CScreenManager inst; + + return inst; +} + +CScreenManager::CScreenManager() : + m_screenMap() +{ +} + +CScreenManager::~CScreenManager() +{ +} + +void CScreenManager::Register(CScreen* pScreen) +{ + this->m_screenMap[pScreen->m_id] = pScreen; +} + +CScreen& CScreenManager::operator[](unsigned index) +{ + return *(this->m_screenMap[index]); +} + +CScreen& CScreenManager::Activate(unsigned screenId) +{ + CScreen& nxtScreen = (*this)[screenId]; + CScreen::Activate(nxtScreen); + + return nxtScreen; +} diff --git a/src/ui.h b/src/ui.h new file mode 100644 index 0000000..bf3cd3b --- /dev/null +++ b/src/ui.h @@ -0,0 +1,242 @@ +// +// minidexed.h +// +// MiniDexed - Dexed FM synthesizer for bare metal Raspberry Pi +// Copyright (C) 2022 The MiniDexed Team +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#ifndef _ui_h +#define _ui_h + +#define U8X8_USE_PINS 1 + +#include + +#include "minidexed.h" +#include "config.h" +#include + +#include +#include + +class CPaint +{ +public: + CPaint(uint8_t sdi, uint8_t sda, uint8_t reset); + ~CPaint(); + + void Initialize(); + + uint32_t GetBusClock(); + void SetBusClock(uint32_t clock_speed); + + void SetI2CAddress(uint8_t adr); + + void EnableUTF8Print(); + void DisableUTF8Print(); + + unsigned Width(); + unsigned Height(); + + void Clear(); + + void SetPowerSave(uint8_t is_enable); + + void SetFlipMode(uint8_t mode); + + void SetContrast(uint8_t value); + + bool Begin(); + void BeginSimple(); + + void SetMaxClipWindow(); + void SetClipWindow(uint8_t clip_x0, uint8_t clip_y0, uint8_t clip_x1, uint8_t clip_y1); + + void SendBuffer(); + void ClearBuffer(); + + void FirstPage(); + uint8_t NextPage(); + + uint8_t* GetBufferPtr(); + uint8_t GetBufferTileHeight(); + uint8_t GetBufferTileWidth(); + uint8_t GetPageCurrTileRow(); + void SetPageCurrTileRow(uint8_t row); + uint8_t GetBufferCurrTileRow(); + void SetBufferCurrTileRow(uint8_t row); + + void SetBufferAutoClear(uint8_t mode); + + void UpdateDisplayArea(uint8_t tx, uint8_t ty, uint8_t tw, uint8_t th); + + void UpdateDisplay(); + + void RefreshDisplay(); + + void SetDrawColor(uint8_t color_index); + uint8_t GetDrawColor(); + void DrawPixel(uint8_t x, uint8_t y); + void DrawHLine(uint8_t x, uint8_t y, uint8_t w); + void DrawVLine(uint8_t x, uint8_t y, uint8_t h); + void DrawHVLine(uint8_t x, uint8_t y, uint8_t len, uint8_t dir); + + void DrawFrame(uint8_t x, uint8_t y, uint8_t w, uint8_t h); + void DrawRFrame(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t r); + void DrawBox(uint8_t x, uint8_t y, uint8_t w, uint8_t h); + void DrawRBox(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t r); + + void DrawButtonUTF8(uint8_t x, uint8_t y, uint8_t flags, uint8_t width, uint8_t padding_h, uint8_t padding_v, const char* text); + + void DrawCircle(uint8_t x0, uint8_t y0, uint8_t rad, uint8_t opt = U8G2_DRAW_ALL); + void DrawDisc(uint8_t x0, uint8_t y0, uint8_t rad, uint8_t opt = U8G2_DRAW_ALL); + void DrawEllipse(uint8_t x0, uint8_t y0, uint8_t rx, uint8_t ry, uint8_t opt = U8G2_DRAW_ALL); + void DrawFilledEllipse(uint8_t x0, uint8_t y0, uint8_t rx, uint8_t ry, uint8_t opt = U8G2_DRAW_ALL); + + void DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2); + + void SetBitmapMode(uint8_t is_transparent); + void DrawBitmap(uint8_t x, uint8_t y, uint8_t cnt, uint8_t h, const uint8_t* bitmap); + void DrawXBM(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t* bitmap); + void DrawXBMP(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t* bitmap); + + void DrawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2); + + void SetFont(const uint8_t* font); + void SetFontMode(uint8_t is_transparent); + void SetFontDirection(uint8_t dir); + + int8_t GetAscent(); + int8_t GetDescent(); + + void SetFontPosBaseline(); + void SetFontPosBottom(); + void SetFontPosTop(); + void SetFontPosCenter(); + + void SetFontRefHeightText(); + void SetFontRefHeightExtendedText(); + void SetFontRefHeightAll(); + + uint8_t DrawGlyph(uint8_t x, uint8_t y, uint16_t encoding); + uint8_t DrawStr(uint8_t x, uint8_t y, const char* s); + uint8_t DrawUTF8(uint8_t x, uint8_t y, const char* s); + uint8_t DrawExtUTF8(uint8_t x, uint8_t y, uint8_t to_left, const uint16_t *kerning_table, const char* s); + + uint8_t GetStrWidth(const char* s); + uint8_t GetUTF8Width(const char* s); + + uint8_t UISelectionList(const char* title, uint8_t start_pos, const char* sl); + uint8_t UIMessage(const char* title1, const char* title2, const char* title3, const char* buttons); + uint8_t UIInputValue(const char* title, const char* pre, uint8_t* value, uint8_t lo, uint8_t hi, uint8_t digits, const char* post); + + void LCDHome(); + void LCDClear(); + void LCDNoDisplay(); + void LCDDisplay(); + void LCDSetCursor(uint8_t x, uint8_t y); + uint8_t LCDGetCursorX(); + uint8_t LCDGetCursorY(); + + void SleepOn(); + void SleepOff(); + void SetColorIndex(uint8_t color_index); + uint8_t GetColorIndex(); + int8_t GetFontAscent(); + int8_t GetFontDescent(); + int8_t GetMaxCharHeight(); + int8_t GetMaxCharWidth(); + +private: + U8G2_SH1122_256X64_F_HW_I2C m_display; +}; + +#define NUM_CONTROLS 4 + +class CControl +{ +public: + CControl(CMiniDexed *pMiniDexed, CGPIOManager *pGPIOManager, CConfig *pConfig); + ~CControl(); + + bool Initialize(); + + CKY040& operator[](size_t index); + +private: + CMiniDexed* m_pMiniDexed; + CGPIOManager* m_pGPIOManager; + CConfig* m_pConfig; + CKY040** m_ppRotaryEncoders; +}; + +class CScreenManager; + +class CScreen +{ + friend class CScreenManager; + +public: + CScreen(unsigned id, const char* name, unsigned nPages = 1); + virtual ~CScreen(); + + static void Activate(CScreen& nxtScreen); + void Activate(); + + unsigned ScrollLeftPage(); + unsigned ScrollRightPage(); + unsigned CurrentScrollPage(); + unsigned ScrollToPage(unsigned pageNum); + + void SetDirty(bool isDirty); + void Dirty(bool isDirty); + bool IsDirty(); + + void Display(CPaint& paint); + +protected: + virtual void Paint(CPaint& paint) = 0; + +private: + const unsigned m_id; + const char* m_name; + const unsigned m_nPages; + unsigned m_currentScrollPage; + bool m_isDirty; +}; + +class CScreenManager +{ +private: + std::map m_screenMap; + + CScreenManager(); + +public: + static CScreenManager& GetInstance(); + + CScreenManager(CScreenManager const&) = delete; + void operator=(CScreenManager const&) = delete; + + ~CScreenManager(); + + void Register(CScreen* pScreen); + + CScreen& operator[](unsigned index); + + CScreen& Activate(unsigned screenId); +}; + +#endif diff --git a/src/userinterface.cpp b/src/userinterface.cpp index c7c746f..ff1a97a 100644 --- a/src/userinterface.cpp +++ b/src/userinterface.cpp @@ -27,10 +27,9 @@ LOGMODULE ("ui"); -CUserInterface::CUserInterface (CMiniDexed *pMiniDexed, CGPIOManager *pGPIOManager, CI2CMaster *pI2CMaster, CConfig *pConfig) +CUserInterface::CUserInterface (CMiniDexed *pMiniDexed, CGPIOManager *pGPIOManager, CConfig *pConfig) : m_pMiniDexed (pMiniDexed), m_pGPIOManager (pGPIOManager), - m_pI2CMaster (pI2CMaster), m_pConfig (pConfig), m_pLCD (0), m_pLCDBuffered (0), @@ -53,23 +52,14 @@ bool CUserInterface::Initialize (void) if (m_pConfig->GetLCDEnabled ()) { - unsigned i2caddr = m_pConfig->GetLCDI2CAddress (); - if (i2caddr == 0) - { - m_pLCD = new CHD44780Device (CConfig::LCDColumns, CConfig::LCDRows, - m_pConfig->GetLCDPinData4 (), - m_pConfig->GetLCDPinData5 (), - m_pConfig->GetLCDPinData6 (), - m_pConfig->GetLCDPinData7 (), - m_pConfig->GetLCDPinEnable (), - m_pConfig->GetLCDPinRegisterSelect (), - m_pConfig->GetLCDPinReadWrite ()); - } - else - { - m_pLCD = new CHD44780Device (m_pI2CMaster, i2caddr, - CConfig::LCDColumns, CConfig::LCDRows); - } + m_pLCD = new CHD44780Device (CConfig::LCDColumns, CConfig::LCDRows, + m_pConfig->GetLCDPinData4 (), + m_pConfig->GetLCDPinData5 (), + m_pConfig->GetLCDPinData6 (), + m_pConfig->GetLCDPinData7 (), + m_pConfig->GetLCDPinEnable (), + m_pConfig->GetLCDPinRegisterSelect (), + m_pConfig->GetLCDPinReadWrite ()); assert (m_pLCD); if (!m_pLCD->Initialize ()) @@ -176,6 +166,12 @@ void CUserInterface::DisplayWrite (const char *pMenu, const char *pParam, const LCDWrite (Msg); } +void CUserInterface::ImmediateLCDWrite (const char *pString) +{ + this->LCDWrite(pString); + this->Process(); +} + void CUserInterface::LCDWrite (const char *pString) { if (m_pLCDBuffered) @@ -219,7 +215,7 @@ void CUserInterface::EncoderEventHandler (CKY040::TEvent Event) break; case CKY040::EventSwitchHold: - if (m_pRotaryEncoder->GetHoldSeconds () >= 120) + if (m_pRotaryEncoder->GetHoldSeconds () >= 10) { delete m_pLCD; // reset LCD diff --git a/src/userinterface.h b/src/userinterface.h index 726abbd..404bbfd 100644 --- a/src/userinterface.h +++ b/src/userinterface.h @@ -26,14 +26,13 @@ #include #include #include -#include class CMiniDexed; class CUserInterface { public: - CUserInterface (CMiniDexed *pMiniDexed, CGPIOManager *pGPIOManager, CI2CMaster *pI2CMaster, CConfig *pConfig); + CUserInterface (CMiniDexed *pMiniDexed, CGPIOManager *pGPIOManager, CConfig *pConfig); ~CUserInterface (void); bool Initialize (void); @@ -49,17 +48,17 @@ public: // +----------------+ void DisplayWrite (const char *pMenu, const char *pParam, const char *pValue, bool bArrowDown, bool bArrowUp); + + void ImmediateLCDWrite (const char *pString); private: void LCDWrite (const char *pString); // Print to optional HD44780 display - void EncoderEventHandler (CKY040::TEvent Event); static void EncoderEventStub (CKY040::TEvent Event, void *pParam); private: CMiniDexed *m_pMiniDexed; CGPIOManager *m_pGPIOManager; - CI2CMaster *m_pI2CMaster; CConfig *m_pConfig; CHD44780Device *m_pLCD; diff --git a/src/userinterfaceext.cpp b/src/userinterfaceext.cpp new file mode 100644 index 0000000..7fed40f --- /dev/null +++ b/src/userinterfaceext.cpp @@ -0,0 +1,237 @@ +// +// userinterface.cpp +// +// MiniDexed - Dexed FM synthesizer for bare metal Raspberry Pi +// Copyright (C) 2022 The MiniDexed Team +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#include "userinterfaceext.h" +#include "minidexed.h" +#include +#include +#include +#include +#include + +LOGMODULE ("uiext"); + +CUserInterfaceExt::CUserInterfaceExt (CMiniDexed *pMiniDexed, CGPIOManager *pGPIOManager, CConfig *pConfig) +: m_pMiniDexed (pMiniDexed), + m_pGPIOManager (pGPIOManager), + m_pConfig (pConfig), + m_pLCD (0), + m_pLCDBuffered (0), + m_pRotaryEncoder (0), + m_bSwitchPressed (false), + m_Menu (this, pMiniDexed) +{ +} + +CUserInterfaceExt::~CUserInterfaceExt (void) +{ + delete m_pRotaryEncoder; + delete m_pLCDBuffered; + delete m_pLCD; +} + +bool CUserInterfaceExt::Initialize (void) +{ + assert (m_pConfig); + + if (m_pConfig->GetLCDEnabled ()) + { + m_pLCD = new CHD44780Device (CConfig::LCDColumns, CConfig::LCDRows, + m_pConfig->GetLCDPinData4 (), + m_pConfig->GetLCDPinData5 (), + m_pConfig->GetLCDPinData6 (), + m_pConfig->GetLCDPinData7 (), + m_pConfig->GetLCDPinEnable (), + m_pConfig->GetLCDPinRegisterSelect (), + m_pConfig->GetLCDPinReadWrite ()); + assert (m_pLCD); + + if (!m_pLCD->Initialize ()) + { + return false; + } + + m_pLCDBuffered = new CWriteBufferDevice (m_pLCD); + assert (m_pLCDBuffered); + + LCDWrite ("\x1B[?25l\x1B""d+"); // cursor off, autopage mode + + LOGDBG ("LCD initialized"); + } + + if (m_pConfig->GetEncoderEnabled ()) + { + m_pRotaryEncoder = new CKY040 (m_pConfig->GetEncoderPinClock (), + m_pConfig->GetEncoderPinData (), + m_pConfig->GetEncoderPinSwitch (), + m_pGPIOManager); + assert (m_pRotaryEncoder); + + if (!m_pRotaryEncoder->Initialize ()) + { + return false; + } + + m_pRotaryEncoder->RegisterEventHandler (EncoderEventStub, this); + + LOGDBG ("Rotary encoder initialized"); + } + + m_Menu.EventHandler (CUIMenu::MenuEventUpdate); + + return true; +} + +void CUserInterfaceExt::Process (void) +{ + if (m_pLCDBuffered) + { + m_pLCDBuffered->Update (); + } +} + +void CUserInterfaceExt::ParameterChanged (void) +{ + m_Menu.EventHandler (CUIMenu::MenuEventUpdate); +} + +void CUserInterfaceExt::DisplayWrite (const char *pMenu, const char *pParam, const char *pValue, + bool bArrowDown, bool bArrowUp) +{ + assert (pMenu); + assert (pParam); + assert (pValue); + + CString Msg ("\x1B[H"); // cursor home + + // first line + Msg.Append (pParam); + + size_t nLen = strlen (pParam) + strlen (pMenu); + if (nLen < CConfig::LCDColumns) + { + for (unsigned i = CConfig::LCDColumns-nLen; i > 0; i--) + { + Msg.Append (" "); + } + } + + Msg.Append (pMenu); + + // second line + CString Value (" "); + if (bArrowDown) + { + Value = "\x7F"; // arrow left character + } + + Value.Append (pValue); + + if (bArrowUp) + { + if (Value.GetLength () < CConfig::LCDColumns-1) + { + for (unsigned i = CConfig::LCDColumns-Value.GetLength ()-1; i > 0; i--) + { + Value.Append (" "); + } + } + + Value.Append ("\x7E"); // arrow right character + } + + Msg.Append (Value); + + if (Value.GetLength () < CConfig::LCDColumns) + { + Msg.Append ("\x1B[K"); // clear end of line + } + + LCDWrite (Msg); +} + +void CUserInterfaceExt::ImmediateLCDWrite (const char *pString) +{ + this->LCDWrite(pString); + this->Process(); +} + +void CUserInterfaceExt::LCDWrite (const char *pString) +{ + if (m_pLCDBuffered) + { + m_pLCDBuffered->Write (pString, strlen (pString)); + } +} + +void CUserInterfaceExt::EncoderEventHandler (CKY040::TEvent Event) +{ + switch (Event) + { + case CKY040::EventSwitchDown: + m_bSwitchPressed = true; + break; + + case CKY040::EventSwitchUp: + m_bSwitchPressed = false; + break; + + case CKY040::EventClockwise: + m_Menu.EventHandler (m_bSwitchPressed ? CUIMenu::MenuEventPressAndStepUp + : CUIMenu::MenuEventStepUp); + break; + + case CKY040::EventCounterclockwise: + m_Menu.EventHandler (m_bSwitchPressed ? CUIMenu::MenuEventPressAndStepDown + : CUIMenu::MenuEventStepDown); + break; + + case CKY040::EventSwitchClick: + m_Menu.EventHandler (CUIMenu::MenuEventBack); + break; + + case CKY040::EventSwitchDoubleClick: + m_Menu.EventHandler (CUIMenu::MenuEventSelect); + break; + + case CKY040::EventSwitchTripleClick: + m_Menu.EventHandler (CUIMenu::MenuEventHome); + break; + + case CKY040::EventSwitchHold: + if (m_pRotaryEncoder->GetHoldSeconds () >= 10) + { + delete m_pLCD; // reset LCD + + reboot (); + } + break; + + default: + break; + } +} + +void CUserInterfaceExt::EncoderEventStub (CKY040::TEvent Event, void *pParam) +{ + CUserInterfaceExt *pThis = static_cast (pParam); + assert (pThis != 0); + + pThis->EncoderEventHandler (Event); +} diff --git a/src/userinterfaceext.h b/src/userinterfaceext.h new file mode 100644 index 0000000..132f13c --- /dev/null +++ b/src/userinterfaceext.h @@ -0,0 +1,73 @@ +// +// userinterface.h +// +// MiniDexed - Dexed FM synthesizer for bare metal Raspberry Pi +// Copyright (C) 2022 The MiniDexed Team +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +#ifndef _userinterface_h +#define _userinterface_h + +#include "config.h" +#include "uimenu.h" +#include +#include +#include +#include + +class CMiniDexed; + +class CUserInterfaceExt +{ +public: + CUserInterfaceExt (CMiniDexed *pMiniDexed, CGPIOManager *pGPIOManager, CConfig *pConfig); + ~CUserInterfaceExt (void); + + bool Initialize (void); + + void Process (void); + + void ParameterChanged (void); + + // Write to display in this format: + // +----------------+ + // |PARAM MENU| + // |[<]VALUE [>]| + // +----------------+ + void DisplayWrite (const char *pMenu, const char *pParam, const char *pValue, + bool bArrowDown, bool bArrowUp); + + void ImmediateLCDWrite (const char *pString); + +private: + void LCDWrite (const char *pString); // Print to optional HD44780 display + void EncoderEventHandler (CKY040::TEvent Event); + static void EncoderEventStub (CKY040::TEvent Event, void *pParam); + +private: + CMiniDexed *m_pMiniDexed; + CGPIOManager *m_pGPIOManager; + CConfig *m_pConfig; + + CHD44780Device *m_pLCD; + CWriteBufferDevice *m_pLCDBuffered; + + CKY040 *m_pRotaryEncoder; + bool m_bSwitchPressed; + + CUIMenu m_Menu; +}; + +#endif diff --git a/u8g2 b/u8g2 new file mode 160000 index 0000000..1ccf4cb --- /dev/null +++ b/u8g2 @@ -0,0 +1 @@ +Subproject commit 1ccf4cb051c9fe84d455e3cdcf18267c4f90388f