├── .clang-format ├── .gitignore ├── .gitmodules ├── LICENSE ├── Makefile ├── README.org ├── assets ├── equations.gcx ├── ex06-dag.png ├── ex07-dag.png ├── gangknob48_12_bg.png ├── moogknob48_16_bg.png └── ws-ldn-12-minigorille.jpg ├── cleanup ├── ext └── usbh_midi │ ├── usbh_MIDI.c │ └── usbh_MIDI.h ├── make ├── devices │ ├── stm32f746.ld │ └── stm32f746.make ├── modules │ ├── ex01.make │ ├── ex02.make │ ├── ex03.make │ ├── ex04.make │ ├── ex05.make │ ├── ex06.make │ ├── ex07.make │ └── ex08.make └── sources.txt └── src ├── common ├── clockconfig.c ├── clockconfig.h ├── handlers.c ├── sdram_alloc.c └── sdram_alloc.h ├── ex01 └── main.c ├── ex02 ├── main.c └── moogknob.c ├── ex03 └── main.c ├── ex04 └── main.c ├── ex05 ├── ffconf.h ├── main.c ├── usbh_conf.c └── usbh_conf.h ├── ex06 └── main.c ├── ex07 └── main.c ├── ex08 ├── main.c ├── usbh_conf.c └── usbh_conf.h ├── stm32f7xx_hal_conf.h └── synth_extras ├── midi_log.c ├── midi_log.h ├── osc_noise.c ├── osc_noise.h ├── sdram_delay.c └── sdram_delay.h /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | AllowAllParametersOfDeclarationOnNextLine: false 3 | AlignConsecutiveAssignments: true 4 | AllowShortBlocksOnASingleLine: false 5 | AllowShortFunctionsOnASingleLine: false 6 | AllowShortIfStatementsOnASingleLine: false 7 | AllowShortLoopsOnASingleLine: false 8 | BinPackParameters: false 9 | BreakBeforeBraces: Attach 10 | ColumnLimit: 80 11 | ReflowComments: false 12 | SortIncludes: true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /build 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ext/ct-head"] 2 | path = ext/ct-head 3 | url = https://github.com/thi-ng/ct-head 4 | branch = master 5 | [submodule "ext/ct-gui"] 6 | path = ext/ct-gui 7 | url = https://github.com/thi-ng/ct-gui 8 | branch = master 9 | [submodule "ext/ct-synstack"] 10 | path = ext/ct-synstack 11 | url = https://github.com/thi-ng/synstack 12 | branch = master 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ifndef STM_CUBE_HOME 2 | $(error STM_CUBE_HOME is not set) 3 | endif 4 | 5 | STM_SRC_ROOT = $(STM_CUBE_HOME)/Drivers 6 | CMSIS_DIR = $(STM_SRC_ROOT)/CMSIS 7 | LL_DIR = $(STM_SRC_ROOT)/BSP/Components 8 | USBH_DIR = $(STM_CUBE_HOME)/Middlewares/ST/STM32_USB_Host_Library 9 | FATFS_DIR = $(STM_CUBE_HOME)/Middlewares/Third_Party/FatFs/src 10 | 11 | ifndef device 12 | device = stm32f746 13 | endif 14 | 15 | ifndef module 16 | module = ex01 17 | endif 18 | 19 | USER_SRC_DIR = src 20 | EXT_SRC_DIR = ext 21 | LIB_DIR = lib 22 | BUILD_DIR = build/$(module) 23 | BIN_DIR = bin/$(module) 24 | 25 | include make/devices/$(device).make 26 | 27 | $(info building module: $(module)) 28 | include make/modules/$(module).make 29 | 30 | ifndef catalog 31 | catalog = make/sources.txt 32 | endif 33 | 34 | $(info using source catalog: $(catalog)) 35 | SRC_FILTER = $(shell grep -v '\#' $(catalog)) 36 | 37 | CC = arm-none-eabi-gcc 38 | LD = arm-none-eabi-g++ 39 | OBJCOPY = arm-none-eabi-objcopy 40 | SIZE = arm-none-eabi-size 41 | 42 | ifndef TARGET_NAME 43 | TARGET_NAME = app 44 | endif 45 | 46 | TARGET_ELF = $(BIN_DIR)/$(TARGET_NAME).elf 47 | TARGET_BIN = $(BIN_DIR)/$(TARGET_NAME).bin 48 | TARGET_SIZE = $(BIN_DIR)/$(TARGET_NAME).siz 49 | 50 | CMSIS_INCLUDES = -I$(CMSIS_DIR)/Include -I$(DEVICE_DIR)/Include 51 | CMSIS_SRC = $(filter $(SRC_FILTER), $(wildcard $(DEVICE_DIR)/Source/Templates/*.c)) 52 | 53 | HAL_INCLUDES = -I$(HAL_DIR)/Inc 54 | HAL_SRC = $(filter $(SRC_FILTER), $(wildcard $(HAL_DIR)/Src/*.c)) 55 | 56 | BSP_INCLUDES = -I$(BSP_DIR) 57 | BSP_SRC = $(filter $(SRC_FILTER), $(wildcard $(BSP_DIR)/*.c)) 58 | 59 | ifeq ($(USE_USBH),1) 60 | $(info including USBH...) 61 | USBH_INCLUDES += -I$(USBH_DIR)/Core/Inc -I$(USBH_DIR)/Class/AUDIO/Inc -I$(USBH_DIR)/Class/MSC/Inc 62 | USBH_SRC += $(filter $(SRC_FILTER), $(wildcard $(USBH_DIR)/Core/Src/*.c)) 63 | USBH_SRC += $(wildcard $(USBH_DIR)/Class/AUDIO/Src/*.c) 64 | USBH_SRC += $(wildcard $(USBH_DIR)/Class/MSC/Src/*.c) 65 | endif 66 | 67 | ifeq ($(USE_FATFS),1) 68 | $(info including FatFS...) 69 | FATFS_INCLUDES += -I$(FATFS_DIR) -I$(FATFS_DIR)/drivers 70 | FATFS_SRC += $(wildcard $(FATFS_DIR)/*.c) 71 | FATFS_SRC += $(filter $(SRC_FILTER), $(wildcard $(FATFS_DIR)/drivers/*.c)) 72 | FATFS_SRC += $(filter $(SRC_FILTER), $(wildcard $(FATFS_DIR)/option/*.c)) 73 | endif 74 | 75 | SYS_INCLUDES = $(CMSIS_INCLUDES) $(HAL_INCLUDES) $(BSP_INCLUDES) $(USBH_INCLUDES) $(FATFS_INCLUDES) 76 | SYS_SRC = $(CMSIS_SRC) $(HAL_SRC) $(BSP_SRC) $(LL_SRC) $(USBH_SRC) $(FATFS_SRC) 77 | 78 | USER_INCLUDES += -I$(USER_SRC_DIR) -Iext 79 | USER_SRC += $(wildcard $(USER_SRC_DIR)/common/*.c) $(wildcard $(USER_SRC_DIR)/$(module)/*.c) 80 | 81 | ALL_INCLUDES = $(USER_INCLUDES) $(SYS_INCLUDES) 82 | ALL_SRC = $(SYS_SRC) $(USER_SRC) 83 | 84 | ASM_OBJ = $(addprefix $(BUILD_DIR)/, $(notdir $(ASM_SRC:.s=.o))) 85 | 86 | C_OBJ += $(addprefix $(BUILD_DIR)/, $(notdir $(ALL_SRC:.c=.o))) 87 | 88 | DEPS += $(ASM_OBJ:.o=.d) $(C_OBJ:.o=.d) 89 | 90 | LIBS += -lm 91 | 92 | CFLAGS += -std=c11 -fsigned-char -ffunction-sections -fdata-sections -Wall 93 | 94 | LD_FLAGS += -Lmake/devices -L$(LIB_DIR) 95 | LD_FLAGS += -Xlinker --gc-sections -Wl,-Map,$(BIN_DIR)/$(TARGET_NAME).map 96 | LD_FLAGS += -specs=nosys.specs -specs=nano.specs 97 | 98 | # Used to enable rules below, allows building from given source list 99 | # http://stackoverflow.com/a/24967712/294515 100 | .SECONDEXPANSION: 101 | PERCENT = % 102 | 103 | all: $(BUILD_DIR) $(BIN_DIR) $(TARGET_ELF) $(TARGET_BIN) $(TARGET_SIZE) 104 | @: 105 | 106 | $(BUILD_DIR): 107 | @echo Creating $(BUILD_DIR) 108 | @mkdir -p $(BUILD_DIR) 109 | 110 | $(BIN_DIR): 111 | @echo Creating $(BIN_DIR) 112 | @mkdir -p $(BIN_DIR) 113 | 114 | $(TARGET_ELF): $(C_OBJ) $(ASM_OBJ) 115 | @echo Linking target: $(TARGET_ELF) 116 | $(CC) $(CFLAGS) $(LD_FLAGS) -o $@ $^ $(LIBS) 117 | 118 | $(TARGET_BIN): $(TARGET_ELF) 119 | @echo Creating flash image: $@ 120 | @$(OBJCOPY) -O binary $< $@ 121 | 122 | $(TARGET_SIZE): $(TARGET_ELF) 123 | @$(SIZE) --format=berkeley -x --totals $(TARGET_ELF) 124 | 125 | $(C_OBJ): %.o : $$(filter $$(PERCENT)/$$(notdir %).c, $(ALL_SRC)) 126 | @echo compiling: $(notdir $<) 127 | @$(CC) $(DEFINES) $(ALL_INCLUDES) $(CFLAGS) -o $@ -c $< -MMD -MP -MF "$(@:%.o=%.d)" 128 | 129 | $(ASM_OBJ): %.o : $$(filter $$(PERCENT)/$$(notdir %).s, $(ASM_SRC)) 130 | @echo assembling: $(notdir $<) 131 | @$(CC) $(DEFINES) $(ALL_INCLUDES) $(CFLAGS) -o $@ -c $< -MMD -MP -MF "$(@:%.o=%.d)" 132 | 133 | -include $(DEPS) 134 | 135 | .PHONY: clean trace 136 | 137 | clean: 138 | @echo Cleaning... 139 | rm -rf $(BUILD_DIR) $(BIN_DIR) 140 | 141 | trace: 142 | @echo SRC_FILTER: $(SRC_FILTER) 143 | @echo BSP: $(BSP_SRC) 144 | @echo HAL: $(HAL_SRC) 145 | @echo ALL_INCL: $(ALL_INCLUDES) 146 | @echo ALL_SRC: $(ALL_SRC) $(ASM_SRC) 147 | @echo OBJ: $(C_OBJ) $(ASM_OBJ) 148 | @echo DEPS: $(DEPS) 149 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | * thi.ng/ws-ldn-12 2 | ARM / STM32F7 DIY synth workshop (STM32F746-DISCO) 3 | 4 | [[./assets/ws-ldn-12-minigorille.jpg]] 5 | 6 | Photo by Lysandre Follet 7 | 8 | *[[https://soundcloud.com/forthcharlie/sets/stm32f4][Check out demo tracks on Soundcloud]]* 9 | 10 | ** Project setup 11 | 12 | This repo contains 8 sub-projects, all described below and each 13 | compilable as standalone application. The repo also includes various 14 | support libraries of the thi.ng collection as Git submodules, located 15 | in the [[./ext][/ext]] folder: 16 | 17 | - [[http://thi.ng/ct-gui][ct-gui]] - tiny GUI library 18 | - [[http://thi.ng/ct-head][ct-head]] - common headers, macros & utils 19 | - [[http://thi.ng/synstack][ct-synstack]] - softsynth / DSP engine 20 | 21 | #+BEGIN_SRC shell 22 | # clone with submodules 23 | git clone https://github.com/thi-ng/ws-ldn-12 --recursive 24 | #+END_SRC 25 | 26 | *** Other 3rd party dependecies 27 | 28 | - [[http://www.st.com/web/en/catalog/tools/PF261909][STM32 CubeF7 SDK]] 29 | - [[https://launchpad.net/gcc-arm-embedded][GCC ARM toolchain]] 30 | - [[https://github.com/texane/stlink][ST-Link]] 31 | - [[https://gnuarmeclipse.github.io/openocd/releases/][OpenOCD]] (optional, using dev version w/ STM32F746 support) 32 | ** Building 33 | 34 | This repo uses a flexible =Makefile= to build all included 35 | projects - *no IDE required!* The setup features: 36 | 37 | - easily customizable device config & linker scripts 38 | - no requirement to manually copy STM Cube SDK sources 39 | - catalog file(s) to selectively exclude various SDK source files (see 40 | [[./make/sources.txt][/make/sources.txt]], can be overridden per project) 41 | - config flags to include USBH & FatFs middlewares 42 | - support for multiple sub-projects (with & without shared sources) 43 | - individual module (sub-project) configs (e.g. [[./make/modules/ex08.make][/make/modules/ex08.make]]) 44 | - separate build & target folders for each module 45 | 46 | Currently only the STM32F746-DISCO board is supported, but additional 47 | board configurations can be easily added (see [[./make/devices/][/make/devices/]] for 48 | reference). 49 | 50 | *IMPORTANT:* The =Makefile= requires the env var =STM_CUBE_HOME= to be 51 | set to the root of your STM SDK directory, e.g. 52 | =~/dev/arm/STM32Cube_FW_F7_V1.4.0=. 53 | 54 | #+BEGIN_SRC shell 55 | export STM_CUBE_HOME=~/dev/arm/STM32Cube_FW_F7_V1.4.0 56 | 57 | make module=ex01 clean 58 | make module=ex01 -j4 59 | 60 | # flash device (0x800000 is ROM start address) 61 | st-flash --reset write bin/ex01/app.bin 0x8000000 62 | 63 | # combine for improved usability in terminal 64 | make module=ex01 -j4 && st-flash --reset write bin/ex01/app.bin 0x8000000 65 | #+END_SRC 66 | 67 | ** Examples 68 | *** ex01 - blinky 69 | 70 | [[./src/ex01/main.c][Source]] 71 | 72 | Simple Hello World LED blink example & demo of using EXTI interrupt to 73 | react to user button. Stops/starts blinking each time button is 74 | pressed. 75 | 76 | *** ex02 - LCD, touchscreen & GUI basics 77 | 78 | [[./src/ex02/main.c][Source]] 79 | 80 | Basic demonstration of working with BSP LCD & touchscreen modules, as 81 | well as intro to working w/ external libraries (here 82 | [[http://thi.ng/ct-gui][thi.ng/ct-gui]]). 83 | 84 | Edit the source file to [[./src/ex02/main.c#L28][uncomment different demo modes]]: 85 | 86 | - =demoWelcome()= - simple text rendering & random dots, non-interactive 87 | - =demoScribble()= - 5 point multi-touch drawing 88 | - =demoGUI()= - basic GUI usage example (dials control nothing) 89 | 90 | *** ex03 - Timers 91 | 92 | [[./src/ex03/main.c][Source]] 93 | 94 | Basic timer setup & multi-tasking example. Timer runs @ 10kHz and 95 | controls simple LED blinking task. Task can be suspended interactively 96 | by pressing user button. 97 | 98 | *** ex04 - Oscillators 99 | 100 | [[./src/ex04/main.c][Source]] 101 | 102 | Simple oscillator & frequency modulation experiment. The following 103 | oscillator types are supported for both main osc & modulator: 104 | 105 | | *ID* | *Type* | 106 | |------+-------------------------------| 107 | | 0 | Sine | 108 | | 1 | Saw | 109 | | 2 | Square | 110 | | 3 | Triangle | 111 | | 4 | Saw + Sin | 112 | | 5 | Noise (uses [[http://xoroshiro.di.unimi.it/][Xorshift128]] PRNG) | 113 | 114 | *Important:* The =mod_amp= field of the =Oscillator= struct is the 115 | modulation amplitude, but since the modulator is acting in the 116 | frequency domain, this amplitude too is in Hz. 117 | 118 | *** ex05 - USB stick WAV file streaming playback 119 | 120 | [[./src/ex05/main.c][Source]] 121 | 122 | This example uses the STM USB Host library & FatFS to access a USB 123 | memory stick connected to the board. Once USB handshake is complete, 124 | the app will then attempt to read the file =sound.wav= located in the 125 | root of the USB filesystem and start streaming to the headphone audio 126 | output (looping playback). 127 | 128 | *Important:* 129 | - The WAV file MUST be in 44.1kHz, 16bit stereo format 130 | - The example is currently configured to use the USB FS (fullspeed) 131 | port (not HS (highspeed)). This can be changed via the 132 | =ex05/usbh_conf.h= file. 133 | 134 | *** ex06 - thi.ng/synstack basics 135 | 136 | [[./src/ex06/main.c][Source]] | [[https://soundcloud.com/forthcharlie/stm32f7-synstack-ex06-ws-ldn-12][Soundcloud]] 137 | 138 | First example using [[http://thi.ng/synstack][thi.ng/synstack]] to implement polyphonic synth with 139 | fully configurable node based DSP graph (1 graph per voice). The graph 140 | implemented is shown below. 141 | 142 | We also define a musical scale to play a randomized, but always 143 | harmonic sequence and show how to dynamically modify parameters of the 144 | DSP node. 145 | 146 | *Note*: The graph doesn't show global LFOs, which are used for various 147 | modulation purposes (env mod, freq etc.). 148 | 149 | #+BEGIN_SRC dot :file assets/ex06-dag.png :exports results 150 | digraph g { 151 | rankdir=LR; 152 | node[color="black",style="filled",fontname="Inconsolata",fontcolor="white",fontsize=11]; 153 | edge[fontname="Inconsolata",fontsize=9]; 154 | 155 | env[label="AD(S)R"]; 156 | osc1[label="osc #1\n(spiral)"]; 157 | osc2[label="osc #2\n(saw-sin)"]; 158 | mul1[shape="circle",label="*"]; 159 | mul2[shape="circle",label="*"]; 160 | sum[shape="circle",label="+"]; 161 | filter[label="biquad LPF\n(randomized)"]; 162 | pan[label="stereo pan"]; 163 | delay[label="delay"]; 164 | env -> mul1; 165 | env -> mul2; 166 | osc1 -> mul1 -> sum; 167 | osc2 -> mul2 -> sum; 168 | sum -> filter -> pan -> delay; 169 | } 170 | #+END_SRC 171 | 172 | #+RESULTS: 173 | [[file:assets/ex06-dag.png]] 174 | 175 | *** ex07 - thi.ng/synstack & custom SDRAM delay 176 | 177 | [[./src/ex07/main.c][Source]] | [[https://soundcloud.com/forthcharlie/stm32f7-synstack-3-osc-fb-sdramdelay][Soundcloud]] 178 | 179 | Similar setup to *ex06* above, however to enable much longer delay 180 | times and not be limited by the <320KB of available on-chip RAM of the 181 | STM32F746-DISCO board, this example uses the 8MB "external" SDRAM 182 | (still on-board, just not in-chip), a [[./src/common/sdram_alloc.c][custom memory allocator]] 183 | (targetting SDRAM) and shows how to easily extend Synstack with custom 184 | DSP nodes - in this case a [[./src/synth_extras/osc_noise.c][noise oscillator]] and a [[./src/synth_extras/sdram_delay.c][new delay node]], 185 | which stores its long delay line in SDRAM, but then has to work with 186 | small, windowed sections in main RAM and mirror them back & forth. 187 | 188 | We also updated the DSP node graph to add the new oscillator, foldback 189 | distortion and replace the old delay with the new one... 190 | 191 | #+BEGIN_SRC dot :file assets/ex07-dag.png :exports results 192 | digraph g { 193 | rankdir=LR; 194 | node[color="black",style="filled",fontname="Inconsolata",fontcolor="white",fontsize=11]; 195 | edge[fontname="Inconsolata",fontsize=9]; 196 | 197 | env[label="AD(S)R"]; 198 | osc1[label="osc #1\n(spiral)"]; 199 | osc2[label="osc #2\n(saw-sin)"]; 200 | osc3[label="osc #3\n(noise)", color="red"]; 201 | mul1[shape="circle",label="*"]; 202 | mul2[shape="circle",label="*"]; 203 | mul3[shape="circle",label="*"]; 204 | sum[shape="circle",label="+"]; 205 | sum2[shape="circle",label="+"]; 206 | fb[label="foldback\ndistortion", color="red"]; 207 | filter[label="biquad LPF\n(randomized)"]; 208 | pan[label="stereo pan"]; 209 | delay[label="SDRAM delay", color="red"]; 210 | env -> mul1; 211 | env -> mul2; 212 | osc1 -> mul1 -> sum -> sum2; 213 | osc2 -> mul2 -> sum; 214 | osc3 -> mul3 -> sum2; 215 | sum2 -> fb -> filter -> pan -> delay; 216 | } 217 | #+END_SRC 218 | 219 | #+RESULTS: 220 | [[file:assets/ex07-dag.png]] 221 | 222 | *** ex08 - Synstack & MIDI 223 | 224 | [[./src/ex08/main.c][Source]] 225 | 226 | Based on *ex07* synth setup, but with USB MIDI support to turn synth 227 | into actual instrument (4 voice polyphonic). Via the optional 228 | =LOG_MIDI= flag (defined in [[./make/modules/ex08.make][ex08.make]]), received MIDI message can be 229 | logged to the board's LCD screen. 230 | 231 | *Note:* Currently the synth only accepts MIDI Note On messages and 232 | ignores MIDI Note Off's, since all voices only use an ADR envelope, 233 | without "sustain" phase. This will be added later... 234 | ** Resources 235 | 236 | - http://asm.thi.ng/ - links to all required SDK & build tools, 237 | references, learning resources... 238 | 239 | ** Contributors 240 | 241 | | *Name* | *Role* | *Website* | 242 | | [[mailto:k@thi.ng][Karsten Schmidt]] | initiator & principal developer | [[http://thi.ng][thi.ng]] | 243 | 244 | ** License 245 | 246 | This project is open source and licensed under the [[http://www.apache.org/licenses/LICENSE-2.0][Apache Software License 2.0]]. 247 | -------------------------------------------------------------------------------- /assets/equations.gcx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thi-ng/ws-ldn-12/c8f449408ff1d617470f3f57f1f185ab9158f999/assets/equations.gcx -------------------------------------------------------------------------------- /assets/ex06-dag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thi-ng/ws-ldn-12/c8f449408ff1d617470f3f57f1f185ab9158f999/assets/ex06-dag.png -------------------------------------------------------------------------------- /assets/ex07-dag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thi-ng/ws-ldn-12/c8f449408ff1d617470f3f57f1f185ab9158f999/assets/ex07-dag.png -------------------------------------------------------------------------------- /assets/gangknob48_12_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thi-ng/ws-ldn-12/c8f449408ff1d617470f3f57f1f185ab9158f999/assets/gangknob48_12_bg.png -------------------------------------------------------------------------------- /assets/moogknob48_16_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thi-ng/ws-ldn-12/c8f449408ff1d617470f3f57f1f185ab9158f999/assets/moogknob48_16_bg.png -------------------------------------------------------------------------------- /assets/ws-ldn-12-minigorille.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thi-ng/ws-ldn-12/c8f449408ff1d617470f3f57f1f185ab9158f999/assets/ws-ldn-12-minigorille.jpg -------------------------------------------------------------------------------- /cleanup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | find . \( -name \*.c -or -name \*.cpp -or -name \*.cc -or -name \*.h \) \ 3 | -not -path "./ext/*" \ 4 | | xargs -n12 -P4 clang-format -i 5 | -------------------------------------------------------------------------------- /ext/usbh_midi/usbh_MIDI.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file usbh_MIDI.c 4 | * @author Xavier Halgand 5 | * @version 6 | * @date 7 | * @brief This file is the MIDI Layer Handlers for USB Host MIDI streaming class. 8 | * 9 | * 10 | ****************************************************************************** 11 | */ 12 | 13 | /* 14 | * This program is free software; you can redistribute it and/or modify 15 | * it under the terms of the GNU General Public License as published by 16 | * the Free Software Foundation; either version 2 of the License, or 17 | * (at your option) any later version. 18 | * 19 | * This program is distributed in the hope that it will be useful, 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | * GNU General Public License for more details. 23 | * 24 | * You should have received a copy of the GNU General Public License 25 | * along with this program; if not, write to the Free Software 26 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | * 28 | */ 29 | 30 | /* Includes ------------------------------------------------------------------*/ 31 | #include "usbh_MIDI.h" 32 | 33 | /*------------------------------------------------------------------------------------------------------------------------------*/ 34 | 35 | /** @defgroup USBH_MIDI_CORE_Private_FunctionPrototypes 36 | * @{ 37 | */ 38 | 39 | static USBH_StatusTypeDef USBH_MIDI_InterfaceInit(USBH_HandleTypeDef *phost); 40 | 41 | static USBH_StatusTypeDef USBH_MIDI_InterfaceDeInit(USBH_HandleTypeDef *phost); 42 | 43 | static USBH_StatusTypeDef USBH_MIDI_Process(USBH_HandleTypeDef *phost); 44 | 45 | static USBH_StatusTypeDef USBH_MIDI_SOFProcess(USBH_HandleTypeDef *phost); 46 | 47 | static USBH_StatusTypeDef USBH_MIDI_ClassRequest(USBH_HandleTypeDef *phost); 48 | 49 | static void MIDI_ProcessTransmission(USBH_HandleTypeDef *phost); 50 | 51 | static void MIDI_ProcessReception(USBH_HandleTypeDef *phost); 52 | 53 | /*-------------------------------------------------------------------------*/ 54 | 55 | USBH_ClassTypeDef MIDI_Class = { 56 | "MIDI", USB_AUDIO_CLASS, USBH_MIDI_InterfaceInit, USBH_MIDI_InterfaceDeInit, 57 | USBH_MIDI_ClassRequest, 58 | USBH_MIDI_Process, // background process called in HOST_CLASS state (core state machine) 59 | USBH_MIDI_SOFProcess, 60 | NULL // MIDI handle structure 61 | }; 62 | 63 | /*------------------------------------------------------------------------------------------------------------------------------*/ 64 | 65 | /** 66 | * @brief USBH_MIDI_InterfaceInit 67 | * The function init the MIDI class. 68 | * @param phost: Host handle 69 | * @retval USBH Status 70 | */ 71 | static USBH_StatusTypeDef USBH_MIDI_InterfaceInit(USBH_HandleTypeDef *phost) { 72 | USBH_StatusTypeDef status = USBH_FAIL; 73 | uint8_t interface = 0; 74 | MIDI_HandleTypeDef *MIDI_Handle; 75 | 76 | //USB_MIDI_ChangeConnectionState(0); 77 | 78 | interface = USBH_FindInterface(phost, USB_AUDIO_CLASS, 79 | USB_MIDISTREAMING_SubCLASS, 0xFF); 80 | 81 | if (interface == 0xFF) /* No Valid Interface */ 82 | { 83 | USBH_DbgLog("Cannot Find the interface for MIDI Interface Class.", 84 | phost->pActiveClass->Name); 85 | status = USBH_FAIL; 86 | } else { 87 | USBH_SelectInterface(phost, interface); 88 | 89 | phost->pActiveClass->pData = 90 | (MIDI_HandleTypeDef *)USBH_malloc(sizeof(MIDI_HandleTypeDef)); 91 | MIDI_Handle = phost->pActiveClass->pData; 92 | 93 | if (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface] 94 | .Ep_Desc[0] 95 | .bEndpointAddress & 96 | 0x80) { 97 | MIDI_Handle->InEp = 98 | (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface] 99 | .Ep_Desc[0] 100 | .bEndpointAddress); 101 | MIDI_Handle->InEpSize = 102 | phost->device.CfgDesc.Itf_Desc[phost->device.current_interface] 103 | .Ep_Desc[0] 104 | .wMaxPacketSize; 105 | } else { 106 | MIDI_Handle->OutEp = 107 | (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface] 108 | .Ep_Desc[0] 109 | .bEndpointAddress); 110 | MIDI_Handle->OutEpSize = 111 | phost->device.CfgDesc.Itf_Desc[phost->device.current_interface] 112 | .Ep_Desc[0] 113 | .wMaxPacketSize; 114 | } 115 | 116 | if (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface] 117 | .Ep_Desc[1] 118 | .bEndpointAddress & 119 | 0x80) { 120 | MIDI_Handle->InEp = 121 | (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface] 122 | .Ep_Desc[1] 123 | .bEndpointAddress); 124 | MIDI_Handle->InEpSize = 125 | phost->device.CfgDesc.Itf_Desc[phost->device.current_interface] 126 | .Ep_Desc[1] 127 | .wMaxPacketSize; 128 | } else { 129 | MIDI_Handle->OutEp = 130 | (phost->device.CfgDesc.Itf_Desc[phost->device.current_interface] 131 | .Ep_Desc[1] 132 | .bEndpointAddress); 133 | MIDI_Handle->OutEpSize = 134 | phost->device.CfgDesc.Itf_Desc[phost->device.current_interface] 135 | .Ep_Desc[1] 136 | .wMaxPacketSize; 137 | } 138 | 139 | MIDI_Handle->OutPipe = USBH_AllocPipe(phost, MIDI_Handle->OutEp); 140 | MIDI_Handle->InPipe = USBH_AllocPipe(phost, MIDI_Handle->InEp); 141 | 142 | /* Open the new channels */ 143 | USBH_OpenPipe(phost, MIDI_Handle->OutPipe, MIDI_Handle->OutEp, 144 | phost->device.address, phost->device.speed, USB_EP_TYPE_BULK, 145 | MIDI_Handle->OutEpSize); 146 | 147 | USBH_OpenPipe(phost, MIDI_Handle->InPipe, MIDI_Handle->InEp, 148 | phost->device.address, phost->device.speed, USB_EP_TYPE_BULK, 149 | MIDI_Handle->InEpSize); 150 | 151 | //USB_MIDI_ChangeConnectionState(1); 152 | MIDI_Handle->state = MIDI_IDLE_STATE; 153 | 154 | USBH_LL_SetToggle(phost, MIDI_Handle->InPipe, 0); 155 | USBH_LL_SetToggle(phost, MIDI_Handle->OutPipe, 0); 156 | status = USBH_OK; 157 | } 158 | return status; 159 | } 160 | 161 | /*------------------------------------------------------------------------------------------------------------------------------*/ 162 | 163 | /** 164 | * @brief USBH_MIDI_InterfaceDeInit 165 | * The function DeInit the Pipes used for the MIDI class. 166 | * @param phost: Host handle 167 | * @retval USBH Status 168 | */ 169 | USBH_StatusTypeDef USBH_MIDI_InterfaceDeInit(USBH_HandleTypeDef *phost) { 170 | MIDI_HandleTypeDef *MIDI_Handle = phost->pActiveClass->pData; 171 | 172 | if (MIDI_Handle->OutPipe) { 173 | USBH_ClosePipe(phost, MIDI_Handle->OutPipe); 174 | USBH_FreePipe(phost, MIDI_Handle->OutPipe); 175 | MIDI_Handle->OutPipe = 0; /* Reset the Channel as Free */ 176 | } 177 | 178 | if (MIDI_Handle->InPipe) { 179 | USBH_ClosePipe(phost, MIDI_Handle->InPipe); 180 | USBH_FreePipe(phost, MIDI_Handle->InPipe); 181 | MIDI_Handle->InPipe = 0; /* Reset the Channel as Free */ 182 | } 183 | 184 | if (phost->pActiveClass->pData) { 185 | USBH_free(phost->pActiveClass->pData); 186 | phost->pActiveClass->pData = 0; 187 | } 188 | 189 | return USBH_OK; 190 | } 191 | 192 | /*------------------------------------------------------------------------------------------------------------------------------*/ 193 | 194 | /** 195 | * @brief USBH_MIDI_ClassRequest 196 | * The function is responsible for handling Standard requests 197 | * for MIDI class. 198 | * @param phost: Host handle 199 | * @retval USBH Status 200 | */ 201 | static USBH_StatusTypeDef USBH_MIDI_ClassRequest(USBH_HandleTypeDef *phost) { 202 | phost->pUser(phost, HOST_USER_CLASS_ACTIVE); 203 | 204 | return USBH_OK; 205 | } 206 | 207 | /*------------------------------------------------------------------------------------------------------------------------------*/ 208 | 209 | /** 210 | * @brief USBH_MIDI_Stop 211 | * Stop current MIDI Transmission 212 | * @param phost: Host handle 213 | * @retval USBH Status 214 | */ 215 | USBH_StatusTypeDef USBH_MIDI_Stop(USBH_HandleTypeDef *phost) { 216 | MIDI_HandleTypeDef *MIDI_Handle = phost->pActiveClass->pData; 217 | 218 | if (phost->gState == HOST_CLASS) { 219 | MIDI_Handle->state = MIDI_IDLE_STATE; 220 | 221 | USBH_ClosePipe(phost, MIDI_Handle->InPipe); 222 | USBH_ClosePipe(phost, MIDI_Handle->OutPipe); 223 | } 224 | return USBH_OK; 225 | } 226 | 227 | /*------------------------------------------------------------------------------------------------------------------------------*/ 228 | 229 | /** 230 | * @brief USBH_MIDI_Process 231 | * The function is for managing state machine for MIDI data transfers 232 | * (background process) 233 | * @param phost: Host handle 234 | * @retval USBH Status 235 | */ 236 | static USBH_StatusTypeDef USBH_MIDI_Process(USBH_HandleTypeDef *phost) { 237 | USBH_StatusTypeDef status = USBH_BUSY; 238 | USBH_StatusTypeDef req_status = USBH_OK; 239 | MIDI_HandleTypeDef *MIDI_Handle = phost->pActiveClass->pData; 240 | 241 | switch (MIDI_Handle->state) { 242 | case MIDI_IDLE_STATE: 243 | status = USBH_OK; 244 | break; 245 | 246 | case MIDI_TRANSFER_DATA: 247 | 248 | MIDI_ProcessTransmission(phost); 249 | MIDI_ProcessReception(phost); 250 | break; 251 | 252 | case MIDI_ERROR_STATE: 253 | req_status = USBH_ClrFeature(phost, 0x00); 254 | 255 | if (req_status == USBH_OK) { 256 | /*Change the state to waiting*/ 257 | MIDI_Handle->state = MIDI_IDLE_STATE; 258 | } 259 | break; 260 | 261 | default: 262 | break; 263 | } 264 | 265 | return status; 266 | } 267 | /*------------------------------------------------------------------------------------------------------------------------------*/ 268 | 269 | /** 270 | * @brief USBH_MIDI_SOFProcess 271 | * The function is for managing SOF callback 272 | * @param phost: Host handle 273 | * @retval USBH Status 274 | */ 275 | static USBH_StatusTypeDef USBH_MIDI_SOFProcess(USBH_HandleTypeDef *phost) { 276 | return USBH_OK; 277 | } 278 | 279 | /*------------------------------------------------------------------------------------------------------------------------------*/ 280 | 281 | /** 282 | * @brief This function return last recieved data size 283 | * @param None 284 | * @retval None 285 | */ 286 | uint16_t USBH_MIDI_GetLastReceivedDataSize(USBH_HandleTypeDef *phost) { 287 | MIDI_HandleTypeDef *MIDI_Handle = phost->pActiveClass->pData; 288 | 289 | if (phost->gState == HOST_CLASS) { 290 | return USBH_LL_GetLastXferSize(phost, MIDI_Handle->InPipe); 291 | } else { 292 | return 0; 293 | } 294 | } 295 | 296 | /*------------------------------------------------------------------------------------------------------------------------------*/ 297 | 298 | /** 299 | * @brief This function prepares the state before issuing the class specific commands 300 | * @param None 301 | * @retval None 302 | */ 303 | USBH_StatusTypeDef USBH_MIDI_Transmit(USBH_HandleTypeDef *phost, 304 | uint8_t *pbuff, 305 | uint16_t length) { 306 | USBH_StatusTypeDef Status = USBH_BUSY; 307 | MIDI_HandleTypeDef *MIDI_Handle = phost->pActiveClass->pData; 308 | 309 | if ((MIDI_Handle->state == MIDI_IDLE_STATE) || 310 | (MIDI_Handle->state == MIDI_TRANSFER_DATA)) { 311 | MIDI_Handle->pTxData = pbuff; 312 | MIDI_Handle->TxDataLength = length; 313 | MIDI_Handle->state = MIDI_TRANSFER_DATA; 314 | MIDI_Handle->data_tx_state = MIDI_SEND_DATA; 315 | Status = USBH_OK; 316 | #if (USBH_USE_OS == 1) 317 | osMessagePut(phost->os_event, USBH_CLASS_EVENT, 0); 318 | #endif 319 | } 320 | return Status; 321 | } 322 | 323 | /*------------------------------------------------------------------------------------------------------------------------------*/ 324 | 325 | /** 326 | * @brief This function prepares the state before issuing the class specific commands 327 | * @param None 328 | * @retval None 329 | */ 330 | USBH_StatusTypeDef USBH_MIDI_Receive(USBH_HandleTypeDef *phost, 331 | uint8_t *pbuff, 332 | uint16_t length) { 333 | USBH_StatusTypeDef Status = USBH_BUSY; 334 | MIDI_HandleTypeDef *MIDI_Handle = phost->pActiveClass->pData; 335 | 336 | if ((MIDI_Handle->state == MIDI_IDLE_STATE) || 337 | (MIDI_Handle->state == MIDI_TRANSFER_DATA)) { 338 | MIDI_Handle->pRxData = pbuff; 339 | MIDI_Handle->RxDataLength = length; 340 | MIDI_Handle->state = MIDI_TRANSFER_DATA; 341 | MIDI_Handle->data_rx_state = MIDI_RECEIVE_DATA; 342 | Status = USBH_OK; 343 | #if (USBH_USE_OS == 1) 344 | osMessagePut(phost->os_event, USBH_CLASS_EVENT, 0); 345 | #endif 346 | } 347 | return Status; 348 | } 349 | 350 | /*------------------------------------------------------------------------------------------------------------------------------*/ 351 | 352 | /** 353 | * @brief The function is responsible for sending data to the device 354 | * @param pdev: Selected device 355 | * @retval None 356 | */ 357 | static void MIDI_ProcessTransmission(USBH_HandleTypeDef *phost) { 358 | MIDI_HandleTypeDef *MIDI_Handle = phost->pActiveClass->pData; 359 | USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE; 360 | 361 | switch (MIDI_Handle->data_tx_state) { 362 | case MIDI_SEND_DATA: 363 | if (MIDI_Handle->TxDataLength > MIDI_Handle->OutEpSize) { 364 | USBH_BulkSendData(phost, MIDI_Handle->pTxData, MIDI_Handle->OutEpSize, 365 | MIDI_Handle->OutPipe, 1); 366 | } else { 367 | USBH_BulkSendData(phost, MIDI_Handle->pTxData, 368 | MIDI_Handle->TxDataLength, MIDI_Handle->OutPipe, 1); 369 | } 370 | 371 | MIDI_Handle->data_tx_state = MIDI_SEND_DATA_WAIT; 372 | 373 | break; 374 | 375 | case MIDI_SEND_DATA_WAIT: 376 | 377 | URB_Status = USBH_LL_GetURBState(phost, MIDI_Handle->OutPipe); 378 | 379 | /*Check the status done for transmission*/ 380 | if (URB_Status == USBH_URB_DONE) { 381 | if (MIDI_Handle->TxDataLength > MIDI_Handle->OutEpSize) { 382 | MIDI_Handle->TxDataLength -= MIDI_Handle->OutEpSize; 383 | MIDI_Handle->pTxData += MIDI_Handle->OutEpSize; 384 | } else { 385 | MIDI_Handle->TxDataLength = 0; 386 | } 387 | 388 | if (MIDI_Handle->TxDataLength > 0) { 389 | MIDI_Handle->data_tx_state = MIDI_SEND_DATA; 390 | } else { 391 | MIDI_Handle->data_tx_state = MIDI_IDLE; 392 | USBH_MIDI_TransmitCallback(phost); 393 | } 394 | #if (USBH_USE_OS == 1) 395 | osMessagePut(phost->os_event, USBH_CLASS_EVENT, 0); 396 | #endif 397 | } else if (URB_Status == USBH_URB_NOTREADY) { 398 | MIDI_Handle->data_tx_state = MIDI_SEND_DATA; 399 | #if (USBH_USE_OS == 1) 400 | osMessagePut(phost->os_event, USBH_CLASS_EVENT, 0); 401 | #endif 402 | } 403 | break; 404 | default: 405 | break; 406 | } 407 | } 408 | 409 | /*------------------------------------------------------------------------------------------------------------------------------*/ 410 | 411 | /** 412 | * @brief This function responsible for reception of data from the device 413 | * @param pdev: Selected device 414 | * @retval None 415 | */ 416 | 417 | static void MIDI_ProcessReception(USBH_HandleTypeDef *phost) { 418 | MIDI_HandleTypeDef *MIDI_Handle = phost->pActiveClass->pData; 419 | USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE; 420 | uint16_t length; 421 | 422 | switch (MIDI_Handle->data_rx_state) { 423 | case MIDI_RECEIVE_DATA: 424 | 425 | USBH_BulkReceiveData(phost, MIDI_Handle->pRxData, MIDI_Handle->InEpSize, 426 | MIDI_Handle->InPipe); 427 | 428 | MIDI_Handle->data_rx_state = MIDI_RECEIVE_DATA_WAIT; 429 | //BSP_LED_On(LED_Red); //ok only here 430 | 431 | break; 432 | 433 | case MIDI_RECEIVE_DATA_WAIT: 434 | 435 | URB_Status = USBH_LL_GetURBState(phost, MIDI_Handle->InPipe); 436 | 437 | /*Check the status done for reception*/ 438 | if (URB_Status == USBH_URB_DONE) { 439 | length = USBH_LL_GetLastXferSize(phost, MIDI_Handle->InPipe); 440 | 441 | if (((MIDI_Handle->RxDataLength - length) > 0) && 442 | (length > MIDI_Handle->InEpSize)) { 443 | MIDI_Handle->RxDataLength -= length; 444 | MIDI_Handle->pRxData += length; 445 | MIDI_Handle->data_rx_state = MIDI_RECEIVE_DATA; 446 | } else { 447 | MIDI_Handle->data_rx_state = MIDI_IDLE; 448 | USBH_MIDI_ReceiveCallback(phost); 449 | } 450 | #if (USBH_USE_OS == 1) 451 | osMessagePut(phost->os_event, USBH_CLASS_EVENT, 0); 452 | #endif 453 | } 454 | break; 455 | 456 | default: 457 | break; 458 | } 459 | } 460 | 461 | /*------------------------------------------------------------------------------------------------------------------------------*/ 462 | 463 | /** 464 | * @brief The function informs user that data have been transmitted. 465 | * @param pdev: Selected device 466 | * @retval None 467 | */ 468 | __weak void USBH_MIDI_TransmitCallback(USBH_HandleTypeDef *phost) { 469 | } 470 | 471 | /*------------------------------------------------------------------------------------------------------------------------------*/ 472 | 473 | /** 474 | * @brief The function informs user that data have been received. 475 | * @retval None 476 | */ 477 | __weak void USBH_MIDI_ReceiveCallback(USBH_HandleTypeDef *phost) { 478 | } 479 | 480 | /**************************END OF FILE*********************************************************/ 481 | -------------------------------------------------------------------------------- /ext/usbh_midi/usbh_MIDI.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file usbh_MIDI.h 4 | * @author Xavier Halgand 5 | * @version 6 | * @date 7 | * @brief This file contains all the prototypes for the usbh_MIDI.c 8 | ****************************************************************************** 9 | */ 10 | /* 11 | * This program is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation; either version 2 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program; if not, write to the Free Software 23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | * 25 | */ 26 | 27 | /* Define to prevent recursive ----------------------------------------------*/ 28 | #ifndef __USBH_MIDI_CORE_H 29 | #define __USBH_MIDI_CORE_H 30 | 31 | /* Includes ------------------------------------------------------------------*/ 32 | #include "stm32746g_discovery.h" 33 | #include "usbh_core.h" 34 | 35 | /*-------------------------------------------------------------------------------*/ 36 | // buffer size (should be at least >= MIOS32_USB_MIDI_DESC_DATA_*_SIZE/4) 37 | #define USB_MIDI_RX_BUFFER_SIZE 64 // packages 38 | #define USB_MIDI_TX_BUFFER_SIZE 64 // packages 39 | 40 | // size of IN/OUT pipe 41 | #define USB_MIDI_DATA_IN_SIZE 64 42 | #define USB_MIDI_DATA_OUT_SIZE 64 43 | 44 | // endpoint assignments (don't change!) 45 | #define USB_MIDI_DATA_OUT_EP 0x02 46 | #define USB_MIDI_DATA_IN_EP 0x81 47 | /** @defgroup USBH_MIDI_CORE_Exported_Defines 48 | * @{ 49 | */ 50 | #define USB_AUDIO_CLASS 0x01 51 | #define USB_MIDISTREAMING_SubCLASS 0x03 52 | #define USB_MIDI_DESC_SIZE 9 53 | #define USBH_MIDI_CLASS &MIDI_Class 54 | 55 | /*-------------------------------------------------------------------------------*/ 56 | 57 | extern USBH_ClassTypeDef MIDI_Class; 58 | 59 | /* -------------------- Exported_Types ------------------------------------------*/ 60 | 61 | typedef enum { 62 | NoteOff = 0x8, 63 | NoteOn = 0x9, 64 | PolyPressure = 0xa, 65 | CC = 0xb, 66 | ProgramChange = 0xc, 67 | Aftertouch = 0xd, 68 | PitchBend = 0xe 69 | } midi_event_t; 70 | 71 | typedef enum { 72 | Chn1, 73 | Chn2, 74 | Chn3, 75 | Chn4, 76 | Chn5, 77 | Chn6, 78 | Chn7, 79 | Chn8, 80 | Chn9, 81 | Chn10, 82 | Chn11, 83 | Chn12, 84 | Chn13, 85 | Chn14, 86 | Chn15, 87 | Chn16 88 | } midi_chn_t; 89 | 90 | typedef union { 91 | struct { 92 | uint32_t ALL; 93 | }; 94 | struct { 95 | uint8_t cin_cable; 96 | uint8_t evnt0; 97 | uint8_t evnt1; 98 | uint8_t evnt2; 99 | }; 100 | struct { 101 | uint8_t type : 4; 102 | uint8_t cable : 4; 103 | uint8_t chn : 4; // mios32_midi_chn_t 104 | uint8_t event : 4; // mios32_midi_event_t 105 | uint8_t value1; 106 | uint8_t value2; 107 | }; 108 | 109 | // C++ doesn't allow to redefine names in anonymous unions 110 | // as a simple workaround, we rename these redundant names 111 | struct { 112 | uint8_t cin : 4; 113 | uint8_t dummy1_cable : 4; 114 | uint8_t dummy1_chn : 4; // mios32_midi_chn_t 115 | uint8_t dummy1_event : 4; // mios32_midi_event_t 116 | uint8_t note : 8; 117 | uint8_t velocity : 8; 118 | }; 119 | struct { 120 | uint8_t dummy2_cin : 4; 121 | uint8_t dummy2_cable : 4; 122 | uint8_t dummy2_chn : 4; // mios32_midi_chn_t 123 | uint8_t dummy2_event : 4; // mios32_midi_event_t 124 | uint8_t cc_number : 8; 125 | uint8_t value : 8; 126 | }; 127 | struct { 128 | uint8_t dummy3_cin : 4; 129 | uint8_t dummy3_cable : 4; 130 | uint8_t dummy3_chn : 4; // mios32_midi_chn_t 131 | uint8_t dummy3_event : 4; // mios32_midi_event_t 132 | uint8_t program_change : 8; 133 | uint8_t dummy3 : 8; 134 | }; 135 | } midi_package_t; 136 | 137 | /* States for MIDI State Machine */ 138 | typedef enum { 139 | MIDI_IDLE = 0, 140 | MIDI_SEND_DATA, 141 | MIDI_SEND_DATA_WAIT, 142 | MIDI_RECEIVE_DATA, 143 | MIDI_RECEIVE_DATA_WAIT, 144 | } MIDI_DataStateTypeDef; 145 | 146 | typedef enum { 147 | MIDI_IDLE_STATE = 0, 148 | MIDI_TRANSFER_DATA, 149 | MIDI_ERROR_STATE, 150 | } MIDI_StateTypeDef; 151 | 152 | /* Structure for MIDI process */ 153 | typedef struct _MIDI_Process { 154 | MIDI_StateTypeDef state; 155 | uint8_t InPipe; 156 | uint8_t OutPipe; 157 | uint8_t OutEp; 158 | uint8_t InEp; 159 | uint16_t OutEpSize; 160 | uint16_t InEpSize; 161 | 162 | uint8_t *pTxData; 163 | uint8_t *pRxData; 164 | uint16_t TxDataLength; 165 | uint16_t RxDataLength; 166 | MIDI_DataStateTypeDef data_tx_state; 167 | MIDI_DataStateTypeDef data_rx_state; 168 | uint8_t Rx_Poll; 169 | //uint8_t buff[8]; 170 | //MIDI_DataItfTypedef DataItf; 171 | //CDC_InterfaceDesc_Typedef CDC_Desc; 172 | } MIDI_HandleTypeDef; 173 | 174 | /*---------------------------Exported_FunctionsPrototype-------------------------------------*/ 175 | 176 | USBH_StatusTypeDef USBH_MIDI_Transmit(USBH_HandleTypeDef *phost, 177 | uint8_t *pbuff, 178 | uint16_t length); 179 | 180 | USBH_StatusTypeDef USBH_MIDI_Receive(USBH_HandleTypeDef *phost, 181 | uint8_t *pbuff, 182 | uint16_t length); 183 | 184 | uint16_t USBH_MIDI_GetLastReceivedDataSize(USBH_HandleTypeDef *phost); 185 | 186 | USBH_StatusTypeDef USBH_MIDI_Stop(USBH_HandleTypeDef *phost); 187 | 188 | void USBH_MIDI_TransmitCallback(USBH_HandleTypeDef *phost); 189 | 190 | void USBH_MIDI_ReceiveCallback(USBH_HandleTypeDef *phost); 191 | 192 | /*-------------------------------------------------------------------------------------------*/ 193 | #endif /* __USBH_MIDI_CORE_H */ 194 | 195 | /*****************************END OF FILE*************************************************************/ 196 | -------------------------------------------------------------------------------- /make/devices/stm32f746.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * Default linker script for Cortex-M (it includes specifics for STM32F[34]xx). 3 | * Based on GNU ARM Eclipse & STM32F7Cube templates 4 | */ 5 | 6 | /* Boot entry (defined in startup_stm32f746xx.s) */ 7 | ENTRY(Reset_Handler) 8 | 9 | /* Specify the memory areas */ 10 | MEMORY { 11 | FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K 12 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K 13 | /* 14 | * SRAM starts at 0xC0000000, but we reserve memory 15 | * for two LCD screen buffers (800 * 480 * 4 * 2) 16 | */ 17 | SRAM (xrw) : ORIGIN = 0xC02EE000, LENGTH = 5192K 18 | } 19 | 20 | /* Highest address of the user mode stack */ 21 | __stack = ORIGIN(RAM) + LENGTH(RAM); 22 | _estack = __stack; /* STM specific */ 23 | 24 | /* Define SRAM region limits */ 25 | _sram_start = ORIGIN(SRAM); 26 | _sram_end = ORIGIN(SRAM) + LENGTH(SRAM); 27 | 28 | /* Generate a link error if heap and stack don't fit into RAM */ 29 | _Min_Heap_Size = 0x200; /* required amount of heap */ 30 | _Min_Stack_Size = 0x400; /* required amount of stack */ 31 | 32 | /* Define output sections */ 33 | SECTIONS { 34 | /* 35 | * For Cortex-M devices, the beginning of the startup code is stored in 36 | * the .isr_vector section, which goes to FLASH. 37 | */ 38 | .isr_vector : ALIGN(4) { 39 | KEEP(*(.isr_vector)) /* ISR jump table */ 40 | . = ALIGN(4); 41 | } >FLASH 42 | 43 | /* Program code and other data goes into FLASH */ 44 | .text : ALIGN(4) { 45 | *(.text .text.*) 46 | /* 47 | * Stub sections generated by the linker, to glue together 48 | * ARM and Thumb code. .glue_7 is used for ARM code calling 49 | * Thumb code, and .glue_7t is used for Thumb code calling 50 | * ARM code. Apparently always generated by the linker, for some 51 | * architectures, so better leave them here. 52 | */ 53 | *(.glue_7 .glue_7t) 54 | *(.eh_frame) 55 | 56 | KEEP (*(.init)) 57 | KEEP (*(.fini)) 58 | 59 | . = ALIGN(4); 60 | _etext = .; /* define a global symbols at end of code */ 61 | } >FLASH 62 | 63 | /* Constant data (constants, strings, etc.) goes into FLASH */ 64 | .rodata : ALIGN(4) { 65 | *(.rodata .rodata*) 66 | . = ALIGN(4); 67 | } >FLASH 68 | 69 | .ARM.extab : ALIGN(4) { 70 | *(.ARM.extab* .gnu.linkonce.armextab.*) 71 | } >FLASH 72 | 73 | .ARM : ALIGN(4) { 74 | __exidx_start = .; 75 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) 76 | __exidx_end = .; 77 | } >FLASH 78 | 79 | .preinit_array : { 80 | PROVIDE_HIDDEN (__preinit_array_start = .); 81 | KEEP (*(.preinit_array*)) 82 | PROVIDE_HIDDEN (__preinit_array_end = .); 83 | } >FLASH 84 | 85 | .init_array : { 86 | PROVIDE_HIDDEN (__init_array_start = .); 87 | KEEP (*(SORT(.init_array.*))) 88 | KEEP (*(.init_array*)) 89 | PROVIDE_HIDDEN (__init_array_end = .); 90 | } >FLASH 91 | 92 | .fini_array : { 93 | PROVIDE_HIDDEN (__fini_array_start = .); 94 | KEEP (*(SORT(.fini_array.*))) 95 | KEEP (*(.fini_array*)) 96 | PROVIDE_HIDDEN (__fini_array_end = .); 97 | } >FLASH 98 | 99 | /* used by the startup to initialize data */ 100 | _sidata = LOADADDR(.data); 101 | 102 | /* Initialized data sections goes into RAM, load LMA copy after code */ 103 | .data : ALIGN(4) { 104 | _sdata = .; /* create a global symbol at data start */ 105 | *(.data) /* .data sections */ 106 | *(.data*) /* .data* sections */ 107 | 108 | . = ALIGN(4); 109 | _edata = .; /* define a global symbol at data end */ 110 | } >RAM AT> FLASH 111 | 112 | 113 | /* Uninitialized data section */ 114 | .bss (NOLOAD) : ALIGN(4) { 115 | /* This is used by the startup in order to initialize the .bss secion */ 116 | _sbss = .; /* define a global symbol at bss start */ 117 | __bss_start__ = _sbss; 118 | *(.bss .bss*) 119 | *(COMMON) 120 | 121 | . = ALIGN(4); 122 | _ebss = .; /* define a global symbol at bss end */ 123 | __bss_end__ = _ebss; 124 | } >RAM 125 | 126 | /* User_heap_stack section, used to check that there is enough RAM left */ 127 | ._user_heap_stack : ALIGN(8) { 128 | PROVIDE ( end = . ); 129 | PROVIDE ( _end = . ); 130 | . = . + _Min_Heap_Size; 131 | . = . + _Min_Stack_Size; 132 | . = ALIGN(8); 133 | } >RAM 134 | 135 | /* Remove information from the standard libraries */ 136 | /DISCARD/ : 137 | { 138 | libc.a ( * ) 139 | libm.a ( * ) 140 | libgcc.a ( * ) 141 | } 142 | 143 | .ARM.attributes 0 : { *(.ARM.attributes) } 144 | } 145 | -------------------------------------------------------------------------------- /make/devices/stm32f746.make: -------------------------------------------------------------------------------- 1 | $(info configuring for STM32F746) 2 | 3 | DEVICE_DIR = $(CMSIS_DIR)/Device/ST/STM32F7xx 4 | HAL_DIR = $(STM_SRC_ROOT)/STM32F7xx_HAL_Driver 5 | BSP_DIR = $(STM_SRC_ROOT)/BSP/STM32746G-Discovery 6 | 7 | DEFINES += -DSTM32F746xx -DUSE_STM32746G_DISCO 8 | 9 | CFLAGS += -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-sp-d16 10 | LD_FLAGS += -Tstm32f746.ld 11 | 12 | ASM_SRC += $(DEVICE_DIR)/Source/Templates/gcc/startup_stm32f746xx.s 13 | 14 | # always include audio & touchscreen drivers 15 | LL_SRC = $(addprefix $(LL_DIR),/ft5336/ft5336.c /wm8994/wm8994.c) 16 | -------------------------------------------------------------------------------- /make/modules/ex01.make: -------------------------------------------------------------------------------- 1 | catalog = make/sources.txt 2 | 3 | CFLAGS += -Os 4 | -------------------------------------------------------------------------------- /make/modules/ex02.make: -------------------------------------------------------------------------------- 1 | catalog = make/sources.txt 2 | 3 | USER_SRC += $(wildcard ext/ct-gui/*.c) 4 | 5 | CFLAGS += -Os 6 | -------------------------------------------------------------------------------- /make/modules/ex03.make: -------------------------------------------------------------------------------- 1 | catalog = make/sources.txt 2 | 3 | CFLAGS += -Os 4 | -------------------------------------------------------------------------------- /make/modules/ex04.make: -------------------------------------------------------------------------------- 1 | catalog = make/sources.txt 2 | 3 | USER_SRC += $(wildcard ext/ct-gui/*.c) 4 | 5 | CFLAGS += -O3 -ffast-math 6 | -------------------------------------------------------------------------------- /make/modules/ex05.make: -------------------------------------------------------------------------------- 1 | catalog = make/sources.txt 2 | 3 | USE_USBH = 1 4 | USE_FATFS = 1 5 | 6 | USER_INCLUDES += -Isrc/ex05 -Iext/ct-synstack/src 7 | 8 | CFLAGS += -O3 -ffast-math 9 | -------------------------------------------------------------------------------- /make/modules/ex06.make: -------------------------------------------------------------------------------- 1 | catalog = make/sources.txt 2 | 3 | USER_INCLUDES += -Iext/ct-synstack/src 4 | USER_SRC += $(wildcard ext/ct-synstack/src/*.c) 5 | 6 | CFLAGS += -O3 -ffast-math 7 | -------------------------------------------------------------------------------- /make/modules/ex07.make: -------------------------------------------------------------------------------- 1 | catalog = make/sources.txt 2 | 3 | USER_INCLUDES += -Iext/ct-synstack/src -Isrc/synth_extras 4 | USER_SRC += $(wildcard ext/ct-synstack/src/*.c) 5 | USER_SRC += src/synth_extras/osc_noise.c src/synth_extras/sdram_delay.c 6 | 7 | CFLAGS += -O3 -ffast-math 8 | -------------------------------------------------------------------------------- /make/modules/ex08.make: -------------------------------------------------------------------------------- 1 | catalog = make/sources.txt 2 | 3 | USE_USBH = 1 4 | USBH_INCLUDES += -I$(EXT_SRC_DIR)/usbh_midi 5 | USBH_SRC += $(EXT_SRC_DIR)/usbh_midi/usbh_MIDI.c 6 | 7 | USER_INCLUDES += -Isrc/ex08 -Iext/ct-synstack/src -Isrc/synth_extras 8 | USER_SRC += $(wildcard ext/ct-synstack/src/*.c) $(wildcard src/synth_extras/*.c) 9 | 10 | #DEFINES += -DLOG_MIDI 11 | 12 | CFLAGS += -O3 -ffast-math 13 | -------------------------------------------------------------------------------- /make/sources.txt: -------------------------------------------------------------------------------- 1 | # In order to speed up the build process using the STM32CubeF7 SDK 2 | # only the uncommented files listed here will be included. The filter 3 | # is NOT applied to any user sources in /src 4 | # 5 | # IMPORTANT: 6 | # It's the user's responsibility to ensure the selected HAL files 7 | # are in sync with the config in /src/stm32f7xx_hal_conf.h 8 | # I.e. if you've enabled a HAL module in the config header file 9 | # then it also MUST be enabled here! 10 | 11 | # CMSIS 12 | %system_stm32f7xx.c 13 | 14 | # HAL 15 | %stm32f7xx_hal.c 16 | %stm32f7xx_hal_adc.c 17 | %stm32f7xx_hal_adc_ex.c 18 | # %stm32f7xx_hal_can.c 19 | # %stm32f7xx_hal_cec.c 20 | %stm32f7xx_hal_cortex.c 21 | # %stm32f7xx_hal_crc.c 22 | # %stm32f7xx_hal_crc_ex.c 23 | # %stm32f7xx_hal_cryp.c 24 | # %stm32f7xx_hal_cryp_ex.c 25 | %stm32f7xx_hal_dac.c 26 | %stm32f7xx_hal_dac_ex.c 27 | # %stm32f7xx_hal_dcmi.c 28 | # %stm32f7xx_hal_dcmi_ex.c 29 | # %stm32f7xx_hal_dfsdm.c 30 | %stm32f7xx_hal_dma.c 31 | %stm32f7xx_hal_dma2d.c 32 | %stm32f7xx_hal_dma_ex.c 33 | # %stm32f7xx_hal_dsi.c 34 | # %stm32f7xx_hal_eth.c 35 | %stm32f7xx_hal_flash.c 36 | %stm32f7xx_hal_flash_ex.c 37 | %stm32f7xx_hal_gpio.c 38 | # %stm32f7xx_hal_hash.c 39 | # %stm32f7xx_hal_hash_ex.c 40 | %stm32f7xx_hal_hcd.c 41 | %stm32f7xx_hal_i2c.c 42 | %stm32f7xx_hal_i2c_ex.c 43 | %stm32f7xx_hal_i2s.c 44 | # %stm32f7xx_hal_irda.c 45 | # %stm32f7xx_hal_iwdg.c 46 | # %stm32f7xx_hal_jpeg.c 47 | # %stm32f7xx_hal_lptim.c 48 | %stm32f7xx_hal_ltdc.c 49 | %stm32f7xx_hal_ltdc_ex.c 50 | # %stm32f7xx_hal_mdios.c 51 | # %stm32f7xx_hal_nand.c 52 | # %stm32f7xx_hal_nor.c 53 | # %stm32f7xx_hal_pcd.c 54 | # %stm32f7xx_hal_pcd_ex.c 55 | %stm32f7xx_hal_pwr.c 56 | %stm32f7xx_hal_pwr_ex.c 57 | # %stm32f7xx_hal_qspi.c 58 | %stm32f7xx_hal_rcc.c 59 | %stm32f7xx_hal_rcc_ex.c 60 | %stm32f7xx_hal_rng.c 61 | # %stm32f7xx_hal_rtc.c 62 | # %stm32f7xx_hal_rtc_ex.c 63 | %stm32f7xx_hal_sai.c 64 | %stm32f7xx_hal_sai_ex.c 65 | # %stm32f7xx_hal_sd.c 66 | %stm32f7xx_hal_sdram.c 67 | # %stm32f7xx_hal_smartcard.c 68 | # %stm32f7xx_hal_smartcard_ex.c 69 | # %stm32f7xx_hal_spdifrx.c 70 | # %stm32f7xx_hal_spi.c 71 | # %stm32f7xx_hal_sram.c 72 | %stm32f7xx_hal_tim.c 73 | %stm32f7xx_hal_tim_ex.c 74 | %stm32f7xx_hal_uart.c 75 | %stm32f7xx_hal_usart.c 76 | # %stm32f7xx_hal_wwdg.c 77 | %stm32f7xx_ll_fmc.c 78 | %stm32f7xx_ll_sdmmc.c 79 | %stm32f7xx_ll_usb.c 80 | 81 | # BSP 82 | %stm32746g_discovery.c 83 | %stm32746g_discovery_audio.c 84 | # %stm32746g_discovery_camera.c 85 | # %stm32746g_discovery_eeprom.c 86 | %stm32746g_discovery_lcd.c 87 | # %stm32746g_discovery_qspi.c 88 | # %stm32746g_discovery_sd.c 89 | %stm32746g_discovery_sdram.c 90 | %stm32746g_discovery_ts.c 91 | 92 | # USBH 93 | %usbh_core.c 94 | %usbh_ctlreq.c 95 | %usbh_ioreq.c 96 | %usbh_pipes.c 97 | 98 | # FatFS 99 | # %sd_diskio.c 100 | # %sdram_diskio.c 101 | # %sram_diskio.c 102 | %usbh_diskio.c 103 | # %cc932.c 104 | # %cc936.c 105 | # %cc949.c 106 | # %cc950.c 107 | %ccsbcs.c 108 | %syscall.c 109 | # %unicode.c 110 | -------------------------------------------------------------------------------- /src/common/clockconfig.c: -------------------------------------------------------------------------------- 1 | #include "clockconfig.h" 2 | 3 | /** 4 | * @brief System Clock Configuration 5 | * The system Clock is configured as follow : 6 | * System Clock source = PLL (HSE) 7 | * SYSCLK(Hz) = 216000000 8 | * HCLK(Hz) = 216000000 9 | * AHB Prescaler = 1 10 | * APB1 Prescaler = 4 11 | * APB2 Prescaler = 2 12 | * HSE Frequency(Hz) = 25000000 13 | * PLL_M = 25 14 | * PLL_N = 432 15 | * PLL_P = 2 16 | * PLL_Q = 9 17 | * VDD(V) = 3.3 18 | * Main regulator output voltage = Scale1 mode 19 | * Flash Latency(WS) = 7 20 | * @param None 21 | * @retval None 22 | */ 23 | void SystemClock_Config(void) { 24 | RCC_ClkInitTypeDef RCC_ClkInitStruct; 25 | RCC_OscInitTypeDef RCC_OscInitStruct; 26 | RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; 27 | HAL_StatusTypeDef ret = HAL_OK; 28 | 29 | /* Enable HSE Oscillator and activate PLL with HSE as source */ 30 | RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; 31 | RCC_OscInitStruct.HSEState = RCC_HSE_ON; 32 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 33 | RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; 34 | RCC_OscInitStruct.PLL.PLLM = 25; 35 | RCC_OscInitStruct.PLL.PLLN = 432; 36 | RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; 37 | RCC_OscInitStruct.PLL.PLLQ = 9; 38 | 39 | ret = HAL_RCC_OscConfig(&RCC_OscInitStruct); 40 | if (ret != HAL_OK) { 41 | Error_Handler(); 42 | } 43 | 44 | /* Activate the OverDrive to reach the 216 MHz Frequency */ 45 | ret = HAL_PWREx_EnableOverDrive(); 46 | if (ret != HAL_OK) { 47 | Error_Handler(); 48 | } 49 | 50 | /* Select PLLSAI output as USB clock source */ 51 | PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_CLK48; 52 | PeriphClkInitStruct.Clk48ClockSelection = RCC_CLK48SOURCE_PLLSAIP; 53 | PeriphClkInitStruct.PLLSAI.PLLSAIN = 192; 54 | PeriphClkInitStruct.PLLSAI.PLLSAIQ = 4; 55 | PeriphClkInitStruct.PLLSAI.PLLSAIP = RCC_PLLSAIP_DIV4; 56 | ret = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); 57 | if (ret != HAL_OK) { 58 | Error_Handler(); 59 | } 60 | 61 | /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */ 62 | RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | 63 | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); 64 | RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; 65 | RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; 66 | RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; 67 | RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; 68 | 69 | ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7); 70 | if (ret != HAL_OK) { 71 | Error_Handler(); 72 | } 73 | } 74 | 75 | /** 76 | * @brief System Clock Configuration 77 | * The system Clock is configured as follow : 78 | * System Clock source = PLL (HSE) 79 | * SYSCLK(Hz) = 200000000 80 | * HCLK(Hz) = 200000000 81 | * AHB Prescaler = 1 82 | * APB1 Prescaler = 4 83 | * APB2 Prescaler = 2 84 | * HSE Frequency(Hz) = 25000000 85 | * PLL_M = 25 86 | * PLL_N = 400 87 | * PLL_P = 2 88 | * PLLSAI_N = 384 89 | * PLLSAI_P = 8 90 | * VDD(V) = 3.3 91 | * Main regulator output voltage = Scale1 mode 92 | * Flash Latency(WS) = 7 93 | * @param None 94 | * @retval None 95 | */ 96 | void SystemClock_Config_USB(void) { 97 | RCC_ClkInitTypeDef RCC_ClkInitStruct; 98 | RCC_OscInitTypeDef RCC_OscInitStruct; 99 | RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; 100 | 101 | /* Enable HSE Oscillator and activate PLL with HSE as source */ 102 | RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; 103 | RCC_OscInitStruct.HSEState = RCC_HSE_ON; 104 | RCC_OscInitStruct.HSIState = RCC_HSI_OFF; 105 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 106 | RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; 107 | RCC_OscInitStruct.PLL.PLLM = 25; 108 | RCC_OscInitStruct.PLL.PLLN = 400; 109 | RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; 110 | RCC_OscInitStruct.PLL.PLLQ = 8; 111 | if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { 112 | Error_Handler(); 113 | } 114 | 115 | /* Activate the OverDrive to reach the 200 Mhz Frequency */ 116 | if (HAL_PWREx_EnableOverDrive() != HAL_OK) { 117 | Error_Handler(); 118 | } 119 | 120 | /* Select PLLSAI output as USB clock source */ 121 | PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_CLK48; 122 | PeriphClkInitStruct.Clk48ClockSelection = RCC_CLK48SOURCE_PLLSAIP; 123 | PeriphClkInitStruct.PLLSAI.PLLSAIN = 192; 124 | PeriphClkInitStruct.PLLSAI.PLLSAIQ = 4; 125 | PeriphClkInitStruct.PLLSAI.PLLSAIP = RCC_PLLSAIP_DIV4; 126 | if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { 127 | Error_Handler(); 128 | } 129 | 130 | /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 131 | clocks dividers */ 132 | RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | 133 | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); 134 | RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; 135 | RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; 136 | RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; 137 | RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; 138 | if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_6) != HAL_OK) { 139 | Error_Handler(); 140 | } 141 | } 142 | 143 | // Enable instruction & data caches 144 | void CPU_CACHE_Enable(void) { 145 | SCB_EnableICache(); 146 | SCB_EnableDCache(); 147 | } 148 | -------------------------------------------------------------------------------- /src/common/clockconfig.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "stm32f7xx_hal.h" 4 | 5 | void SystemClock_Config(void); 6 | void SystemClock_Config_USB(void); 7 | void CPU_CACHE_Enable(void); 8 | 9 | extern void Error_Handler(); 10 | -------------------------------------------------------------------------------- /src/common/handlers.c: -------------------------------------------------------------------------------- 1 | #include "stm32746g_discovery.h" 2 | #include "stm32f7xx_hal.h" 3 | 4 | void Error_Handler(void) { 5 | BSP_LED_On(LED_GREEN); 6 | while (1) { 7 | } 8 | } 9 | 10 | void SysTick_Handler(void) { 11 | HAL_IncTick(); 12 | } 13 | -------------------------------------------------------------------------------- /src/common/sdram_alloc.c: -------------------------------------------------------------------------------- 1 | #include "sdram_alloc.h" 2 | #include "ct-head/math.h" 3 | 4 | // start of heap = SDRAM base address PLUS length of screen buffer 5 | static uint32_t sdram_heap_ptr = SDRAM_DEVICE_ADDR + 480 * 276 * 4; 6 | static uint32_t sdram_heap_end = SDRAM_DEVICE_ADDR + SDRAM_DEVICE_SIZE; 7 | static uint32_t sdram_zero[32] = {0}; 8 | 9 | void* ct_sdram_malloc(size_t size) { 10 | void* ptr = NULL; 11 | if (sdram_heap_ptr + size < sdram_heap_end) { 12 | ptr = (void*)sdram_heap_ptr; 13 | sdram_heap_ptr += ct_ceil_multiple_pow2(size, 4); 14 | } 15 | return ptr; 16 | } 17 | 18 | void* ct_sdram_calloc(size_t num, size_t size) { 19 | size *= num; 20 | void* ptr = ct_sdram_malloc(size); 21 | if (ptr) { 22 | uint32_t addr = (uint32_t)ptr; 23 | while (size > 32) { 24 | BSP_SDRAM_WriteData(addr, sdram_zero, 32); 25 | addr += 32; 26 | size -= 32; 27 | } 28 | if (size > 0) { 29 | BSP_SDRAM_WriteData(addr, sdram_zero, size); 30 | } 31 | } 32 | return ptr; 33 | } 34 | -------------------------------------------------------------------------------- /src/common/sdram_alloc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "stm32746g_discovery_sdram.h" 4 | 5 | void* ct_sdram_malloc(size_t size); 6 | 7 | void* ct_sdram_calloc(size_t num, size_t size); 8 | -------------------------------------------------------------------------------- /src/ex01/main.c: -------------------------------------------------------------------------------- 1 | #include "stm32746g_discovery.h" 2 | 3 | #include "common/clockconfig.h" 4 | 5 | #define LED_SPEED 100 6 | 7 | volatile int do_blink = 1; 8 | 9 | int main() { 10 | HAL_Init(); 11 | SystemClock_Config(); 12 | BSP_LED_Init(LED_GREEN); 13 | // configure user button in ISR mode 14 | BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_EXTI); 15 | 16 | while (1) { 17 | if (do_blink) { 18 | BSP_LED_On(LED_GREEN); 19 | HAL_Delay(LED_SPEED); 20 | BSP_LED_Off(LED_GREEN); 21 | HAL_Delay(LED_SPEED); 22 | } 23 | } 24 | return 0; 25 | } 26 | 27 | void EXTI15_10_IRQHandler(void) { 28 | HAL_GPIO_EXTI_IRQHandler(KEY_BUTTON_PIN); 29 | } 30 | 31 | void HAL_GPIO_EXTI_Callback(uint16_t pin) { 32 | if (pin == KEY_BUTTON_PIN) { 33 | while (BSP_PB_GetState(BUTTON_KEY) != RESET) 34 | ; 35 | do_blink = !do_blink; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/ex02/main.c: -------------------------------------------------------------------------------- 1 | #include "stm32f7xx_hal.h" 2 | 3 | #include "ct-gui/gui_stm32.h" 4 | #include "ct-head/random.h" 5 | 6 | #include "common/clockconfig.h" 7 | 8 | extern const CTGUI_SpriteSheet ctgui_spritesheet_moogknob50; 9 | 10 | // touch event state 11 | static TS_StateTypeDef rawTouchState; 12 | 13 | static void demoWelcome(); 14 | static void demoScribble(); 15 | static void demoGUI(); 16 | 17 | int main() { 18 | CPU_CACHE_Enable(); 19 | HAL_Init(); 20 | SystemClock_Config(); 21 | BSP_LCD_Init(); 22 | 23 | // only continue if touch screen init ok 24 | if (BSP_TS_Init(BSP_LCD_GetXSize(), BSP_LCD_GetYSize()) == TS_OK) { 25 | BSP_LCD_LayerDefaultInit(LTDC_ACTIVE_LAYER, SDRAM_DEVICE_ADDR); 26 | BSP_LCD_SelectLayer(LTDC_ACTIVE_LAYER); 27 | 28 | // Only enable ONE of the following: 29 | //demoWelcome(); 30 | //demoScribble(); 31 | demoGUI(); 32 | } 33 | return 0; 34 | } 35 | 36 | static void demoWelcome() { 37 | BSP_LCD_SetFont(&CTGUI_FONT); 38 | BSP_LCD_SetBackColor(LCD_COLOR_WHITE); 39 | BSP_LCD_Clear(LCD_COLOR_WHITE); 40 | BSP_LCD_SetTextColor(LCD_COLOR_BLUE); 41 | BSP_LCD_DisplayStringAt(0, BSP_LCD_GetYSize() / 2 - 8, 42 | (uint8_t *)"STM32F746G", CENTER_MODE); 43 | BSP_LCD_SetTextColor(LCD_COLOR_DARKBLUE); 44 | BSP_LCD_DisplayStringAt(0, BSP_LCD_GetYSize() / 2 + 8, (uint8_t *)"Welcome!", 45 | CENTER_MODE); 46 | const float w = BSP_LCD_GetXSize() - 5; 47 | const float h = BSP_LCD_GetYSize() - 5; 48 | 49 | CT_Smush rnd; 50 | // seed random number generator 51 | ct_smush_init(&rnd, 0xdecafbad); 52 | 53 | while (1) { 54 | BSP_LCD_SetTextColor((ct_smush(&rnd) & 0xffffff) | 0xff000000); 55 | BSP_LCD_FillCircle(ct_smush_minmax(&rnd, 5.f, w), 56 | ct_smush_minmax(&rnd, 5.f, h), 4); 57 | HAL_Delay(1); 58 | } 59 | } 60 | 61 | static void demoScribble() { 62 | static uint32_t cols[] = {LCD_COLOR_RED, LCD_COLOR_GREEN, LCD_COLOR_BLUE, 63 | LCD_COLOR_YELLOW, LCD_COLOR_MAGENTA}; 64 | uint16_t width = BSP_LCD_GetXSize(); 65 | uint16_t height = BSP_LCD_GetYSize(); 66 | BSP_LCD_Clear(LCD_COLOR_WHITE); 67 | while (1) { 68 | BSP_TS_GetState(&rawTouchState); 69 | if (rawTouchState.touchDetected) { 70 | for (int i = 0; i < CT_MIN(rawTouchState.touchDetected, 5); i++) { 71 | BSP_LCD_SetTextColor(cols[i]); 72 | BSP_LCD_FillCircle(CT_CLAMP(rawTouchState.touchX[i], 6, width - 6), 73 | CT_CLAMP(rawTouchState.touchY[i], 6, height - 6), 5); 74 | } 75 | } 76 | HAL_Delay(10); 77 | } 78 | } 79 | 80 | static void demoGUI() { 81 | CTGUI gui; 82 | CTGUI_TouchState touchState; 83 | ctgui_init(&gui, 3, &CTGUI_FONT, CTGUI_BG_COLOR, CTGUI_TEXT_COLOR); 84 | ctgui_dialbutton(&gui, 0, "Volume", 135, 100, 0.0f, 0.025f, 85 | &ctgui_spritesheet_moogknob50, NULL); 86 | ctgui_dialbutton(&gui, 1, "Freq", 205, 100, 0.0f, 0.025f, 87 | &ctgui_spritesheet_moogknob50, NULL); 88 | ctgui_dialbutton(&gui, 2, "Filter", 275, 100, 0.0f, 0.025f, 89 | &ctgui_spritesheet_moogknob50, NULL); 90 | 91 | BSP_LCD_Clear(gui.col_bg); 92 | ctgui_force_redraw(&gui); 93 | 94 | while (1) { 95 | BSP_TS_GetState(&rawTouchState); 96 | ctgui_update_touch(&rawTouchState, &touchState); 97 | ctgui_update(&gui, &touchState); 98 | ctgui_draw(&gui); 99 | HAL_Delay(10); 100 | } 101 | } 102 | 103 | // Interrupt handler shared between: 104 | // SD_DETECT pin, USER_KEY button and touch screen interrupt 105 | void EXTI15_10_IRQHandler(void) { 106 | if (__HAL_GPIO_EXTI_GET_IT(SD_DETECT_PIN) != RESET) { 107 | HAL_GPIO_EXTI_IRQHandler(SD_DETECT_PIN | TS_INT_PIN); 108 | } else { 109 | // User button event or Touch screen interrupt 110 | HAL_GPIO_EXTI_IRQHandler(KEY_BUTTON_PIN); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/ex03/main.c: -------------------------------------------------------------------------------- 1 | #include "stm32746g_discovery.h" 2 | #include "stm32f7xx_hal.h" 3 | 4 | #include "common/clockconfig.h" 5 | 6 | #define TIMx TIM3 7 | #define TIMx_CLK_ENABLE() __HAL_RCC_TIM3_CLK_ENABLE() 8 | #define TIMx_IRQn TIM3_IRQn 9 | #define TIMx_IRQHandler TIM3_IRQHandler 10 | 11 | TIM_HandleTypeDef timer; 12 | static uint8_t isBlinking = 1; 13 | 14 | static void initTimer(uint16_t period); 15 | 16 | int main(void) { 17 | CPU_CACHE_Enable(); 18 | HAL_Init(); 19 | SystemClock_Config(); 20 | BSP_LED_Init(LED_GREEN); 21 | BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_EXTI); 22 | 23 | // Start timer w/ 500ms interval (time base = 10kHz) 24 | initTimer(5000); 25 | 26 | while (1) 27 | ; 28 | 29 | return 0; 30 | } 31 | 32 | // Initialize timer w/ 10kHz resolution and given period 33 | static void initTimer(uint16_t period) { 34 | uint32_t prescaler = (uint32_t)((SystemCoreClock / 2) / 10000) - 1; 35 | timer.Instance = TIMx; 36 | timer.Init.Period = period - 1; 37 | timer.Init.Prescaler = prescaler; 38 | timer.Init.ClockDivision = 0; 39 | timer.Init.CounterMode = TIM_COUNTERMODE_UP; 40 | timer.Init.RepetitionCounter = 0; 41 | 42 | if (HAL_TIM_Base_Init(&timer) != HAL_OK) { 43 | Error_Handler(); 44 | } 45 | if (HAL_TIM_Base_Start_IT(&timer) != HAL_OK) { 46 | Error_Handler(); 47 | } 48 | } 49 | 50 | void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim) { 51 | // TIMx Peripheral clock enable 52 | TIMx_CLK_ENABLE(); 53 | // Set the TIMx priority 54 | HAL_NVIC_SetPriority(TIMx_IRQn, 3, 0); 55 | // Enable the TIMx global Interrupt 56 | HAL_NVIC_EnableIRQ(TIMx_IRQn); 57 | } 58 | 59 | // Timer interrupt request. 60 | void TIMx_IRQHandler(void) { 61 | HAL_TIM_IRQHandler(&timer); 62 | } 63 | 64 | // Callback function run whenever timer caused interrupt 65 | void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { 66 | if (isBlinking) { 67 | BSP_LED_Toggle(LED_GREEN); 68 | } 69 | } 70 | 71 | // External line 0 interrupt request. 72 | void EXTI15_10_IRQHandler(void) { 73 | HAL_GPIO_EXTI_IRQHandler(KEY_BUTTON_PIN); 74 | } 75 | 76 | // Callback function run whenever user button has been pressed 77 | void HAL_GPIO_EXTI_Callback(uint16_t pin) { 78 | if (pin == KEY_BUTTON_PIN) { 79 | isBlinking = !isBlinking; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/ex04/main.c: -------------------------------------------------------------------------------- 1 | #include "stm32746g_discovery_audio.h" 2 | 3 | #include "ct-head/math.h" 4 | #include "ct-head/random.h" 5 | 6 | #include "common/clockconfig.h" 7 | 8 | #define VOLUME 50 9 | #define SAMPLE_RATE 44100 10 | 11 | // in bytes... 12 | #define AUDIO_DMA_BUFFER_SIZE 512 13 | // 16bit words 14 | #define AUDIO_DMA_BUFFER_SIZE2 (AUDIO_DMA_BUFFER_SIZE >> 1) 15 | // half buffer size (in 16bit words) 16 | #define AUDIO_DMA_BUFFER_SIZE4 (AUDIO_DMA_BUFFER_SIZE >> 2) 17 | // number of stereo samples (16bit words) 18 | #define AUDIO_DMA_BUFFER_SIZE8 (AUDIO_DMA_BUFFER_SIZE >> 3) 19 | 20 | #define TAU_RATE (CT_TAU / (float)SAMPLE_RATE) 21 | #define HZ_TO_RAD(freq) ((freq)*TAU_RATE) 22 | 23 | typedef struct { 24 | float phase; 25 | float freq; 26 | float mod_phase; 27 | float mod_freq; 28 | float mod_amp; 29 | uint8_t type; 30 | uint8_t mod_type; 31 | } Oscillator; 32 | 33 | extern SAI_HandleTypeDef haudio_out_sai; 34 | static uint8_t audioBuf[AUDIO_DMA_BUFFER_SIZE]; 35 | static CT_XorShift rnd; 36 | 37 | // clang-format off 38 | static Oscillator osc = { 39 | .phase = 0.0f, 40 | .freq = HZ_TO_RAD(220.0f), 41 | .type = 0, 42 | .mod_phase = 0.0f, 43 | .mod_freq = HZ_TO_RAD(0.5f), 44 | .mod_amp = HZ_TO_RAD(110.0f), 45 | .mod_type = 2 46 | }; 47 | // clang-format on 48 | 49 | int main() { 50 | CPU_CACHE_Enable(); 51 | HAL_Init(); 52 | SystemClock_Config(); 53 | ct_xors_init(&rnd); 54 | 55 | if (BSP_AUDIO_OUT_Init(OUTPUT_DEVICE_HEADPHONE, VOLUME, SAMPLE_RATE) != 0) { 56 | Error_Handler(); 57 | } 58 | BSP_AUDIO_OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02); 59 | BSP_AUDIO_OUT_SetVolume(VOLUME); 60 | BSP_AUDIO_OUT_Play((uint16_t *)audioBuf, AUDIO_DMA_BUFFER_SIZE); 61 | 62 | while (1) { 63 | } 64 | 65 | return 0; 66 | } 67 | 68 | static float compute_osc(size_t type, float phase) { 69 | switch (type) { 70 | case 0: 71 | return sinf(phase); 72 | case 1: // saw 73 | return ct_mapf(phase, 0.0f, CT_TAU, 1.f, -1.f); 74 | case 2: // square 75 | return phase < CT_PI ? -1.0f : 1.0f; 76 | case 3: // triangle 77 | if (phase < CT_PI) { 78 | return ct_mapf(phase, 0.0f, CT_PI, -1.f, 1.f); 79 | } else { 80 | return ct_mapf(phase, CT_PI, CT_TAU, 1.f, -1.f); 81 | } 82 | case 4: // saw + sin 83 | if (phase < CT_PI) { 84 | return ct_mapf(phase, 0.0f, CT_PI, -1.f, 1.f); 85 | } else { 86 | return sinf(phase); 87 | } 88 | case 5: 89 | return ct_xors_normpos(&rnd); 90 | } 91 | return 0; 92 | } 93 | 94 | static void renderAudio(int16_t *ptr) { 95 | size_t len = AUDIO_DMA_BUFFER_SIZE8; 96 | int16_t y; 97 | float f; 98 | while (len--) { 99 | osc.mod_phase += osc.mod_freq; 100 | if (osc.mod_phase >= CT_TAU) { 101 | osc.mod_phase -= CT_TAU; 102 | } 103 | f = osc.freq + osc.mod_amp * compute_osc(osc.mod_type, osc.mod_phase); 104 | osc.phase = ct_wrapf(osc.phase + f, CT_TAU); 105 | y = ct_clamp16(compute_osc(osc.type, osc.phase) * 32767.f); 106 | *ptr++ = y; 107 | *ptr++ = y; 108 | } 109 | } 110 | 111 | void AUDIO_OUT_SAIx_DMAx_IRQHandler(void) { 112 | HAL_DMA_IRQHandler(haudio_out_sai.hdmatx); 113 | } 114 | 115 | void BSP_AUDIO_OUT_HalfTransfer_CallBack(void) { 116 | renderAudio((int16_t *)&audioBuf[0]); 117 | } 118 | 119 | void BSP_AUDIO_OUT_TransferComplete_CallBack(void) { 120 | renderAudio((int16_t *)&audioBuf[0] + AUDIO_DMA_BUFFER_SIZE4); 121 | } 122 | 123 | void BSP_AUDIO_OUT_Error_CallBack(void) { 124 | Error_Handler(); 125 | } 126 | -------------------------------------------------------------------------------- /src/ex05/ffconf.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------/ 2 | / FatFs - FAT file system module configuration file R0.11 (C)ChaN, 2015 3 | /---------------------------------------------------------------------------*/ 4 | 5 | #ifndef _FFCONF 6 | #define _FFCONF 32020 /* Revision ID */ 7 | 8 | /*-----------------------------------------------------------------------------/ 9 | / Additional user header to be used 10 | /-----------------------------------------------------------------------------*/ 11 | #include "stm32f7xx_hal.h" 12 | 13 | /* If uSD is used, then include the uSD BSP header file. 14 | Replace 'stm32xxx' with your EVAL board name, ex: stm324x9i_eval_sd.h 15 | */ 16 | // #include "stm32xxx_eval_sd.h" 17 | 18 | /* If USB Host MSC is used, then need to include the USBH and UBSH MSC core header files */ 19 | #include "usbh_core.h" 20 | #include "usbh_msc.h" 21 | /* hUSBH to be updated with the USBH handle defined in the application code */ 22 | #define HOST_HANDLE hUSBH 23 | 24 | /*---------------------------------------------------------------------------/ 25 | / Functions and Buffer Configurations 26 | /---------------------------------------------------------------------------*/ 27 | 28 | #define _FS_TINY 0 /* 0:Normal or 1:Tiny */ 29 | /* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) 30 | / At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS 31 | / bytes. Instead of private sector buffer eliminated from the file object, 32 | / common sector buffer in the file system object (FATFS) is used for the file 33 | / data transfer. */ 34 | 35 | #define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */ 36 | /* This option switches read-only configuration. (0:Read/Write or 1:Read-only) 37 | / Read-only configuration removes writing API functions, f_write(), f_sync(), 38 | / f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() 39 | / and optional writing functions as well. */ 40 | 41 | #define _FS_MINIMIZE 0 /* 0 to 3 */ 42 | /* This option defines minimization level to remove some basic API functions. 43 | / 44 | / 0: All basic functions are enabled. 45 | / 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_chmod(), f_utime(), 46 | / f_truncate() and f_rename() function are removed. 47 | / 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. 48 | / 3: f_lseek() function is removed in addition to 2. */ 49 | 50 | #define _USE_STRFUNC 2 /* 0:Disable or 1-2:Enable */ 51 | /* This option switches string functions, f_gets(), f_putc(), f_puts() and 52 | / f_printf(). 53 | / 54 | / 0: Disable string functions. 55 | / 1: Enable without LF-CRLF conversion. 56 | / 2: Enable with LF-CRLF conversion. */ 57 | 58 | #define _USE_FIND 0 59 | /* This option switches filtered directory read feature and related functions, 60 | / f_findfirst() and f_findnext(). (0:Disable or 1:Enable) */ 61 | 62 | #define _USE_MKFS 1 63 | /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ 64 | 65 | #define _USE_FASTSEEK 1 66 | /* This option switches fast seek feature. (0:Disable or 1:Enable) */ 67 | 68 | #define _USE_LABEL 0 69 | /* This option switches volume label functions, f_getlabel() and f_setlabel(). 70 | / (0:Disable or 1:Enable) */ 71 | 72 | #define _USE_FORWARD 0 73 | /* This option switches f_forward() function. (0:Disable or 1:Enable) 74 | / To enable it, also _FS_TINY need to be set to 1. */ 75 | 76 | #define _USE_BUFF_WO_ALIGNMENT 0 77 | /* This option is available only for usbh diskio interface and allow to disable 78 | / the management of the unaligned buffer. 79 | / When STM32 USB OTG HS or FS IP is used with internal DMA enabled, this define 80 | / must be set to 0 to align data into 32bits through an internal scratch buffer 81 | / before being processed by the DMA . Otherwise (DMA not used), this define must 82 | / be set to 1 to avoid Data alignment and improve the performance. 83 | / Please note that if _USE_BUFF_WO_ALIGNMENT is set to 1 and an unaligned 32bits 84 | / buffer is forwarded to the FatFs Write/Read functions, an error will be returned. 85 | / (0: default value or 1: unaligned buffer return an error). */ 86 | 87 | /*---------------------------------------------------------------------------/ 88 | / Locale and Namespace Configurations 89 | /---------------------------------------------------------------------------*/ 90 | 91 | #define _CODE_PAGE 1252 92 | /* This option specifies the OEM code page to be used on the target system. 93 | / Incorrect setting of the code page can cause a file open failure. 94 | / 95 | / 932 - Japanese Shift_JIS (DBCS, OEM, Windows) 96 | / 936 - Simplified Chinese GBK (DBCS, OEM, Windows) 97 | / 949 - Korean (DBCS, OEM, Windows) 98 | / 950 - Traditional Chinese Big5 (DBCS, OEM, Windows) 99 | / 1250 - Central Europe (Windows) 100 | / 1251 - Cyrillic (Windows) 101 | / 1252 - Latin 1 (Windows) 102 | / 1253 - Greek (Windows) 103 | / 1254 - Turkish (Windows) 104 | / 1255 - Hebrew (Windows) 105 | / 1256 - Arabic (Windows) 106 | / 1257 - Baltic (Windows) 107 | / 1258 - Vietnam (OEM, Windows) 108 | / 437 - U.S. (OEM) 109 | / 720 - Arabic (OEM) 110 | / 737 - Greek (OEM) 111 | / 775 - Baltic (OEM) 112 | / 850 - Multilingual Latin 1 (OEM) 113 | / 858 - Multilingual Latin 1 + Euro (OEM) 114 | / 852 - Latin 2 (OEM) 115 | / 855 - Cyrillic (OEM) 116 | / 866 - Russian (OEM) 117 | / 857 - Turkish (OEM) 118 | / 862 - Hebrew (OEM) 119 | / 874 - Thai (OEM, Windows) 120 | / 1 - ASCII (No extended character. Valid for only non-LFN configuration.) */ 121 | 122 | #define _USE_LFN 3 123 | #define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ 124 | /* The _USE_LFN option switches the LFN feature. 125 | / 126 | / 0: Disable LFN feature. _MAX_LFN has no effect. 127 | / 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. 128 | / 2: Enable LFN with dynamic working buffer on the STACK. 129 | / 3: Enable LFN with dynamic working buffer on the HEAP. 130 | / 131 | / When enable the LFN feature, Unicode handling functions (option/unicode.c) must 132 | / be added to the project. The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. 133 | / When use stack for the working buffer, take care on stack overflow. When use heap 134 | / memory for the working buffer, memory management functions, ff_memalloc() and 135 | / ff_memfree(), must be added to the project. */ 136 | 137 | #define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */ 138 | /* This option switches character encoding on the API. (0:ANSI/OEM or 1:Unicode) 139 | / To use Unicode string for the path name, enable LFN feature and set _LFN_UNICODE 140 | / to 1. This option also affects behavior of string I/O functions. */ 141 | 142 | #define _STRF_ENCODE 3 143 | /* When _LFN_UNICODE is 1, this option selects the character encoding on the file to 144 | / be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf(). 145 | / 146 | / 0: ANSI/OEM 147 | / 1: UTF-16LE 148 | / 2: UTF-16BE 149 | / 3: UTF-8 150 | / 151 | / When _LFN_UNICODE is 0, this option has no effect. */ 152 | 153 | #define _FS_RPATH 0 154 | /* This option configures relative path feature. 155 | / 156 | / 0: Disable relative path feature and remove related functions. 157 | / 1: Enable relative path feature. f_chdir() and f_chdrive() are available. 158 | / 2: f_getcwd() function is available in addition to 1. 159 | / 160 | / Note that directory items read via f_readdir() are affected by this option. */ 161 | 162 | /*---------------------------------------------------------------------------/ 163 | / Drive/Volume Configurations 164 | /---------------------------------------------------------------------------*/ 165 | 166 | #define _VOLUMES 1 167 | /* Number of volumes (logical drives) to be used. */ 168 | 169 | #define _STR_VOLUME_ID 0 170 | #define _VOLUME_STRS "RAM", "NAND", "CF", "SD1", "SD2", "USB1", "USB2", "USB3" 171 | /* _STR_VOLUME_ID option switches string volume ID feature. 172 | / When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive 173 | / number in the path name. _VOLUME_STRS defines the drive ID strings for each 174 | / logical drives. Number of items must be equal to _VOLUMES. Valid characters for 175 | / the drive ID strings are: A-Z and 0-9. */ 176 | 177 | #define _MULTI_PARTITION 0 178 | /* This option switches multi-partition feature. By default (0), each logical drive 179 | / number is bound to the same physical drive number and only an FAT volume found on 180 | / the physical drive will be mounted. When multi-partition feature is enabled (1), 181 | / each logical drive number is bound to arbitrary physical drive and partition 182 | / listed in the VolToPart[]. Also f_fdisk() funciton will be available. */ 183 | 184 | #define _MIN_SS 512 185 | #define _MAX_SS 512 186 | /* These options configure the range of sector size to be supported. (512, 1024, 187 | / 2048 or 4096) Always set both 512 for most systems, all type of memory cards and 188 | / harddisk. But a larger value may be required for on-board flash memory and some 189 | / type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured 190 | / to variable sector size and GET_SECTOR_SIZE command must be implemented to the 191 | / disk_ioctl() function. */ 192 | 193 | #define _USE_TRIM 0 194 | /* This option switches ATA-TRIM feature. (0:Disable or 1:Enable) 195 | / To enable Trim feature, also CTRL_TRIM command should be implemented to the 196 | / disk_ioctl() function. */ 197 | 198 | #define _FS_NOFSINFO 0 199 | /* If you need to know correct free space on the FAT32 volume, set bit 0 of this 200 | / option, and f_getfree() function at first time after volume mount will force 201 | / a full FAT scan. Bit 1 controls the use of last allocated cluster number. 202 | / 203 | / bit0=0: Use free cluster count in the FSINFO if available. 204 | / bit0=1: Do not trust free cluster count in the FSINFO. 205 | / bit1=0: Use last allocated cluster number in the FSINFO if available. 206 | / bit1=1: Do not trust last allocated cluster number in the FSINFO. 207 | */ 208 | 209 | /*---------------------------------------------------------------------------/ 210 | / System Configurations 211 | /---------------------------------------------------------------------------*/ 212 | 213 | #define _FS_NORTC 1 214 | #define _NORTC_MON 1 215 | #define _NORTC_MDAY 1 216 | #define _NORTC_YEAR 2016 217 | /* The _FS_NORTC option switches timestamp feature. If the system does not have 218 | / an RTC function or valid timestamp is not needed, set _FS_NORTC to 1 to disable 219 | / the timestamp feature. All objects modified by FatFs will have a fixed timestamp 220 | / defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR. 221 | / When timestamp feature is enabled (_FS_NORTC == 0), get_fattime() function need 222 | / to be added to the project to read current time form RTC. _NORTC_MON, 223 | / _NORTC_MDAY and _NORTC_YEAR have no effect. 224 | / These options have no effect at read-only configuration (_FS_READONLY == 1). */ 225 | 226 | #define _FS_LOCK 2 227 | /* The _FS_LOCK option switches file lock feature to control duplicated file open 228 | / and illegal operation to open objects. This option must be 0 when _FS_READONLY 229 | / is 1. 230 | / 231 | / 0: Disable file lock feature. To avoid volume corruption, application program 232 | / should avoid illegal open, remove and rename to the open objects. 233 | / >0: Enable file lock feature. The value defines how many files/sub-directories 234 | / can be opened simultaneously under file lock control. Note that the file 235 | / lock feature is independent of re-entrancy. */ 236 | 237 | #define _FS_REENTRANT 0 238 | #define _FS_TIMEOUT 1000 239 | #define _SYNC_t osSemaphoreId 240 | /* The _FS_REENTRANT option switches the re-entrancy (thread safe) of the FatFs 241 | / module itself. Note that regardless of this option, file access to different 242 | / volume is always re-entrant and volume control functions, f_mount(), f_mkfs() 243 | / and f_fdisk() function, are always not re-entrant. Only file/directory access 244 | / to the same volume is under control of this feature. 245 | / 246 | / 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect. 247 | / 1: Enable re-entrancy. Also user provided synchronization handlers, 248 | / ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() 249 | / function, must be added to the project. Samples are available in 250 | / option/syscall.c. 251 | / 252 | / The _FS_TIMEOUT defines timeout period in unit of time tick. 253 | / The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, 254 | / SemaphoreHandle_t and etc.. */ 255 | 256 | #define _WORD_ACCESS 0 257 | /* The _WORD_ACCESS option is an only platform dependent option. It defines 258 | / which access method is used to the word data on the FAT volume. 259 | / 260 | / 0: Byte-by-byte access. Always compatible with all platforms. 261 | / 1: Word access. Do not choose this unless under both the following conditions. 262 | / 263 | / * Address misaligned memory access is always allowed to ALL instructions. 264 | / * Byte order on the memory is little-endian. 265 | / 266 | / If it is the case, _WORD_ACCESS can also be set to 1 to reduce code size. 267 | / Following table shows allowable settings of some processor types. 268 | / 269 | / ARM7TDMI 0 ColdFire 0 V850E 0 270 | / Cortex-M3 0 Z80 0/1 V850ES 0/1 271 | / Cortex-M0 0 x86 0/1 TLCS-870 0/1 272 | / AVR 0/1 RX600(LE) 0/1 TLCS-900 0/1 273 | / AVR32 0 RL78 0 R32C 0 274 | / PIC18 0/1 SH-2 0 M16C 0/1 275 | / PIC24 0 H8S 0 MSP430 0 276 | / PIC32 0 H8/300H 0 8051 0/1 277 | */ 278 | 279 | #endif /* _FFCONF */ 280 | -------------------------------------------------------------------------------- /src/ex05/main.c: -------------------------------------------------------------------------------- 1 | #include "stm32746g_discovery.h" 2 | #include "stm32746g_discovery_audio.h" 3 | #include "stm32f7xx_hal.h" 4 | 5 | #include "ff.h" 6 | #include "ff_gen_drv.h" 7 | #include "usbh_diskio.h" 8 | 9 | #include "common/clockconfig.h" 10 | #include "wavfile.h" 11 | 12 | #define VOLUME 70 13 | 14 | #define AUDIO_DMA_BUFFER_SIZE 4096 15 | #define AUDIO_DMA_BUFFER_SIZE2 (AUDIO_DMA_BUFFER_SIZE >> 1) 16 | 17 | #define WAVEFILENAME "0:sound.wav" 18 | 19 | typedef enum { 20 | BUFFER_OFFSET_NONE = 0, 21 | BUFFER_OFFSET_HALF, 22 | BUFFER_OFFSET_FULL 23 | } DMABufferState; 24 | 25 | extern HCD_HandleTypeDef hhcd; 26 | extern USBH_HandleTypeDef hUSBH; 27 | extern SAI_HandleTypeDef haudio_out_sai; 28 | 29 | static uint8_t audio_buf[AUDIO_DMA_BUFFER_SIZE]; 30 | static DMABufferState dma_state = BUFFER_OFFSET_NONE; 31 | 32 | FIL audio_file; 33 | CTSS_WavHeader audio_format; 34 | UINT bytes_read; 35 | 36 | static char usb_drive_path[4]; 37 | 38 | static void process_usbh_message(USBH_HandleTypeDef *host, uint8_t msg); 39 | static void start_playback(); 40 | static void stop_playback(); 41 | static void play_wav_file(); 42 | 43 | int main() { 44 | CPU_CACHE_Enable(); 45 | HAL_Init(); 46 | SystemClock_Config(); 47 | BSP_LED_Init(LED_GREEN); 48 | if (FATFS_LinkDriver(&USBH_Driver, usb_drive_path) == 0) { 49 | USBH_Init(&hUSBH, process_usbh_message, 0); 50 | USBH_RegisterClass(&hUSBH, USBH_MSC_CLASS); 51 | USBH_Start(&hUSBH); 52 | while (1) { 53 | USBH_Process(&hUSBH); 54 | } 55 | } else { 56 | Error_Handler(); 57 | } 58 | return 0; 59 | } 60 | 61 | static void process_usbh_message(USBH_HandleTypeDef *host, uint8_t msg) { 62 | switch (msg) { 63 | case HOST_USER_SELECT_CONFIGURATION: 64 | break; 65 | 66 | case HOST_USER_DISCONNECTION: 67 | f_mount(NULL, (TCHAR const *)"", 0); 68 | stop_playback(); 69 | break; 70 | 71 | case HOST_USER_CLASS_ACTIVE: 72 | start_playback(); 73 | break; 74 | 75 | case HOST_USER_CONNECTION: 76 | break; 77 | 78 | default: 79 | break; 80 | } 81 | } 82 | 83 | static void start_playback() { 84 | if (f_open(&audio_file, WAVEFILENAME, FA_READ) == FR_OK) { 85 | f_read(&audio_file, &audio_format, sizeof(CTSS_WavHeader), &bytes_read); 86 | play_wav_file(); 87 | } else { 88 | Error_Handler(); 89 | } 90 | } 91 | 92 | static void play_wav_file() { 93 | BSP_AUDIO_OUT_Init(OUTPUT_DEVICE_HEADPHONE, VOLUME, audio_format.sampleRate); 94 | BSP_AUDIO_OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02); 95 | f_lseek(&audio_file, 0); 96 | f_read(&audio_file, audio_buf, AUDIO_DMA_BUFFER_SIZE, &bytes_read); 97 | uint32_t samples_remaining = audio_format.riffLength - bytes_read; 98 | BSP_AUDIO_OUT_Play((uint16_t *)audio_buf, AUDIO_DMA_BUFFER_SIZE); 99 | uint32_t err = 0; 100 | while (!err) { 101 | bytes_read = 0; 102 | if (dma_state == BUFFER_OFFSET_HALF) { 103 | err = (f_read(&audio_file, audio_buf, AUDIO_DMA_BUFFER_SIZE2, 104 | &bytes_read) != FR_OK); 105 | dma_state = BUFFER_OFFSET_NONE; 106 | } else if (dma_state == BUFFER_OFFSET_FULL) { 107 | err = (f_read(&audio_file, &audio_buf[AUDIO_DMA_BUFFER_SIZE2], 108 | AUDIO_DMA_BUFFER_SIZE2, &bytes_read) != FR_OK); 109 | dma_state = BUFFER_OFFSET_NONE; 110 | } 111 | if (!err) { 112 | if (samples_remaining > AUDIO_DMA_BUFFER_SIZE2) { 113 | samples_remaining -= bytes_read; 114 | } else { 115 | f_lseek(&audio_file, 0); 116 | samples_remaining = audio_format.riffLength - bytes_read; 117 | } 118 | BSP_LED_Toggle(LED_GREEN); 119 | } 120 | } 121 | stop_playback(); 122 | } 123 | 124 | static void stop_playback() { 125 | BSP_AUDIO_OUT_Stop(CODEC_PDWN_HW); 126 | } 127 | 128 | void OTG_FS_IRQHandler(void) { 129 | HAL_HCD_IRQHandler(&hhcd); 130 | } 131 | 132 | void AUDIO_OUT_SAIx_DMAx_IRQHandler(void) { 133 | HAL_DMA_IRQHandler(haudio_out_sai.hdmatx); 134 | } 135 | 136 | void BSP_AUDIO_OUT_HalfTransfer_CallBack(void) { 137 | dma_state = BUFFER_OFFSET_HALF; 138 | } 139 | 140 | void BSP_AUDIO_OUT_TransferComplete_CallBack(void) { 141 | dma_state = BUFFER_OFFSET_FULL; 142 | } 143 | 144 | void BSP_AUDIO_OUT_Error_CallBack(void) { 145 | Error_Handler(); 146 | } 147 | -------------------------------------------------------------------------------- /src/ex05/usbh_conf.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file USB_Host/MSC_Standalone/Src/usbh_conf.c 4 | * @author MCD Application Team 5 | * @version V1.0.3 6 | * @date 22-April-2016 7 | * @brief USB Host configuration file. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | *