Mercurial > hg > beaglert
changeset 67:472e892c6e41
Merge newapi into default
author | Andrew McPherson <a.mcpherson@qmul.ac.uk> |
---|---|
date | Fri, 17 Jul 2015 15:28:18 +0100 |
parents | 0d80ff9e2227 (current diff) 74a44c3d91f0 (diff) |
children | 59edd5780fef |
files | include/RTAudio.h include/render.h projects/basic_sensor/main.cpp projects/basic_sensor/render.cpp pru_rtaudio.bin pru_rtaudio.p |
diffstat | 65 files changed, 6023 insertions(+), 1222 deletions(-) [+] |
line wrap: on
line diff
--- a/.cproject Sun Feb 08 00:20:01 2015 +0000 +++ b/.cproject Fri Jul 17 15:28:18 2015 +0100 @@ -5,16 +5,16 @@ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.exe.debug.528876549" moduleId="org.eclipse.cdt.core.settings" name="Debug"> <externalSettings/> <extensions> - <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/> <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/> <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> + <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/> </extensions> </storageModule> <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.debug.528876549" name="Debug" parent="cdt.managedbuild.config.gnu.exe.debug"> + <configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.debug.528876549" name="Debug" parent="cdt.managedbuild.config.gnu.exe.debug" postannouncebuildStep="Kills the process running on the BeagleBone (if any) and copies the new binary to the BeagleBone in beaglert/" postbuildStep="ssh root@192.168.7.2 "kill -s 2 \`pidof ${BuildArtifactFileName}\` 2>/dev/null; sleep 0.5; scp host:${PWD}/${BuildArtifactFileName} ~/beaglert/ && echo 'done copying\n' | wall || echo 'error'|wall""> <folderInfo id="cdt.managedbuild.config.gnu.exe.debug.528876549." name="/" resourcePath=""> <toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.681872250" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.debug"> <targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.debug.295375065" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.debug"/> @@ -24,34 +24,53 @@ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name="Release"/> </outputEntries> </builder> - <tool id="cdt.managedbuild.tool.gnu.archiver.base.1542380883" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/> - <tool command="arm-linux-gnueabihf-g++" id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.2030825480" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug"> - <option id="gnu.cpp.compiler.exe.debug.option.optimization.level.2006448218" name="Optimization Level" superClass="gnu.cpp.compiler.exe.debug.option.optimization.level" value="gnu.cpp.compiler.optimization.level.more" valueType="enumerated"/> + <tool command="arm-linux-gnueabihf-g++ " id="cdt.managedbuild.tool.gnu.archiver.base.1542380883" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/> + <tool command="arm-linux-gnueabihf-g++ " id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.2030825480" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug"> + <option id="gnu.cpp.compiler.exe.debug.option.optimization.level.2006448218" name="Optimization Level" superClass="gnu.cpp.compiler.exe.debug.option.optimization.level" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/> <option id="gnu.cpp.compiler.exe.debug.option.debugging.level.1267706246" name="Debug Level" superClass="gnu.cpp.compiler.exe.debug.option.debugging.level" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.include.paths.2031219124" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath"> + <listOptionValue builtIn="false" value="/usr/xenomai/include"/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/xenomai/include"/> + <listOptionValue builtIn="false" value="/import/teaching/ECS732/arm-gcc/arm-linux-gnueabihf/include"/> + <listOptionValue builtIn="false" value="/import/teaching/ECS732/arm-gcc/arm-linux-gnueabihf/include/xenomai/include"/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/ne10"/> + <listOptionValue builtIn="false" value=""${workspace_loc:/BeagleRT/include}""/> </option> <option id="gnu.cpp.compiler.option.other.other.1516989263" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" value="-c -fmessage-length=0 -Wpointer-arith -Wunused-result -D_GNU_SOURCE -D_REENTRANT -D__XENO__" valueType="string"/> <option id="gnu.cpp.compiler.option.warnings.allwarn.1392851614" name="All warnings (-Wall)" superClass="gnu.cpp.compiler.option.warnings.allwarn" value="true" valueType="boolean"/> + <option id="gnu.cpp.compiler.option.dialect.std.904910934" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/> <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1166892316" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> </tool> <tool command="arm-linux-gnueabihf-gcc" id="cdt.managedbuild.tool.gnu.c.compiler.exe.debug.917207395" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.debug"> - <option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.exe.debug.option.optimization.level.326761664" name="Optimization Level" superClass="gnu.c.compiler.exe.debug.option.optimization.level" value="gnu.c.optimization.level.more" valueType="enumerated"/> + <option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.exe.debug.option.optimization.level.326761664" name="Optimization Level" superClass="gnu.c.compiler.exe.debug.option.optimization.level" value="gnu.c.optimization.level.none" valueType="enumerated"/> <option id="gnu.c.compiler.exe.debug.option.debugging.level.471732683" name="Debug Level" superClass="gnu.c.compiler.exe.debug.option.debugging.level" value="gnu.c.debugging.level.max" valueType="enumerated"/> <option id="gnu.c.compiler.option.include.paths.358825414" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath"> + <listOptionValue builtIn="false" value="/usr/xenomai/include"/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/xenomai/include"/> + <listOptionValue builtIn="false" value="/import/teaching/ECS732/arm-gcc/arm-linux-gnueabihf/include"/> + <listOptionValue builtIn="false" value="/import/teaching/ECS732/arm-gcc/arm-linux-gnueabihf/include/xenomai/include"/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/ne10"/> + <listOptionValue builtIn="false" value=""${workspace_loc:/BeagleRT/include}""/> </option> <option id="gnu.c.compiler.option.misc.other.835792865" name="Other flags" superClass="gnu.c.compiler.option.misc.other" value="-c -fmessage-length=0 -Wpointer-arith -Wunused-result -D_GNU_SOURCE -D_REENTRANT -D__XENO__ -std=gnu99" valueType="string"/> <option id="gnu.c.compiler.option.warnings.allwarn.1145989346" name="All warnings (-Wall)" superClass="gnu.c.compiler.option.warnings.allwarn" value="true" valueType="boolean"/> <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.308014221" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> </tool> - <tool id="cdt.managedbuild.tool.gnu.c.linker.exe.debug.214461086" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.debug"/> - <tool command="arm-linux-gnueabihf-g++" id="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.1669966018" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug"> - <option id="gnu.cpp.link.option.paths.462980690" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths"/> - <option id="gnu.cpp.link.option.libs.139390951" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs"/> - <option id="gnu.cpp.link.option.flags.2096887116" name="Linker flags" superClass="gnu.cpp.link.option.flags" value="-pthread -rdynamics" valueType="string"/> + <tool command="arm-linux-gnueabihf-g++ " id="cdt.managedbuild.tool.gnu.c.linker.exe.debug.214461086" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.debug"/> + <tool command="arm-linux-gnueabihf-g++ " commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" id="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.1669966018" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug"> + <option id="gnu.cpp.link.option.paths.462980690" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" valueType="libPaths"> + <listOptionValue builtIn="false" value="/usr/xenomai/lib"/> + <listOptionValue builtIn="false" value="/usr/local/linaro/arm-linux-gnueabihf/include/xenomai/lib"/> + <listOptionValue builtIn="false" value="/import/teaching/ECS732/arm-gcc/arm-linux-gnueabihf/lib"/> + <listOptionValue builtIn="false" value="/usr/lib/arm-linux-gnueabihf"/> + <listOptionValue builtIn="false" value="/import/teaching/ECS732/arm-gcc/arm-linux-gnueabihf/lib/xenomai"/> + </option> + <option id="gnu.cpp.link.option.libs.139390951" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" valueType="libs"> + <listOptionValue builtIn="false" value="rt"/> + <listOptionValue builtIn="false" value="native"/> + <listOptionValue builtIn="false" value="xenomai"/> + </option> + <option id="gnu.cpp.link.option.flags.2096887116" name="Linker flags" superClass="gnu.cpp.link.option.flags" value="-pthread -rdynamic" valueType="string"/> <option id="gnu.cpp.link.option.userobjs.537608578" name="Other objects" superClass="gnu.cpp.link.option.userobjs" valueType="userObjs"> <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/libprussdrv.a}""/> <listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/libNE10.a}""/> @@ -63,17 +82,21 @@ </tool> <tool command="arm-linux-gnueabihf-as" id="cdt.managedbuild.tool.gnu.assembler.exe.debug.37270610" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.debug"> <option id="gnu.both.asm.option.include.paths.1403814918" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath"> + <listOptionValue builtIn="false" value="/import/teaching/ECS732/arm-gcc/arm-linux-gnueabihf/include/xenomai/include"/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/xenomai/include"/> + <listOptionValue builtIn="false" value="/import/teaching/ECS732/arm-gcc/arm-linux-gnueabihf/include"/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/ne10"/> + <listOptionValue builtIn="false" value=""${workspace_loc:/BeagleRT/include}""/> </option> <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1788972942" superClass="cdt.managedbuild.tool.gnu.assembler.input"/> </tool> </toolChain> </folderInfo> <sourceEntries> - <entry excluding="audio_routines_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="core"/> + <entry excluding="default_main.cpp|audio_routines_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="core"/> <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="include"/> - <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/basic_analog_output"/> + <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/basic"/> + <entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="source"/> </sourceEntries> </configuration> </storageModule> @@ -83,45 +106,57 @@ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.exe.release.1521194538" moduleId="org.eclipse.cdt.core.settings" name="Release"> <externalSettings/> <extensions> - <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/> <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/> <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> + <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/> </extensions> </storageModule> <storageModule moduleId="cdtBuildSystem" version="4.0.0"> - <configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.release.1521194538" name="Release" parent="cdt.managedbuild.config.gnu.exe.release"> + <configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.release.1521194538" name="Release" parent="cdt.managedbuild.config.gnu.exe.release" postannouncebuildStep="Stopping process on BBB and copying new binary" postbuildStep="ssh root@192.168.7.2 "kill -s 2 \`pidof ${BuildArtifactFileName}\` 2>/dev/null"; scp ${BuildArtifactFilePrefix}${BuildArtifactFileName} root@192.168.7.2:~/beaglert/ ; echo 'done copying' | wall"> <folderInfo id="cdt.managedbuild.config.gnu.exe.release.1521194538." name="/" resourcePath=""> <toolChain id="cdt.managedbuild.toolchain.gnu.exe.release.1612059942" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.release"> <targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.release.908983575" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.release"/> <builder buildPath="${workspace_loc:/BBB_audio+input/Release}" id="cdt.managedbuild.target.gnu.builder.exe.release.511190290" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.exe.release"/> - <tool id="cdt.managedbuild.tool.gnu.archiver.base.810674388" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/> - <tool command="arm-linux-gnueabihf-g++" id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.163790048" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release"> + <tool command="arm-linux-gnueabihf-g++ " id="cdt.managedbuild.tool.gnu.archiver.base.810674388" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/> + <tool command="arm-linux-gnueabihf-g++ " commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.163790048" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release"> <option id="gnu.cpp.compiler.exe.release.option.optimization.level.2031085570" name="Optimization Level" superClass="gnu.cpp.compiler.exe.release.option.optimization.level" value="gnu.cpp.compiler.optimization.level.more" valueType="enumerated"/> <option id="gnu.cpp.compiler.exe.release.option.debugging.level.701035863" name="Debug Level" superClass="gnu.cpp.compiler.exe.release.option.debugging.level" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/> <option id="gnu.cpp.compiler.option.include.paths.823255770" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath"> - <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include"/> + <listOptionValue builtIn="false" value="/usr/xenomai/include"/> + <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/xenomai/include"/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/ne10"/> - <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/xenomai/include"/> + <listOptionValue builtIn="false" value=""${workspace_loc:/BeagleRT/include}""/> </option> + <option id="gnu.cpp.compiler.option.dialect.std.776548502" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" value="gnu.cpp.compiler.dialect.default" valueType="enumerated"/> + <option id="gnu.cpp.compiler.option.other.other.398422461" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" value="-c -fmessage-length=0 -U_FORTIFY_SOURCE" valueType="string"/> <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.601059736" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> </tool> <tool command="arm-linux-gnueabihf-gcc" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" id="cdt.managedbuild.tool.gnu.c.compiler.exe.release.1302828968" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.release"> <option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.exe.release.option.optimization.level.1118673208" name="Optimization Level" superClass="gnu.c.compiler.exe.release.option.optimization.level" value="gnu.c.optimization.level.more" valueType="enumerated"/> <option id="gnu.c.compiler.exe.release.option.debugging.level.1329456558" name="Debug Level" superClass="gnu.c.compiler.exe.release.option.debugging.level" value="gnu.c.debugging.level.none" valueType="enumerated"/> <option id="gnu.c.compiler.option.include.paths.1269113471" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath"> - <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include"/> + <listOptionValue builtIn="false" value="/usr/xenomai/include"/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/xenomai/include"/> + <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/include/ne10"/> + <listOptionValue builtIn="false" value=""${workspace_loc:/BeagleRT/include}""/> + </option> + <option id="gnu.c.compiler.option.include.files.40806287" name="Include files (-include)" superClass="gnu.c.compiler.option.include.files"/> + <option id="gnu.c.compiler.option.preprocessor.undef.symbol.980935416" name="Undefined symbols (-U)" superClass="gnu.c.compiler.option.preprocessor.undef.symbol" valueType="undefDefinedSymbols"> + <listOptionValue builtIn="false" value="_FORTIFY_SOURCE"/> </option> <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.574072828" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> </tool> - <tool id="cdt.managedbuild.tool.gnu.c.linker.exe.release.281634187" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.release"/> - <tool command="arm-linux-gnueabihf-g++" id="cdt.managedbuild.tool.gnu.cpp.linker.exe.release.929570421" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.release"> + <tool command="arm-linux-gnueabihf-g++ " id="cdt.managedbuild.tool.gnu.c.linker.exe.release.281634187" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.release"/> + <tool command="arm-linux-gnueabihf-g++ " id="cdt.managedbuild.tool.gnu.cpp.linker.exe.release.929570421" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.release"> <option id="gnu.cpp.link.option.paths.277042583" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" valueType="libPaths"> + <listOptionValue builtIn="false" value="/usr/xenomai/lib"/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/lib"/> <listOptionValue builtIn="false" value="/usr/arm-linux-gnueabihf/lib/xenomai"/> + <listOptionValue builtIn="false" value="/usr/local/linaro/arm-linux-gnueabihf/include/xenomai/lib"/> + <listOptionValue builtIn="false" value="/usr/lib/arm-linux-gnueabihf"/> </option> <option id="gnu.cpp.link.option.libs.1930118082" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" valueType="libs"> <listOptionValue builtIn="false" value="rt"/> @@ -140,14 +175,18 @@ </inputType> </tool> <tool command="arm-linux-gnueabihf-as" id="cdt.managedbuild.tool.gnu.assembler.exe.release.2052985276" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.release"> + <option id="gnu.both.asm.option.include.paths.1499955275" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath"> + <listOptionValue builtIn="false" value=""${workspace_loc:/BeagleRT/include}""/> + </option> <inputType id="cdt.managedbuild.tool.gnu.assembler.input.1212659593" superClass="cdt.managedbuild.tool.gnu.assembler.input"/> </tool> </toolChain> </folderInfo> <sourceEntries> - <entry excluding="audio_routines_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="core"/> + <entry excluding="default_main.cpp|audio_routines_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="core"/> <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="include"/> - <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/basic_analog_output"/> + <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/basic"/> + <entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="source"/> </sourceEntries> </configuration> </storageModule>
--- a/.settings/org.eclipse.cdt.core.prefs Sun Feb 08 00:20:01 2015 +0000 +++ b/.settings/org.eclipse.cdt.core.prefs Fri Jul 17 15:28:18 2015 +0100 @@ -1,3 +1,17 @@ eclipse.preferences.version=1 +environment/project/cdt.managedbuild.config.gnu.exe.debug.528876549/LD_LIBRARY_PATH/delimiter=\: +environment/project/cdt.managedbuild.config.gnu.exe.debug.528876549/LD_LIBRARY_PATH/operation=append +environment/project/cdt.managedbuild.config.gnu.exe.debug.528876549/LD_LIBRARY_PATH/value=/usr/lib64/openmpi/lib\:/import/teaching/ECS732/arm-gcc/x86_64-linux-gnu/arm-linux-gnueabihf/lib\:/import/teaching/ECS732/arm-gcc/lib/x86_64-linux-gnu\:/import/teaching/ECS732/arm-gcc/arm-linux-gnueabihf/lib +environment/project/cdt.managedbuild.config.gnu.exe.debug.528876549/PATH/delimiter=\: +environment/project/cdt.managedbuild.config.gnu.exe.debug.528876549/PATH/operation=append +environment/project/cdt.managedbuild.config.gnu.exe.debug.528876549/PATH/value=/usr/bin\:/bin\:/usr/sbin\:/sbin\:/usr/local/linaro/arm-linux-gnueabihf/bin environment/project/cdt.managedbuild.config.gnu.exe.debug.528876549/append=true environment/project/cdt.managedbuild.config.gnu.exe.debug.528876549/appendContributed=true +environment/project/cdt.managedbuild.config.gnu.exe.release.1521194538/LD_LIBRARY_PATH/delimiter=\: +environment/project/cdt.managedbuild.config.gnu.exe.release.1521194538/LD_LIBRARY_PATH/operation=append +environment/project/cdt.managedbuild.config.gnu.exe.release.1521194538/LD_LIBRARY_PATH/value=/usr/lib64/openmpi/lib\:/import/teaching/ECS732/arm-gcc/x86_64-linux-gnu/arm-linux-gnueabihf/lib\:/import/teaching/ECS732/arm-gcc/lib/x86_64-linux-gnu\:/import/teaching/ECS732/arm-gcc/arm-linux-gnueabihf/lib +environment/project/cdt.managedbuild.config.gnu.exe.release.1521194538/PATH/delimiter=\: +environment/project/cdt.managedbuild.config.gnu.exe.release.1521194538/PATH/operation=append +environment/project/cdt.managedbuild.config.gnu.exe.release.1521194538/PATH/value=/usr/bin\:/bin\:/usr/sbin\:/sbin\:/usr/local/linaro/arm-linux-gnueabihf/bin +environment/project/cdt.managedbuild.config.gnu.exe.release.1521194538/append=true +environment/project/cdt.managedbuild.config.gnu.exe.release.1521194538/appendContributed=true
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Doxyfile Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,1781 @@ +# Doxyfile 1.7.6.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = "BeagleRT" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "Real-time, ultra-low-latency audio and sensor processing system for BeagleBone Black" + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +SYMBOL_CACHE_SIZE = 0 + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command <command> <input-file>, where <command> is the value of +# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = include/BeagleRT.h include/Utilities.h + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = Debug Release + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# style sheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> +# Qt Help Project / Custom Filters</a>. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> +# Qt Help Project / Filter Attributes</a>. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the +# mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,139 @@ +#Â BeagleRT +# Low-latency, real-time audio and sensor processing on BeagleBone Black +#Â (c) 2015 Andrew McPherson, Victor Zappi, Giulio Moro +# Centre for Digital Music, Queen Mary University of London + +# This Makefile is intended for use on the BeagleBone Black itself +# and not for cross-compiling + +RM := rm -rf +STATIC_LIBS := ./libprussdrv.a ./libNE10.a +LIBS := -lrt -lnative -lxenomai + +ASM_SRCS := $(wildcard source/*.S) +ASM_OBJS := $(addprefix build/source/,$(notdir $(ASM_SRCS:.S=.o))) +ASM_DEPS := $(addprefix build/source/,$(notdir $(ASM_SRCS:.S=.d))) + +C_SRCS := $(wildcard source/*.c) +C_OBJS := $(addprefix build/source/,$(notdir $(C_SRCS:.c=.o))) +C_DEPS := $(addprefix build/source/,$(notdir $(C_SRCS:.c=.d))) + +CPP_SRCS := $(wildcard source/*.cpp) +CPP_OBJS := $(addprefix build/source/,$(notdir $(CPP_SRCS:.cpp=.o))) +CPP_DEPS := $(addprefix build/source/,$(notdir $(CPP_SRCS:.cpp=.d))) + +# Core BeagleRT sources +CORE_CPP_SRCS := \ +./core/GPIOcontrol.cpp \ +./core/I2c_Codec.cpp \ +./core/PRU.cpp \ +./core/RTAudio.cpp \ +./core/RTAudioCommandLine.cpp \ +./core/Utilities.cpp \ +./core/client.cpp + +CORE_OBJS := \ +./build/core/GPIOcontrol.o \ +./build/core/I2c_Codec.o \ +./build/core/PRU.o \ +./build/core/RTAudio.o \ +./build/core/RTAudioCommandLine.o \ +./build/core/Utilities.o \ +./build/core/client.o + +CORE_CPP_DEPS := \ +./build/core/GPIOcontrol.d \ +./build/core/I2c_Codec.d \ +./build/core/PRU.d \ +./build/core/RTAudio.d \ +./build/core/RTAudioCommandLine.d \ +./build/core/Utilities.d \ +./build/core/client.d + +# Objects for a system-supplied default main() file, if the user +#Â only wants to provide the render functions. +DEFAULT_MAIN_CPP_SRCS := ./core/default_main.cpp +DEFAULT_MAIN_OBJS := ./build/core/default_main.o +DEFAULT_MAIN_CPP_DEPS := ./build/core/default_main.d + +# All = build BeagleRT +all: BeagleRT + +# Rule for BeagleRT core C++ files +build/core/%.o: ./core/%.cpp + @echo 'Building file: $<' + @echo 'Invoking: GCC C++ Compiler' + g++ -I/usr/xenomai/include -I/usr/arm-linux-gnueabihf/include/xenomai/include -I/usr/arm-linux-gnueabihf/include/ne10 -O2 -Wall -c -fmessage-length=0 -U_FORTIFY_SOURCE -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + +# Rule for user-supplied C++ files +build/source/%.o: ./source/%.cpp + @echo 'Building file: $<' + @echo 'Invoking: GCC C++ Compiler' + g++ -I./include -I/usr/xenomai/include -I/usr/arm-linux-gnueabihf/include/xenomai/include -I/usr/arm-linux-gnueabihf/include/ne10 -O2 -Wall -c -fmessage-length=0 -U_FORTIFY_SOURCE -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + +# Rule for user-supplied C files +build/source/%.o: ./source/%.c + @echo 'Building file: $<' + @echo 'Invoking: GCC C Compiler' + gcc -I./include -I/usr/xenomai/include -I/usr/arm-linux-gnueabihf/include/xenomai/include -I/usr/arm-linux-gnueabihf/include/ne10 -O2 -Wall -c -fmessage-length=0 -U_FORTIFY_SOURCE -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + +# Rule for user-supplied assembly files +build/source/%.o: ./source/%.S + @echo 'Building file: $<' + @echo 'Invoking: GCC Assembler' + as -o "$@" "$<" + @echo 'Finished building: $<' + @echo ' ' + +# This is a nasty kludge: we want to be able to optionally link in a default +# main file if the user hasn't supplied one. We check for the presence of the main() +# function, and conditionally call one of two recursive make targets depending on whether +# we want to link in the default main file or not. The kludge is the mess of a shell script +# line below. Surely there's a better way to do this? +BeagleRT: $(CORE_OBJS) $(ASM_OBJS) $(C_OBJS) $(CPP_OBJS) $(STATIC_LIBS) + $(eval NEXT_TARGET := $(shell bash -c 'if [ `nm build/source/*.o | grep -w T | grep -w main | wc -l` == '0' ]; then echo "BeagleRT_with_main"; else echo "BeagleRT_without_main"; fi')) + $(MAKE) $(NEXT_TARGET) + @echo 'Finished building target: $@' + @echo ' ' +# $(MAKE) --no-print-directory post-build + +# Rule for building BeagleRT including the default main file (no user-supplied main()) +BeagleRT_with_main: $(CORE_OBJS) $(DEFAULT_MAIN_OBJS) $(ASM_OBJS) $(C_OBJS) $(CPP_OBJS) $(STATIC_LIBS) + @echo 'Building target: $@' + @echo 'Invoking: GCC C++ Linker' + g++ -L/usr/xenomai/lib -L/usr/arm-linux-gnueabihf/lib -L/usr/arm-linux-gnueabihf/lib/xenomai -L/usr/lib/arm-linux-gnueabihf -pthread -Wpointer-arith -o "BeagleRT" $(CORE_OBJS) $(DEFAULT_MAIN_OBJS) $(ASM_OBJS) $(C_OBJS) $(CPP_OBJS) $(STATIC_LIBS) $(LIBS) + +#Â Rule for building BeagleRT without the default main file (user-supplied main()) +BeagleRT_without_main: $(CORE_OBJS) $(ASM_OBJS) $(C_OBJS) $(CPP_OBJS) $(STATIC_LIBS) + @echo 'Building target: $@' + @echo 'Invoking: GCC C++ Linker' + g++ -L/usr/xenomai/lib -L/usr/arm-linux-gnueabihf/lib -L/usr/arm-linux-gnueabihf/lib/xenomai -L/usr/lib/arm-linux-gnueabihf -pthread -Wpointer-arith -o "BeagleRT" $(CORE_OBJS) $(ASM_OBJS) $(C_OBJS) $(CPP_OBJS) $(STATIC_LIBS) $(LIBS) + +# Other Targets: + +# Remove the temporary user-supplied source, plus the objects built from them +sourceclean: + -$(RM) source/* build/source/* BeagleRT + -@echo ' ' + +# Remove all the built objects, including the core BeagleRT objects +distclean: + -$(RM) build/source/* $(CORE_OBJS) $(CORE_CPP_DEPS) $(DEFAULT_MAIN_OBJS) $(DEFAULT_MAIN_CPP_DEPS) BeagleRT + -@echo ' ' + +# Remove only the user-generated objects +clean: + -$(RM) build/source/* BeagleRT + -@echo ' ' + +post-build: +# Nothing to do here (for now) + +.PHONY: all clean distclean sourceclean dependents +.SECONDARY: post-build
--- a/core/PRU.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/core/PRU.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -16,8 +16,9 @@ #include "../include/PRU.h" #include "../include/prussdrv.h" #include "../include/pruss_intc_mapping.h" +#include "../include/digital_gpio_mapping.h" #include "../include/GPIOcontrol.h" -#include "../include/render.h" +#include "../include/BeagleRT.h" #include "../include/pru_rtaudio_bin.h" #include <iostream> @@ -26,6 +27,7 @@ #include <cerrno> #include <fcntl.h> #include <sys/mman.h> +#include <unistd.h> // Xenomai-specific includes #include <sys/mman.h> @@ -40,7 +42,9 @@ #define PRU_MEM_DAC_OFFSET 0x0 // Offset within PRU0 RAM #define PRU_MEM_DAC_LENGTH 0x2000 // Length of ADC+DAC memory, in bytes #define PRU_MEM_COMM_OFFSET 0x0 // Offset within PRU-SHARED RAM - +#define PRU_MEM_DIGITAL_OFFSET 0x1000 //Offset within PRU-SHARED RAM +#define MEM_DIGITAL_BUFFER1_OFFSET 0x400 //Start pointer to DIGITAL_BUFFER1, which is 256 words. + // 256 is the maximum number of frames allowed #define PRU_SHOULD_STOP 0 #define PRU_CURRENT_BUFFER 1 #define PRU_BUFFER_FRAMES 2 @@ -52,6 +56,26 @@ #define PRU_FRAME_COUNT 8 #define PRU_USE_SPI 9 #define PRU_SPI_NUM_CHANNELS 10 +#define PRU_USE_DIGITAL 11 + +short int digitalPins[NUM_DIGITALS]={ + GPIO_NO_BIT_0, + GPIO_NO_BIT_1, + GPIO_NO_BIT_2, + GPIO_NO_BIT_3, + GPIO_NO_BIT_4, + GPIO_NO_BIT_5, + GPIO_NO_BIT_6, + GPIO_NO_BIT_7, + GPIO_NO_BIT_8, + GPIO_NO_BIT_9, + GPIO_NO_BIT_10, + GPIO_NO_BIT_11, + GPIO_NO_BIT_12, + GPIO_NO_BIT_13, + GPIO_NO_BIT_14, + GPIO_NO_BIT_15, +}; #define PRU_SAMPLE_INTERVAL_NS 11338 // 88200Hz per SPI sample = 11.338us @@ -75,13 +99,17 @@ const unsigned int PRU::kPruGPIOTestPin2 = 31; // GPIO0(31); P9-13 const unsigned int PRU::kPruGPIOTestPin3 = 26; // GPIO0(26); P8-14 -extern int gShouldStop; +extern bool gShouldStop; extern int gRTAudioVerbose; // Constructor: specify a PRU number (0 or 1) -PRU::PRU() -: pru_number(0), running(false), spi_enabled(false), gpio_enabled(false), led_enabled(false), - gpio_test_pin_enabled(false), spi_num_channels(0), xenomai_gpio_fd(-1), xenomai_gpio(0) +PRU::PRU(BeagleRTContext *input_context) +: context(input_context), pru_number(0), running(false), analog_enabled(false), + digital_enabled(false), gpio_enabled(false), led_enabled(false), + gpio_test_pin_enabled(false), + pru_buffer_comm(0), pru_buffer_spi_dac(0), pru_buffer_spi_adc(0), + pru_buffer_digital(0), pru_buffer_audio_dac(0), pru_buffer_audio_adc(0), + xenomai_gpio_fd(-1), xenomai_gpio(0) { } @@ -103,9 +131,9 @@ // viewed on a scope. If include_led is set, // user LED 3 on the BBB is taken over by the PRU // to indicate activity -int PRU::prepareGPIO(int use_spi, int include_test_pin, int include_led) +int PRU::prepareGPIO(int include_test_pin, int include_led) { - if(use_spi) { + if(context->analogFrames != 0) { // Prepare DAC CS/ pin: output, high to begin if(gpio_export(kPruGPIODACSyncPin)) { if(gRTAudioVerbose) @@ -138,7 +166,22 @@ return -1; } - spi_enabled = true; + analog_enabled = true; + } + + if(context->digitalFrames != 0){ + for(unsigned int i = 0; i < context->digitalChannels; i++){ + if(gpio_export(digitalPins[i])) { + if(gRTAudioVerbose) + cerr << "Warning: couldn't export digital GPIO pin " << digitalPins[i] << "\n"; // this is left as a warning because if the pin has been exported by somebody else, can still be used + } + if(gpio_set_dir(digitalPins[i], INPUT_PIN)) { + if(gRTAudioVerbose) + cerr << "Error: Couldn't set direction on digital GPIO pin " << digitalPins[i] << "\n"; + return -1; + } + } + digital_enabled = true; } if(include_test_pin) { @@ -206,10 +249,15 @@ { if(!gpio_enabled) return; - if(spi_enabled) { + if(analog_enabled) { gpio_unexport(kPruGPIODACSyncPin); gpio_unexport(kPruGPIOADCSyncPin); } + if(digital_enabled){ + for(unsigned int i = 0; i < context->digitalChannels; i++){ + gpio_unexport(digitalPins[i]); + } + } if(gpio_test_pin_enabled) { gpio_unexport(kPruGPIOTestPin); gpio_unexport(kPruGPIOTestPin2); @@ -221,7 +269,6 @@ // rather than the system default led_set_trigger(3, "mmc1"); } - gpio_enabled = gpio_test_pin_enabled = false; } @@ -237,20 +284,13 @@ pru_number = pru_num; - /* Set number of SPI ADC / DAC channels to use. This implicitly - * also determines the sample rate relative to the audio clock - * (half audio clock for 8 channels, full audio clock for 4, - * double audio clock for 2) - */ - spi_num_channels = spi_channels; - /* Initialize structure used by prussdrv_pruintc_intc */ /* PRUSS_INTC_INITDATA is found in pruss_intc_mapping.h */ tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA; /* Allocate and initialize memory */ prussdrv_init(); - if(prussdrv_open(pru_number == 0 ? PRU_EVTOUT_0 : PRU_EVTOUT_1)) { + if(prussdrv_open(PRU_EVTOUT_0)) { rt_printf("Failed to open PRU driver\n"); return 1; } @@ -258,32 +298,37 @@ /* Map PRU's INTC */ prussdrv_pruintc_init(&pruss_intc_initdata); - spi_buffer_frames = frames_per_buffer; - audio_buffer_frames = spi_buffer_frames * spi_num_channels / 4; - /* Map PRU memory to pointers */ prussdrv_map_prumem (PRUSS0_SHARED_DATARAM, (void **)&pruMem); pru_buffer_comm = (uint32_t *)&pruMem[PRU_MEM_COMM_OFFSET/sizeof(uint32_t)]; pru_buffer_audio_dac = (int16_t *)&pruMem[PRU_MEM_MCASP_OFFSET/sizeof(uint32_t)]; /* ADC memory starts 2(ch)*2(buffers)*bufsize samples later */ - pru_buffer_audio_adc = &pru_buffer_audio_dac[4 * audio_buffer_frames]; + pru_buffer_audio_adc = &pru_buffer_audio_dac[4 * context->audioFrames]; - if(spi_enabled) { + if(analog_enabled) { prussdrv_map_prumem (pru_number == 0 ? PRUSS0_PRU0_DATARAM : PRUSS0_PRU1_DATARAM, (void **)&pruMem); pru_buffer_spi_dac = (uint16_t *)&pruMem[PRU_MEM_DAC_OFFSET/sizeof(uint32_t)]; /* ADC memory starts after N(ch)*2(buffers)*bufsize samples */ - pru_buffer_spi_adc = &pru_buffer_spi_dac[2 * spi_num_channels * spi_buffer_frames]; + pru_buffer_spi_adc = &pru_buffer_spi_dac[2 * context->analogChannels * context->analogFrames]; } else { pru_buffer_spi_dac = pru_buffer_spi_adc = 0; } + if(digital_enabled) { + prussdrv_map_prumem (PRUSS0_SHARED_DATARAM, (void **)&pruMem); + pru_buffer_digital = (uint32_t *)&pruMem[PRU_MEM_DIGITAL_OFFSET/sizeof(uint32_t)]; + } + else { + pru_buffer_digital = 0; + } + /* Set up flags */ pru_buffer_comm[PRU_SHOULD_STOP] = 0; pru_buffer_comm[PRU_CURRENT_BUFFER] = 0; - pru_buffer_comm[PRU_BUFFER_FRAMES] = spi_buffer_frames; + pru_buffer_comm[PRU_BUFFER_FRAMES] = context->analogFrames; pru_buffer_comm[PRU_SHOULD_SYNC] = 0; pru_buffer_comm[PRU_SYNC_ADDRESS] = 0; pru_buffer_comm[PRU_SYNC_PIN_MASK] = 0; @@ -295,19 +340,33 @@ pru_buffer_comm[PRU_LED_ADDRESS] = 0; pru_buffer_comm[PRU_LED_PIN_MASK] = 0; } - if(spi_enabled) { + if(analog_enabled) { pru_buffer_comm[PRU_USE_SPI] = 1; - pru_buffer_comm[PRU_SPI_NUM_CHANNELS] = spi_num_channels; + pru_buffer_comm[PRU_SPI_NUM_CHANNELS] = context->analogChannels; } else { pru_buffer_comm[PRU_USE_SPI] = 0; pru_buffer_comm[PRU_SPI_NUM_CHANNELS] = 0; } + if(digital_enabled) { + pru_buffer_comm[PRU_USE_DIGITAL] = 1; +//TODO: add mask + } + else { + pru_buffer_comm[PRU_USE_DIGITAL] = 0; - /* Clear ADC and DAC memory */ - if(spi_enabled) { + } + + /* Clear ADC and DAC memory.*/ + //TODO: this initialisation should only address the memory effectively used by these buffers, i.e.:depend on the number of frames + // (otherwise might cause issues if we move memory locations later on) + if(analog_enabled) { for(int i = 0; i < PRU_MEM_DAC_LENGTH / 2; i++) pru_buffer_spi_dac[i] = 0; + if(digital_enabled){ + for(int i = 0; i < PRU_MEM_DIGITAL_OFFSET*2; i++) + pru_buffer_digital[i] = 0x0000ffff; // set to all inputs, to avoid unexpected spikes + } } for(int i = 0; i < PRU_MEM_MCASP_LENGTH / 2; i++) pru_buffer_audio_dac[i] = 0; @@ -332,121 +391,278 @@ } // Run the code image in the specified file -int PRU::start() +int PRU::start(char * const filename) { /* Clear any old interrupt */ - if(pru_number == 0) - prussdrv_pru_clear_event(PRU_EVTOUT_0, PRU0_ARM_INTERRUPT); - else - prussdrv_pru_clear_event(PRU_EVTOUT_1, PRU1_ARM_INTERRUPT); + prussdrv_pru_clear_event(PRU_EVTOUT_0, PRU0_ARM_INTERRUPT); - /* Load and execute binary on PRU */ - if(prussdrv_exec_code(pru_number, PRUcode, sizeof(PRUcode))) { - rt_printf("Failed to execute PRU code\n"); - return 1; - } + /* Load and execute binary on PRU */ + if(filename[0] == '\0') { //if the string is empty, load the embedded code + if(gRTAudioVerbose) + rt_printf("Using embedded PRU code\n"); + if(prussdrv_exec_code(pru_number, PRUcode, sizeof(PRUcode))) { + rt_printf("Failed to execute PRU code\n"); + return 1; + } + } else { + if(gRTAudioVerbose) + rt_printf("Using PRU code from %s\n",filename); + if(prussdrv_exec_program(pru_number, filename)) { + rt_printf("Failed to execute PRU code from %s\n", filename); + return 1; + } + } running = true; return 0; } // Main loop to read and write data from/to PRU -void PRU::loop() +void PRU::loop(RT_INTR *pru_interrupt, void *userData) { +#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS + RTIME irqTimeout = PRU_SAMPLE_INTERVAL_NS * 1024; // Timeout for PRU interrupt: about 10ms, much longer than any expected period +#else // Polling interval is 1/4 of the period - RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * (spi_num_channels / 2) * spi_buffer_frames / 4; - float *audioInBuffer, *audioOutBuffer; + RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * (context->analogChannels / 2) * context->analogFrames / 4; +#endif - audioInBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float)); - audioOutBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float)); + float *lastAnalogOutFrame; + uint32_t *digitalBuffer0, *digitalBuffer1, *lastDigitalBuffer; + uint32_t pru_audio_offset, pru_spi_offset; - if(audioInBuffer == 0 || audioOutBuffer == 0) { - rt_printf("Error: couldn't allocated audio buffers\n"); + // Allocate audio buffers + context->audioIn = (float *)malloc(2 * context->audioFrames * sizeof(float)); + context->audioOut = (float *)malloc(2 * context->audioFrames * sizeof(float)); + if(context->audioIn == 0 || context->audioOut == 0) { + rt_printf("Error: couldn't allocate audio buffers\n"); return; } + // Allocate analog buffers + if(analog_enabled) { + context->analogIn = (float *)malloc(context->analogChannels * context->analogFrames * sizeof(float)); + context->analogOut = (float *)malloc(context->analogChannels * context->analogFrames * sizeof(float)); + lastAnalogOutFrame = (float *)malloc(context->analogChannels * sizeof(float)); + + if(context->analogIn == 0 || context->analogOut == 0 || lastAnalogOutFrame == 0) { + rt_printf("Error: couldn't allocate analog buffers\n"); + return; + } + + memset(lastAnalogOutFrame, 0, context->analogChannels * sizeof(float)); + } + + // Allocate digital buffers + digitalBuffer0 = pru_buffer_digital; + digitalBuffer1 = pru_buffer_digital + MEM_DIGITAL_BUFFER1_OFFSET / sizeof(uint32_t); + if(digital_enabled) { + lastDigitalBuffer = (uint32_t *)malloc(context->digitalFrames * sizeof(uint32_t)); //temp buffer to hold previous states + if(lastDigitalBuffer == 0) { + rt_printf("Error: couldn't allocate digital buffers\n"); + return; + } + + for(unsigned int n = 0; n < context->digitalFrames; n++){ + // Initialize lastDigitalFrames to all inputs + lastDigitalBuffer[n] = 0x0000ffff; + } + } + + // TESTING + // uint32_t testCount = 0; + // RTIME startTime = rt_timer_read(); + +#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS + int result; +#else + // Which buffer the PRU was last processing + uint32_t lastPRUBuffer = 0; +#endif + while(!gShouldStop) { - // Wait for PRU to move to buffer 1 - while(pru_buffer_comm[PRU_CURRENT_BUFFER] == 0 && !gShouldStop) { +#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS + // Wait for PRU to move to change buffers; + // PRU will send an interrupts which we wait for + rt_intr_enable(pru_interrupt); + while(!gShouldStop) { + result = rt_intr_wait(pru_interrupt, irqTimeout); + if(result >= 0) + break; + else if(result == -ETIMEDOUT) + rt_printf("Warning: PRU timeout!\n"); + else { + rt_printf("Error: wait for interrupt failed (%d)\n", result); + gShouldStop = 1; + } + } + + // Clear pending PRU interrupt + prussdrv_pru_clear_event(PRU_EVTOUT_1, PRU1_ARM_INTERRUPT); +#else + // Poll + while(pru_buffer_comm[PRU_CURRENT_BUFFER] == lastPRUBuffer && !gShouldStop) { rt_task_sleep(sleepTime); } + + lastPRUBuffer = pru_buffer_comm[PRU_CURRENT_BUFFER]; +#endif + if(gShouldStop) break; + // Check which buffer we're on-- will have been set right + // before the interrupt was asserted + if(pru_buffer_comm[PRU_CURRENT_BUFFER] == 1) { + // PRU is on buffer 1. We read and write to buffer 0 + pru_audio_offset = 0; + pru_spi_offset = 0; + if(digital_enabled) + context->digital = digitalBuffer0; + } + else { + // PRU is on buffer 0. We read and write to buffer 1 + pru_audio_offset = context->audioFrames * 2; + pru_spi_offset = context->analogFrames * context->analogChannels; + if(digital_enabled) + context->digital = digitalBuffer1; + } + + // FIXME: some sort of margin is needed here to prevent the audio + // code from completely eating the Linux system + // testCount++; + //rt_task_sleep(sleepTime*4); + //rt_task_sleep(sleepTime/4); + if(xenomai_gpio != 0) { // Set the test pin high xenomai_gpio[GPIO_SETDATAOUT] = TEST_PIN_MASK; } - // Render from/to buffer 0 + // Convert short (16-bit) samples to float + // TODO: NEON + for(unsigned int n = 0; n < 2 * context->audioFrames; n++) + context->audioIn[n] = (float)pru_buffer_audio_adc[n + pru_audio_offset] / 32768.0; - // Convert short (16-bit) samples to float - for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++) - audioInBuffer[n] = (float)pru_buffer_audio_adc[n] / 32768.0; + if(analog_enabled) { + // TODO: NEON + for(unsigned int n = 0; n < context->analogChannels * context->analogFrames; n++) + context->analogIn[n] = (float)pru_buffer_spi_adc[n + pru_spi_offset] / 65536.0; - if(spi_enabled) - render(spi_buffer_frames, audio_buffer_frames, audioInBuffer, audioOutBuffer, - pru_buffer_spi_adc, pru_buffer_spi_dac); - else - render(0, audio_buffer_frames, audioInBuffer, audioOutBuffer, 0, 0); + if(context->flags & BEAGLERT_FLAG_ANALOG_OUTPUTS_PERSIST) { + // Initialize the output buffer with the values that were in the last frame of the previous output + for(unsigned int ch = 0; ch < context->analogChannels; ch++){ + for(unsigned int n = 0; n < context->analogFrames; n++){ + context->analogOut[n * context->analogChannels + ch] = lastAnalogOutFrame[ch]; + } + } + } + else { + // Outputs are 0 unless set otherwise + memset(context->analogOut, 0, context->analogChannels * context->analogFrames * sizeof(float)); + } + } - // Convert float back to short - for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++) { - int out = audioOutBuffer[n] * 32768.0; + if(digital_enabled){ + // Use past digital values to initialize the array properly. + // For each frame: + // - pins previously set as outputs will keep the output value they had in the last frame of the previous buffer, + // - pins previously set as inputs will carry the newly read input value + + for(unsigned int n = 0; n < context->digitalFrames; n++){ + uint16_t inputs = lastDigitalBuffer[n] & 0xffff; // half-word, has 1 for inputs and 0 for outputs + + uint16_t outputs = ~inputs; // half-word has 1 for outputs and 0 for inputs; + context->digital[n] = (lastDigitalBuffer[context->digitalFrames - 1] & (outputs << 16)) | // keep output values set in the last frame of the previous buffer + (context->digital[n] & (inputs << 16)) | // inputs from current context->digital[n]; + (lastDigitalBuffer[n] & (inputs)); // keep pin configuration from previous context->digital[n] +// context->digital[n]=digitalBufferTemp[n]; //ignores inputs + } + } + + // Call user render function + // *********************** + render(context, userData); + // *********************** + + if(analog_enabled) { + if(context->flags & BEAGLERT_FLAG_ANALOG_OUTPUTS_PERSIST) { + // Remember the content of the lastAnalogOutFrame + for(unsigned int ch = 0; ch < context->analogChannels; ch++){ + lastAnalogOutFrame[ch] = context->analogOut[context->analogChannels * (context->analogFrames - 1) + ch]; + } + } + + // Convert float back to short for SPI output + for(unsigned int n = 0; n < context->analogChannels * context->analogFrames; n++) { + int out = context->analogOut[n] * 65536.0; + if(out < 0) out = 0; + else if(out > 65535) out = 65535; + pru_buffer_spi_dac[n + pru_spi_offset] = (uint16_t)out; + } + } + + if(digital_enabled) { // keep track of past digital values + for(unsigned int n = 0; n < context->digitalFrames; n++){ + lastDigitalBuffer[n] = context->digital[n]; + } + } + + // Convert float back to short for audio + // TODO: NEON + for(unsigned int n = 0; n < 2 * context->audioFrames; n++) { + int out = context->audioOut[n] * 32768.0; if(out < -32768) out = -32768; else if(out > 32767) out = 32767; - pru_buffer_audio_dac[n] = (int16_t)out; + pru_buffer_audio_dac[n + pru_audio_offset] = (int16_t)out; } + // Increment total number of samples that have elapsed + context->audioSampleCount += context->audioFrames; + if(xenomai_gpio != 0) { // Set the test pin high xenomai_gpio[GPIO_CLEARDATAOUT] = TEST_PIN_MASK; } - // Wait for PRU to move to buffer 0 - while(pru_buffer_comm[PRU_CURRENT_BUFFER] != 0 && !gShouldStop) { - rt_task_sleep(sleepTime); - } + // FIXME: TESTING!! + // if(testCount > 100000) + // break; + } - if(gShouldStop) - break; +#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS + // Turn off the interrupt for the PRU if it isn't already off + rt_intr_disable(pru_interrupt); +#endif - if(xenomai_gpio != 0) { - // Set the test pin high - xenomai_gpio[GPIO_SETDATAOUT] = TEST_PIN_MASK; - } - - // Render from/to buffer 1 - - // Convert short (16-bit) samples to float - for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++) - audioInBuffer[n] = (float)pru_buffer_audio_adc[n + audio_buffer_frames * 2] / 32768.0; - - if(spi_enabled) - render(spi_buffer_frames, audio_buffer_frames, audioInBuffer, audioOutBuffer, - &pru_buffer_spi_adc[spi_buffer_frames * spi_num_channels], &pru_buffer_spi_dac[spi_buffer_frames * spi_num_channels]); - else - render(0, audio_buffer_frames, audioInBuffer, audioOutBuffer, 0, 0); - - // Convert float back to short - for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++) { - int out = audioOutBuffer[n] * 32768.0; - if(out < -32768) out = -32768; - else if(out > 32767) out = 32767; - pru_buffer_audio_dac[n + audio_buffer_frames * 2] = (int16_t)out; - } - - if(xenomai_gpio != 0) { - // Set the test pin high - xenomai_gpio[GPIO_CLEARDATAOUT] = TEST_PIN_MASK; - } - } + // FIXME: TESTING + // RTIME endTime = rt_timer_read(); + // RTIME diffTime = endTime - startTime; + // rt_printf("%d blocks elapsed in %f seconds, %f Hz block rate\n", testCount, ((float)diffTime / 1.0e9), (float)testCount / ((float)diffTime / 1.0e9)); // Tell PRU to stop pru_buffer_comm[PRU_SHOULD_STOP] = 1; - free(audioInBuffer); - free(audioOutBuffer); + // Wait two buffer lengths for the PRU to finish + rt_task_sleep(PRU_SAMPLE_INTERVAL_NS * context->analogFrames * 4 * 2); + + // Clean up after ourselves + free(context->audioIn); + free(context->audioOut); + + if(analog_enabled) { + free(context->analogIn); + free(context->analogOut); + free(lastAnalogOutFrame); + } + + if(digital_enabled) { + free(lastDigitalBuffer); + } + + context->audioIn = context->audioOut = 0; + context->analogIn = context->analogOut = 0; + context->digital = 0; } // Wait for an interrupt from the PRU indicate it is finished @@ -454,11 +670,8 @@ { if(!running) return; - prussdrv_pru_wait_event (pru_number == 0 ? PRU_EVTOUT_0 : PRU_EVTOUT_1); - if(pru_number == 0) - prussdrv_pru_clear_event(PRU_EVTOUT_0, PRU0_ARM_INTERRUPT); - else - prussdrv_pru_clear_event(PRU_EVTOUT_1, PRU1_ARM_INTERRUPT); + prussdrv_pru_wait_event (PRU_EVTOUT_0); + prussdrv_pru_clear_event(PRU_EVTOUT_0, PRU0_ARM_INTERRUPT); } // Turn off the PRU when done
--- a/core/RTAudio.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/core/RTAudio.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -24,13 +24,17 @@ #include <sys/mman.h> #include <native/task.h> #include <native/timer.h> +#include <native/intr.h> #include <rtdk.h> -#include "../include/RTAudio.h" +#include "../include/BeagleRT.h" #include "../include/PRU.h" #include "../include/I2c_Codec.h" -#include "../include/render.h" #include "../include/GPIOcontrol.h" +#include "../include/client.h" + +// ARM interrupt number for PRU event EVTOUT7 +#define PRU_RTAUDIO_IRQ 21 using namespace std; @@ -44,9 +48,13 @@ } InternalAuxiliaryTask; const char gRTAudioThreadName[] = "beaglert-audio"; +const char gRTAudioInterruptName[] = "beaglert-pru-irq"; // Real-time tasks and objects RT_TASK gRTAudioThread; +#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS +RT_INTR gRTAudioInterrupt; +#endif PRU *gPRU = 0; I2c_Codec *gAudioCodec = 0; @@ -56,43 +64,46 @@ bool gShouldStop = false; // general settings +char gPRUFilename[MAX_PRU_FILENAME_LENGTH]; // Path to PRU binary file (internal code if empty)_ int gRTAudioVerbose = 0; // Verbosity level for debugging int gAmplifierMutePin = -1; int gAmplifierShouldBeginMuted = 0; -// Number of audio and matrix channels, globally accessible -// At least gNumMatrixChannels needs to be global to be used -// by the analogRead() and analogWrite() macros without creating -// extra confusion in their use cases by passing this argument -int gNumAudioChannels = 0; -int gNumMatrixChannels = 0; +// Context which holds all the audio/sensor data passed to the render routines +BeagleRTContext gContext; + +// User data passed in from main() +void *gUserData; // initAudio() prepares the infrastructure for running PRU-based real-time // audio, but does not actually start the calculations. // periodSize indicates the number of _sensor_ frames per period: the audio period size // is twice this value. In total, the audio latency in frames will be 4*periodSize, // plus any latency inherent in the ADCs and DACs themselves. -// useMatrix indicates whether to enable the ADC and DAC or just use the audio codec. -// numMatrixChannels indicates how many ADC and DAC channels to use. -// userData is an opaque pointer which will be passed through to the initialise_render() +// useAnalog indicates whether to enable the ADC and DAC or just use the audio codec. +// numAnalogChannels indicates how many ADC and DAC channels to use. +// userData is an opaque pointer which will be passed through to the setup() // function for application-specific use // // Returns 0 on success. -int BeagleRT_initAudio(RTAudioSettings *settings, void *userData) +int BeagleRT_initAudio(BeagleRTInitSettings *settings, void *userData) { rt_print_auto_init(1); - setVerboseLevel(settings->verbose); - if(gRTAudioVerbose == 1) - rt_printf("Running with Xenomai\n"); + BeagleRT_setVerboseLevel(settings->verbose); + strncpy(gPRUFilename, settings->pruFilename, MAX_PRU_FILENAME_LENGTH); + gUserData = userData; + + // Initialise context data structure + memset(&gContext, 0, sizeof(BeagleRTContext)); if(gRTAudioVerbose) { cout << "Starting with period size " << settings->periodSize << "; "; - if(settings->useMatrix) - cout << "matrix enabled\n"; + if(settings->useAnalog) + cout << "analog enabled\n"; else - cout << "matrix disabled\n"; + cout << "analog disabled\n"; cout << "DAC level " << settings->dacLevel << "dB; ADC level " << settings->adcLevel; cout << "dB; headphone level " << settings->headphoneLevel << "dB\n"; if(settings->beginMuted) @@ -106,7 +117,7 @@ if(gpio_export(settings->ampMutePin)) { if(gRTAudioVerbose) - cout << "Warning: couldn't export amplifier mute pin\n"; + cout << "Warning: couldn't export amplifier mute pin " << settings-> ampMutePin << "\n"; } if(gpio_set_dir(settings->ampMutePin, OUTPUT_PIN)) { if(gRTAudioVerbose) @@ -120,36 +131,78 @@ } } - // Limit the matrix channels to sane values - if(settings->numMatrixChannels >= 8) - settings->numMatrixChannels = 8; - else if(settings->numMatrixChannels >= 4) - settings->numMatrixChannels = 4; + // Limit the analog channels to sane values + if(settings->numAnalogChannels >= 8) + settings->numAnalogChannels = 8; + else if(settings->numAnalogChannels >= 4) + settings->numAnalogChannels = 4; else - settings->numMatrixChannels = 2; + settings->numAnalogChannels = 2; // Sanity check the combination of channels and period size - if(settings->numMatrixChannels <= 4 && settings->periodSize < 2) { - cout << "Error: " << settings->numMatrixChannels << " channels and period size of " << settings->periodSize << " not supported.\n"; + if(settings->numAnalogChannels <= 4 && settings->periodSize < 2) { + cout << "Error: " << settings->numAnalogChannels << " channels and period size of " << settings->periodSize << " not supported.\n"; return 1; } - if(settings->numMatrixChannels <= 2 && settings->periodSize < 4) { - cout << "Error: " << settings->numMatrixChannels << " channels and period size of " << settings->periodSize << " not supported.\n"; + if(settings->numAnalogChannels <= 2 && settings->periodSize < 4) { + cout << "Error: " << settings->numAnalogChannels << " channels and period size of " << settings->periodSize << " not supported.\n"; return 1; } + // Initialise the rendering environment: sample rates, frame counts, numbers of channels + gContext.audioSampleRate = 44100.0; + gContext.audioChannels = 2; + + if(settings->useAnalog) { + gContext.audioFrames = settings->periodSize * settings->numAnalogChannels / 4; + + gContext.analogFrames = settings->periodSize; + gContext.analogChannels = settings->numAnalogChannels; + gContext.analogSampleRate = gContext.audioSampleRate * 4.0 / (float)settings->numAnalogChannels; + } + else { + gContext.audioFrames = settings->periodSize * 2; + + gContext.analogFrames = 0; + gContext.analogChannels = 0; + gContext.analogSampleRate = 0; + } + + // For now, digital frame rate is equal to audio frame rate + if(settings->useDigital) { + gContext.digitalFrames = gContext.audioFrames; + gContext.digitalSampleRate = gContext.audioSampleRate; + gContext.digitalChannels = settings->numDigitalChannels; + } + else { + gContext.digitalFrames = 0; + gContext.digitalSampleRate = 0; + gContext.digitalChannels = 0; + } + + // Set flags based on init settings + if(settings->interleave) + gContext.flags |= BEAGLERT_FLAG_INTERLEAVED; + if(settings->analogOutputsPersist) + gContext.flags |= BEAGLERT_FLAG_ANALOG_OUTPUTS_PERSIST; + // Use PRU for audio - gPRU = new PRU(); + gPRU = new PRU(&gContext); gAudioCodec = new I2c_Codec(); - if(gPRU->prepareGPIO(settings->useMatrix, 1, 1)) { + // Initialise the GPIO pins, including possibly the digital pins in the render routines + if(gPRU->prepareGPIO(1, 1)) { cout << "Error: unable to prepare GPIO for PRU audio\n"; return 1; } - if(gPRU->initialise(0, settings->periodSize, settings->numMatrixChannels, true)) { + + // Get the PRU memory buffers ready to go + if(gPRU->initialise(0, settings->periodSize, settings->numAnalogChannels, true)) { cout << "Error: unable to initialise PRU\n"; return 1; } + + // Prepare the audio codec, which clocks the whole system if(gAudioCodec->initI2C_RW(2, settings->codecI2CAddress, -1)) { cout << "Unable to open codec I2C\n"; return 1; @@ -164,25 +217,8 @@ BeagleRT_setADCLevel(settings->adcLevel); BeagleRT_setHeadphoneLevel(settings->headphoneLevel); - // Initialise the rendering environment: pass the number of audio and matrix - // channels, the period size for matrix and audio, and the sample rates - - int audioPeriodSize = settings->periodSize * 2; - float audioSampleRate = 44100.0; - float matrixSampleRate = 22050.0; - if(settings->useMatrix) { - audioPeriodSize = settings->periodSize * settings->numMatrixChannels / 4; - matrixSampleRate = audioSampleRate * 4.0 / (float)settings->numMatrixChannels; - } - - gNumAudioChannels = 2; - gNumMatrixChannels = settings->useMatrix ? settings->numMatrixChannels : 0; - - if(!initialise_render(gNumMatrixChannels, gNumAudioChannels, - settings->useMatrix ? settings->periodSize : 0, /* matrix period size */ - audioPeriodSize, - matrixSampleRate, audioSampleRate, - userData)) { + // Call the user-defined initialisation function + if(!setup(&gContext, userData)) { cout << "Couldn't initialise audio rendering\n"; return 1; } @@ -208,8 +244,8 @@ gShouldStop = 1; } else { - if(gPRU->start()) { - rt_printf("Error: unable to start PRU\n"); + if(gPRU->start(gPRUFilename)) { + rt_printf("Error: unable to start PRU from file %s\n", gPRUFilename); gShouldStop = 1; } else { @@ -223,8 +259,11 @@ } } - gPRU->loop(); - +#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS + gPRU->loop(&gRTAudioInterrupt, gUserData); +#else + gPRU->loop(0, gUserData); +#endif // Now clean up // gPRU->waitForFinish(); gPRU->disable(); @@ -238,9 +277,10 @@ } // Create a calculation loop which can run independently of the audio, at a different -// (equal or lower) priority. Audio priority is 99; priority should be generally be less than this. +// (equal or lower) priority. Audio priority is defined in BEAGLERT_AUDIO_PRIORITY; +// priority should be generally be less than this. // Returns an (opaque) pointer to the created task on success; 0 on failure -AuxiliaryTask createAuxiliaryTaskLoop(void (*functionToCall)(void), int priority, const char *name) +AuxiliaryTask BeagleRT_createAuxiliaryTask(void (*functionToCall)(void), int priority, const char *name) { InternalAuxiliaryTask *newTask = (InternalAuxiliaryTask*)malloc(sizeof(InternalAuxiliaryTask)); @@ -263,7 +303,7 @@ // Schedule a previously created auxiliary task. It will run when the priority rules next // allow it to be scheduled. -void scheduleAuxiliaryTask(AuxiliaryTask task) +void BeagleRT_scheduleAuxiliaryTask(AuxiliaryTask task) { InternalAuxiliaryTask *taskToSchedule = (InternalAuxiliaryTask *)task; @@ -300,12 +340,21 @@ int BeagleRT_startAudio() { - // Create audio thread with the highest priority - if(rt_task_create(&gRTAudioThread, gRTAudioThreadName, 0, 99, T_JOINABLE | T_FPU)) { + // Create audio thread with high Xenomai priority + if(rt_task_create(&gRTAudioThread, gRTAudioThreadName, 0, BEAGLERT_AUDIO_PRIORITY, T_JOINABLE | T_FPU)) { cout << "Error: unable to create Xenomai audio thread" << endl; return -1; } +#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS + // Create an interrupt which the audio thread receives from the PRU + int result = 0; + if((result = rt_intr_create(&gRTAudioInterrupt, gRTAudioInterruptName, PRU_RTAUDIO_IRQ, I_NOAUTOENA)) != 0) { + cout << "Error: unable to create Xenomai interrupt for PRU (error " << result << ")" << endl; + return -1; + } +#endif + // Start all RT threads if(rt_task_start(&gRTAudioThread, &audioLoop, 0)) { cout << "Error: unable to start Xenomai audio thread" << endl; @@ -354,19 +403,28 @@ // Free any resources associated with PRU real-time audio void BeagleRT_cleanupAudio() { - cleanup_render(); + cleanup(&gContext, gUserData); // Clean up the auxiliary tasks vector<InternalAuxiliaryTask*>::iterator it; for(it = gAuxTasks.begin(); it != gAuxTasks.end(); it++) { InternalAuxiliaryTask *taskStruct = *it; + // Delete the task + rt_task_delete(&taskStruct->task); + // Free the name string and the struct itself free(taskStruct->name); free(taskStruct); } gAuxTasks.clear(); + // Delete the audio task and its interrupt +#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS + rt_intr_delete(&gRTAudioInterrupt); +#endif + rt_task_delete(&gRTAudioThread); + if(gPRU != 0) delete gPRU; if(gAudioCodec != 0) @@ -420,7 +478,7 @@ } // Set the verbosity level -void setVerboseLevel(int level) +void BeagleRT_setVerboseLevel(int level) { gRTAudioVerbose = level; }
--- a/core/RTAudioCommandLine.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/core/RTAudioCommandLine.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -9,38 +9,66 @@ #include <cstdlib> #include <cstring> #include <getopt.h> +#include "../include/BeagleRT.h" -#include "../include/RTAudio.h" +#ifndef OPT_PRU_FILE +#define OPT_PRU_FILE 176 // this is an extended ASCII code +#endif + +enum { + kAmplifierMutePin = 61 // P8-26 controls amplifier mute +}; // Default command-line options for RTAudio struct option gDefaultLongOptions[] = { {"period", 1, NULL, 'p'}, {"verbose", 0, NULL, 'v'}, - {"use-matrix", 1, NULL, 'm'}, - {"matrix-channels", 1, NULL, 'C'}, + {"use-analog", 1, NULL, 'N'}, + {"use-digital", 1, NULL, 'G'}, + {"analog-channels", 1, NULL, 'C'}, + {"digital-channels", 1, NULL, 'B'}, {"mute-speaker", 1, NULL, 'M'}, {"dac-level", 1, NULL, 'D'}, {"adc-level", 1, NULL, 'A'}, {"hp-level", 1, NULL, 'H'}, + {"receive-port", 1, NULL, 'R'}, + {"transmit-port", 1, NULL, 'T'}, + {"server-name", 1, NULL, 'S'}, + {"pru-file", 1, NULL, OPT_PRU_FILE}, {NULL, 0, NULL, 0} }; -const char gDefaultShortOptions[] = "p:vm:M:C:D:A:H:"; +const char gDefaultShortOptions[] = "p:vN:M:C:D:A:H:G:B:R:T:S:"; -// This function sets the default settings for the RTAudioSettings structure -void BeagleRT_defaultSettings(RTAudioSettings *settings) +// This function sets the default settings for the BeagleRTInitSettings structure +void BeagleRT_defaultSettings(BeagleRTInitSettings *settings) { // Set default values for settings settings->periodSize = 8; + settings->useAnalog = 1; + settings->useDigital = 1; + settings->numAnalogChannels = 8; + settings->numDigitalChannels = 16; + settings->beginMuted = 0; settings->dacLevel = DEFAULT_DAC_LEVEL; settings->adcLevel = DEFAULT_ADC_LEVEL; settings->headphoneLevel = DEFAULT_HP_LEVEL; - settings->useMatrix = 1; - settings->numMatrixChannels = 8; + settings->verbose = 0; + settings->pruFilename[0] = '\0'; + + // These two deliberately have no command-line flags by default. + // A given program might prefer one mode or another, but it's unlikely + // the user would want to switch at runtime + settings->interleave = 1; + settings->analogOutputsPersist = 1; + settings->codecI2CAddress = CODEC_I2C_ADDRESS; + settings->receivePort = 9998; + settings->transmitPort = 9999; + strcpy(settings->serverName, "127.0.0.1"); settings->ampMutePin = kAmplifierMutePin; } @@ -50,7 +78,7 @@ // be stored in settings, otherwise arguments will be returned // as getopt() normally does. -int BeagleRT_getopt_long(int argc, char *argv[], const char *customShortOptions, const struct option *customLongOptions, RTAudioSettings *settings) +int BeagleRT_getopt_long(int argc, char *argv[], const char *customShortOptions, const struct option *customLongOptions, BeagleRTInitSettings *settings) { static int firstRun = 1; static char totalShortOptions[256]; @@ -122,17 +150,31 @@ case 'v': settings->verbose = 1; break; - case 'm': - settings->useMatrix = atoi(optarg); + case 'N': + settings->useAnalog = atoi(optarg); + break; + case 'G': + settings->useDigital = atoi(optarg); + settings->numDigitalChannels = 0; break; case 'C': - settings->numMatrixChannels = atoi(optarg); - if(settings->numMatrixChannels >= 8) - settings->numMatrixChannels = 8; - else if(settings->numMatrixChannels >= 4) - settings->numMatrixChannels = 4; + settings->numAnalogChannels = atoi(optarg); + if(settings->numAnalogChannels >= 8) + settings->numAnalogChannels = 8; + else if(settings->numAnalogChannels >= 4) + settings->numAnalogChannels = 4; else - settings->numMatrixChannels = 2; + settings->numAnalogChannels = 2; + break; + case 'B': + settings->numDigitalChannels = atoi(optarg); + if(settings->numDigitalChannels >= 16) + settings->numDigitalChannels = 16; + else if (settings->numDigitalChannels < 1){ + settings->numDigitalChannels = 0; + settings->useDigital = 0; //TODO: this actually works only if -G 0 is specified after -g 1. + //No worries, though: disabling numDigital will only prevent the pins from being exported. + } break; case 'M': settings->beginMuted = atoi(optarg); @@ -146,6 +188,25 @@ case 'H': settings->headphoneLevel = atof(optarg); break; + case 'R': + settings->receivePort = atoi(optarg); + break; + case 'T': + settings->transmitPort = atoi(optarg); + break; + case 'S': + if(strlen(optarg)<MAX_SERVERNAME_LENGTH) + strcpy(settings->serverName, optarg); + else + std::cerr << "Warning: server name is too long (>" << MAX_SERVERNAME_LENGTH << " characters)." + " Using default severName Instead ( " << settings->serverName << " ).\n"; + break; + case OPT_PRU_FILE: + if(strlen(optarg) < MAX_PRU_FILENAME_LENGTH) + strcpy(settings->pruFilename, optarg); + else + std::cerr << "Warning: filename for the PRU code is too long (>" << MAX_PRU_FILENAME_LENGTH << " characters). Using embedded PRU code instead\n"; + break; case '?': default: return c; @@ -157,12 +218,19 @@ // Call from within your own usage function void BeagleRT_usage() { - std::cerr << " --period [-p] period: Set the hardware period (buffer) size in matrix samples\n"; - std::cerr << " --dac-level [-D] dBs: Set the DAC output level (0dB max; -63.5dB min)\n"; - std::cerr << " --adc-level [-A] dBs: Set the ADC input level (0dB max; -12dB min)\n"; - std::cerr << " --hp-level [-H] dBs: Set the headphone output level (0dB max; -63.5dB min)\n"; - std::cerr << " --mute-speaker [-M] val: Set whether to mute the speaker initially (default: no)\n"; - std::cerr << " --use-matrix [-m] val: Set whether to use ADC/DAC matrix\n"; - std::cerr << " --matrix-channels [-C] val: Set the number of ADC/DAC channels (default: 8)\n"; - std::cerr << " --verbose [-v]: Enable verbose logging information\n"; + std::cerr << " --period [-p] period: Set the hardware period (buffer) size in analog samples\n"; + std::cerr << " --dac-level [-D] dBs: Set the DAC output level (0dB max; -63.5dB min)\n"; + std::cerr << " --adc-level [-A] dBs: Set the ADC input level (0dB max; -12dB min)\n"; + std::cerr << " --hp-level [-H] dBs: Set the headphone output level (0dB max; -63.5dB min)\n"; + std::cerr << " --mute-speaker [-M] val: Set whether to mute the speaker initially (default: no)\n"; + std::cerr << " --use-analog [-N] val: Set whether to use ADC/DAC analog (default: yes)\n"; + std::cerr << " --use-digital [-G] val: Set whether to use digital GPIO channels (default: yes)\n"; + std::cerr << " --analog-channels [-C] val: Set the number of ADC/DAC channels (default: 8)\n"; + std::cerr << " --digital-channels [-B] val: Set the number of GPIO channels (default: 16)\n"; + std::cerr << " --receive-port [-R] val: Set the receive port (default: 9998)\n"; + std::cerr << " --transmit-port [-T] val: Set the transmit port (default: 9999)\n"; + std::cerr << " --server-name [-S] val: Set the destination server name (default: '127.0.0.1')\n"; + std::cerr << " --pru-file val: Set an optional external file to use for the PRU binary code\n"; + std::cerr << " --verbose [-v]: Enable verbose logging information\n"; } +
--- a/core/Utilities.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/core/Utilities.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -7,6 +7,84 @@ #include "../include/Utilities.h" +// analogReadFrame() +// +// Returns the value of the given analog input at the given frame number. +float analogReadFrame(BeagleRTContext *context, int frame, int channel) { + return context->analogIn[frame * context->analogChannels + channel]; +} + +// analogWriteFrame() +// +// Sets a given channel to a value for the current frame and, if persistent outputs are +// enabled, for all subsequent frames +void analogWriteFrame(BeagleRTContext *context, int frame, int channel, float value) { + if(context->flags & BEAGLERT_FLAG_ANALOG_OUTPUTS_PERSIST) { + for(unsigned int f = frame; f < context->analogFrames; f++) + context->analogOut[frame * context->analogChannels + channel] = value; + } + else + context->analogOut[frame * context->analogChannels + channel] = value; +} + +// analogWriteFrameOnce() +// +// Sets a given channel to a value for only the current frame +void analogWriteFrameOnce(BeagleRTContext *context, int frame, int channel, float value) { + context->analogOut[frame * context->analogChannels + channel] = value; +} + +// digitalReadFrame() +// +// Returns the value of a given digital input at the given frame number +int digitalReadFrame(BeagleRTContext *context, int frame, int channel) { + return getBit(context->digital[frame], channel + 16); +} + +// digitalWriteFrame() +// +// Sets a given digital output channel to a value for the current frame and all subsequent frames +void digitalWriteFrame(BeagleRTContext *context, int frame, int channel, int value) { + for(unsigned int f = frame; f < context->digitalFrames; f++) { + if(value) + context->digital[f] |= 1 << (channel + 16); + else + context->digital[f] &= ~(1 << (channel + 16)); + } +} + +// digitalWriteFrameOnce() +// +// Sets a given digital output channel to a value for the current frame only +void digitalWriteFrameOnce(BeagleRTContext *context, int frame, int channel, int value) { + if(value) + context->digital[frame] |= 1 << (channel + 16); + else + context->digital[frame] &= ~(1 << (channel + 16)); +} + +// pinModeFrame() +// +// Sets the direction of a digital pin for the current frame and all subsequent frames +void pinModeFrame(BeagleRTContext *context, int frame, int channel, int mode) { + for(unsigned int f = frame; f < context->digitalFrames; f++) { + if(mode) + context->digital[f] |= (1 << channel); + else + context->digital[f] &= ~(1 << channel); + } +} + +// pinModeFrameOnce() +// +// Sets the direction of a digital pin for the current frame only +void pinModeFrameOnce(BeagleRTContext *context, int frame, int channel, int mode) { + if(mode) + context->digital[frame] |= (1 << channel); + else + context->digital[frame] &= ~(1 << channel); +} + // map() // // Scale an input value from one range to another. Works like its Wiring language equivalent.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/client.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,129 @@ +///* UDP client in the internet domain */ + +#include <ctype.h> +#include <sys/time.h> +#include <fcntl.h> +#include "../include/client.h" +#include <unistd.h> +#include <rtdk.h> + +#define BUFF_LEN 1024 +#define MAX_VAR_STRING 20 + +struct sockaddr_in outServer, inServer; +int outSock, inSock, n, length; +socklen_t fromlen; +struct sockaddr_in from; +char inBuffer[1024]; +char variableString[MAX_VAR_STRING]; + +int setupSockets(int receivePort, int transmitPort, char const*serverName){ + //setup transmitter + printf("receivePort: %d; transmitPort: %d; serverName: %s\n",receivePort, transmitPort, serverName); + outSock= socket(AF_INET, SOCK_DGRAM, 0); + outServer.sin_port = htons(transmitPort); + if (outSock < 0){ + error("Opening out socket"); + return -1; + } + outServer.sin_family = AF_INET; + inet_pton(AF_INET,serverName,&outServer.sin_addr); + + //setup receiver + inSock=socket(AF_INET, SOCK_DGRAM, 0); + if (inSock < 0){ + return -1; + error("Opening in socket"); + } + length = sizeof(inServer); + inServer.sin_family=AF_INET; + inServer.sin_addr.s_addr=INADDR_ANY; + inServer.sin_port=htons(receivePort); + if (bind(inSock,(struct sockaddr *)&inServer,length)<0) + error("binding"); + fromlen = sizeof(struct sockaddr_in); + return 0; +} +int sendMessage(networkData message) +{ + unsigned int length; + char buffer[BUFF_LEN]; + length=sizeof(struct sockaddr_in); + int k=0; + k=sprintf(buffer+k, "%8d;",*message.counter); + for(int j=0; j<message.numVariables; j++){ + k+=sprintf(buffer+k, "%.3f;",*message.variables[j]); + if(k>BUFF_LEN - 20) //safety margin + continue; + } + sprintf(buffer+k,"\n"); + // printf(buffer); + n=sendto(outSock,buffer, + strlen(buffer),0,(const struct sockaddr *)&outServer,length); + if (n < 0) error("Sendto"); + return 0; +} +/* +int receiveMessage() +{ + int n = recvfrom(inSock,inBuffer,1024,0,(struct sockaddr *)&from,&fromlen); + if (n < 0) error("recvfrom"); + printf("Received a datagram: "); + printf(inBuffer); + } +*/ + + +int receiveMessage(networkData message){ + struct timeval stTimeOut; + fd_set stReadFDS; + FD_ZERO(&stReadFDS); + // Timeout of one second + stTimeOut.tv_sec = 0; + stTimeOut.tv_usec = 0; + FD_SET(inSock, &stReadFDS); + + int t = select(inSock+1, &stReadFDS, NULL, NULL, &stTimeOut); + if (t == -1) { + rt_fprintf(stderr, "Call to select() failed"); + return -1; + } + else if (t != 0) { + if (FD_ISSET(inSock, &stReadFDS)) { +// printf("There is data pending to be read..."); // Read data with recv() + int n = recvfrom(inSock,inBuffer,1024,0,(struct sockaddr *)&from,&fromlen); + if (n < 0){ + rt_fprintf(stderr,"Error while receiving"); + return -1; + } + printf("Received a datagram: "); + printf("%s", inBuffer); + //the worst parser ever + int previousN=0; + int currentVariable=0; + for(int n=0; inBuffer[n]!=0 && currentVariable<message.numVariables && n-previousN<MAX_VAR_STRING && n<BUFF_LEN; n++){ //scan the string + if(inBuffer[n]==';'||inBuffer[n]==0||inBuffer[n]=='\n'){ // if you find a separator or you are at the end of the string, parse the variable + int j=0; + inBuffer[n]=0; //set the semicolon to 0 ... + while( (variableString[j++]=inBuffer[previousN++]) );; // ... so that this will stop when it gets there + rt_printf("variable %d: %s\n", currentVariable, variableString); + *(message.variables[currentVariable])=atof(variableString); + n++; //increment to step after the semicolon + previousN=n; + currentVariable++; + } + } + } + } + return 0; +} + +void closeSockets(){ + close(outSock); + close(inSock); +} +void error(const char *msg) +{ + perror(msg); + exit(0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/default_main.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,91 @@ +/* + * default_main.cpp + * + * Created on: Oct 24, 2014 + * Author: parallels + */ +#include <unistd.h> +#include <iostream> +#include <cstdlib> +#include <libgen.h> +#include <signal.h> +#include <getopt.h> +#include "../include/BeagleRT.h" + +using namespace std; + +// Handle Ctrl-C by requesting that the audio rendering stop +void interrupt_handler(int var) +{ + gShouldStop = true; +} + +// Print usage information +void usage(const char * processName) +{ + cerr << "Usage: " << processName << " [options]" << endl; + + BeagleRT_usage(); + + cerr << " --help [-h]: Print this menu\n"; +} + +int main(int argc, char *argv[]) +{ + BeagleRTInitSettings settings; // Standard audio settings + + struct option customOptions[] = + { + {"help", 0, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + // Set default settings + BeagleRT_defaultSettings(&settings); + + // Parse command-line arguments + while (1) { + int c; + if ((c = BeagleRT_getopt_long(argc, argv, "h", customOptions, &settings)) < 0) + break; + switch (c) { + case 'h': + usage(basename(argv[0])); + exit(0); + case '?': + default: + usage(basename(argv[0])); + exit(1); + } + } + + // Initialise the PRU audio device + if(BeagleRT_initAudio(&settings, 0) != 0) { + cout << "Error: unable to initialise audio" << endl; + return -1; + } + + // Start the audio device running + if(BeagleRT_startAudio()) { + cout << "Error: unable to start real-time audio" << endl; + return -1; + } + + // Set up interrupt handler to catch Control-C and SIGTERM + signal(SIGINT, interrupt_handler); + signal(SIGTERM, interrupt_handler); + + // Run until told to stop + while(!gShouldStop) { + usleep(100000); + } + + // Stop the audio device + BeagleRT_stopAudio(); + + // Clean up any resources allocated for audio + BeagleRT_cleanupAudio(); + + // All done! + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/BeagleRT.h Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,569 @@ +/** + * @file + * @brief Main BeagleRT public API + * + * Central control code for hard real-time audio on BeagleBone Black + * using PRU and Xenomai Linux extensions. This code began as part + * of the Hackable Instruments project (EPSRC) at Queen Mary University + * of London, 2013-14. + * + * (c) 2014-15 Andrew McPherson, Victor Zappi and Giulio Moro, + * Queen Mary University of London + */ + +/** + * \mainpage + * + * BeagleRT is a hard-real-time, ultra-low latency audio and sensor environment for + * BeagleBone Black, which works with the BeagleBone Audio Cape or a custom "BeagleRT Cape" + * which incorporates stereo audio with 8x, 16-bit analog inputs and outputs. + * + * BeagleRT is based on the Xenomai real-time Linux extensions (http://xenomai.org) and + * uses the BeagleBone %PRU subsystem to address the audio and sensor hardware. + * + * Further information can be found at http://beaglert.cc + */ + + +#ifndef BEAGLERT_H_ +#define BEAGLERT_H_ + +#include <stdint.h> +#include <rtdk.h> +#include "digital_gpio_mapping.h" + +// Useful constants + +/** \cond PRIVATE */ +#define DBOX_CAPE // New custom cape +#ifdef DBOX_CAPE +#define CODEC_I2C_ADDRESS 0x18 // Address of TLV320AIC3104 codec +#else +#define CODEC_I2C_ADDRESS 0x1B // Address of TLV320AIC3106 codec +#endif + +#define MAX_PRU_FILENAME_LENGTH 256 +#define MAX_SERVERNAME_LENGTH 256 +/** \endcond */ + +/** + * \ingroup auxtask + * + * Xenomai priority level for audio processing. Maximum possible priority is 99. + * In general, all auxiliary tasks should have a level lower than this unless for\ + * special purposes where the task needs to interrupt audio processing. + */ +#define BEAGLERT_AUDIO_PRIORITY 95 + +// Default volume levels + +/** + * \addtogroup levels + * + * @{ + */ + +/** + * Default level of the audio DAC in decibels. See BeagleRT_setDACLevel(). + */ +#define DEFAULT_DAC_LEVEL 0.0 + +/** + * Default level of the audio ADC in decibels. See BeagleRT_setADCLevel(). + */ +#define DEFAULT_ADC_LEVEL -6.0 + +/** + * Default level of the headphone output in decibels. See BeagleRT_setHeadphoneLevel(). + */ +#define DEFAULT_HP_LEVEL -6.0 +/** @} */ + +/** + * Flag for BeagleRTContext. If set, indicates the audio and analog buffers are interleaved. + */ +#define BEAGLERT_FLAG_INTERLEAVED (1 << 0) // Set if buffers are interleaved +/** + * Flag for BeagleRTContext. If set, indicates analog outputs persist for future frames. + */ +#define BEAGLERT_FLAG_ANALOG_OUTPUTS_PERSIST (1 << 1) // Set if analog/digital outputs persist for future buffers + +/** + * \ingroup control + * \brief Structure containing initialisation parameters for the real-time + * audio control system. + * + * This structure is initialised using BeagleRT_defaultSettings(). Its contents + * are used up through the point of calling + * BeagleRT_initAudio() at which point it is no longer needed. + */ +typedef struct { + // These items might be adjusted by the user: + + /// \brief Number of (analog) frames per period. + /// + /// Number of audio frames depends on relative sample rates of the two. By default, + /// audio is twice the sample rate, so has twice the period size. + int periodSize; + /// Whether to use the analog input and output + int useAnalog; + /// Whether to use the 16 programmable GPIOs + int useDigital; + /// How many channels for the ADC and DAC + int numAnalogChannels; + /// How many channels for the GPIOs + int numDigitalChannels; + + /// Whether to begin with the speakers muted + int beginMuted; + /// Level for the audio DAC output + float dacLevel; + /// Level for the audio ADC input + float adcLevel; + /// Level for the headphone output + float headphoneLevel; + + /// The external .bin file to load. If empty will use PRU code from pru_rtaudio_bin.h + char pruFilename[MAX_PRU_FILENAME_LENGTH]; + /// Whether to use verbose logging + int verbose; + + // These items are application-dependent but should probably be + // determined by the programmer rather than the user + + /// Whether audio/analog data should be interleaved + int interleave; + /// \brief Whether analog outputs should persist to future frames. + /// + /// n.b. digital pins always persist, audio never does + int analogOutputsPersist; + + // These items are hardware-dependent and should only be changed + // to run on different hardware + + /// Where the codec can be found on the I2C bus + int codecI2CAddress; + /// Pin where amplifier mute can be found + int ampMutePin; + /// Port where the UDP server will listen + int receivePort; + /// Port where the UDP client will transmit + int transmitPort; + char serverName[MAX_SERVERNAME_LENGTH]; +} BeagleRTInitSettings; + + +/** + * \ingroup render + * \brief Structure holding current audio and sensor settings and pointers to data buffers. + * + * This structure is passed to setup(), render() and cleanup(). It is + * initialised in BeagleRT_initAudio() based on the contents of the BeagleRTInitSettings + * structure. + */ +typedef struct { + /// \brief Buffer holding audio input samples + /// + /// This buffer may be in either interleaved or non-interleaved format, + /// depending on the contents of the BeagleRTInitSettings structure. + /// \b Note: this element is available in render() only. + float *audioIn; + + /// \brief Buffer holding audio output samples + /// + /// This buffer may be in either interleaved or non-interleaved format, + /// depending on the contents of the BeagleRTInitSettings structure. + /// \b Note: this element is available in render() only. + float *audioOut; + + /// \brief Buffer holding analog input samples + /// + /// This buffer may be in either interleaved or non-interleaved format, + /// depending on the contents of the BeagleRTInitSettings structure. + /// \b Note: this element is available in render() only. + float *analogIn; + + /// \brief Buffer holding analog output samples + /// + /// This buffer may be in either interleaved or non-interleaved format, + /// depending on the contents of the BeagleRTInitSettings structure. + /// \b Note: this element is available in render() only. + float *analogOut; + + /// \brief Buffer holding digital input/output samples + /// + /// \b Note: this element is available in render() only. + uint32_t *digital; + + /// Number of audio frames per period + uint32_t audioFrames; + /// Number of audio channels (currently always 2) + uint32_t audioChannels; + /// Audio sample rate in Hz (currently always 44100.0) + float audioSampleRate; + + /// \brief Number of analog frames per period + /// + /// This will be 0 if analog I/O is disabled. + uint32_t analogFrames; + + /// \brief Number of analog channels + /// + /// This could take a value of 8, 4 or 2. This will be 0 if analog I/O is disabled. + uint32_t analogChannels; + + /// \brief Analog sample rate in Hz + /// + /// The analog sample rate depends on the number of analog channels used. If + /// 8 channels are used, the sample rate is 22050. If 4 channels are used, the sample + /// rate is 44100. If 2 channels are used, the sample rate is 88200. If analog I/O + /// is disabled, the sample rate is 0. + float analogSampleRate; + + /// Number of digital frames per period + uint32_t digitalFrames; + /// \brief Number of digital channels + /// + /// Currently this will always be 16, unless digital I/O is disabled, in which case it will be 0. + uint32_t digitalChannels; + /// Digital sample rate in Hz (currently always 44100.0) + float digitalSampleRate; + + /// \brief Number of elapsed audio samples since the start of rendering. + /// + /// This holds the total number of audio samples as of the beginning of the current period. To + /// find the current number of analog or digital samples elapsed, multiply by the ratio of the + /// sample rates (e.g. half the number of analog samples will have elapsed if the analog sample + /// rate is 22050). + uint64_t audioSampleCount; + + /// \brief Other audio/sensor settings + /// + /// Binary combination of flags including: + /// + /// BEAGLERT_FLAG_INTERLEAVED: indicates the audio and analog buffers are interleaved + /// + /// BEAGLERT_FLAG_ANALOG_OUTPUTS_PERSIST: indicates that writes to the analog outputs will + /// persist for future frames. If not set, writes affect one frame only. + uint32_t flags; +} BeagleRTContext; + +/** \ingroup auxtask + * + * Auxiliary task variable. Auxiliary tasks are created using createAuxiliaryTask() and + * automatically cleaned up after cleanup() finishes. + */ +typedef void* AuxiliaryTask; // Opaque data type to keep track of aux tasks + +/** \ingroup render + * + * Flag that indicates when the audio will stop. Threads can poll this variable to indicate when + * they should stop. Additionally, a program can set this to \c true + * to indicate that audio processing should terminate. Calling BeagleRT_stopAudio() + * has the effect of setting this to \c true. + */ +extern bool gShouldStop; + +// *** User-defined render functions *** + +/** + * \defgroup render User-defined render functions + * + * These three functions must be implemented by the developer in every BeagleRT program. + * Typically they appear in their own .cpp source file. + * + * @{ + */ + +/** + * \brief User-defined initialisation function which runs before audio rendering begins. + * + * This function runs once at the beginning of the program, after most of the system + * initialisation has begun but before audio rendering starts. Use it to prepare any + * memory or resources that will be needed in render(). + * + * \param context Data structure holding information on sample rates, numbers of channels, + * frame sizes and other state. Note: the buffers for audio, analog and digital data will + * \b not yet be available to use. Do not attempt to read or write audio or sensor data + * in setup(). + * \param userData An opaque pointer to an optional user-defined data structure. Whatever + * is passed as the second argument to BeagleRT_initAudio() will appear here. + * + * \return true on success, or false if an error occurred. If no initialisation is + * required, setup() should return true. + */ +bool setup(BeagleRTContext *context, void *userData); + +/** + * \brief User-defined callback function to process audio and sensor data. + * + * This function is called regularly by the system every time there is a new block of + * audio and/or sensor data to process. Your code should process the requested samples + * of data, store the results within \c context, and return. + * + * \param context Data structure holding buffers for audio, analog and digital data. The + * structure also holds information on numbers of channels, frame sizes and sample rates, + * which are guaranteed to remain the same throughout the program and to match what was + * passed to setup(). + * \param userData An opaque pointer to an optional user-defined data structure. Will + * be the same as the \c userData parameter passed to setup(). + */ +void render(BeagleRTContext *context, void *userData); + +/** + * \brief User-defined cleanup function which runs when the program finishes. + * + * This function is called by the system once after audio rendering has finished, before the + * program quits. Use it to release any memory allocated in setup() and to perform + * any other required cleanup. If no initialisation is performed in setup(), then + * this function will usually be empty. + * + * \param context Data structure holding information on sample rates, numbers of channels, + * frame sizes and other state. Note: the buffers for audio, analog and digital data will + * no longer be available to use. Do not attempt to read or write audio or sensor data + * in cleanup(). + * \param userData An opaque pointer to an optional user-defined data structure. Will + * be the same as the \c userData parameter passed to setup() and render(). + */ +void cleanup(BeagleRTContext *context, void *userData); + +/** @} */ + +/** + * \defgroup control Control and command line functions + * + * These functions are used to initialise the BeagleRT settings, process arguments + * from the command line, and start/stop the audio and sensor system. + * + * @{ + */ + +// *** Command-line settings *** + +/** + * \brief Initialise the data structure containing settings for BeagleRT. + * + * This function should be called in main() before parsing any command-line arguments. It + * sets default values in the data structure which specifies the BeagleRT settings, including + * frame sizes, numbers of channels, volume levels and other parameters. + * + * \param settings Structure holding initialisation data for BeagleRT. + */ +void BeagleRT_defaultSettings(BeagleRTInitSettings *settings); + +/** + * \brief Get long options from command line argument list, including BeagleRT standard options + * + * This function should be used in main() to process command line options, in place of the + * standard library getopt_long(). Internally, it parses standard BeagleRT command-line options, + * storing the results in the settings data structure. Any options which are not part of the + * BeagleRT standard options will be returned, as they would normally be in getopt_long(). + * + * \param argc Number of command line options, as passed to main(). + * \param argv Array of command line options, as passed to main(). + * \param customShortOptions List of short options to be parsed, analogous to getopt_long(). This + * list should not include any characters already parsed as part of the BeagleRT standard options. + * \param customLongOptions List of long options to parsed, analogous to getopt_long(). This + * list should not include any long options already parsed as part of the BeagleRT standard options. + * \param settings Data structure holding initialisation settings for BeagleRT. Any standard options + * parsed will automatically update this data structure. + * + * \return Value of the next option parsed which is not a BeagleRT standard option, or -1 when the + * argument list has been exhausted. Similar to the return value of getopt_long() except that BeagleRT + * standard options are handled internally and not returned. + */ +int BeagleRT_getopt_long(int argc, char *argv[], const char *customShortOptions, + const struct option *customLongOptions, BeagleRTInitSettings *settings); + +/** + * \brief Print usage information for BeagleRT standard options. + * + * This function should be called from your code wherever you wish to print usage information for the + * user. It will print usage information on BeagleRT standard options, after which you can print usage + * information for your own custom options. + */ +void BeagleRT_usage(); + +/** + * \brief Set level of verbose (debugging) printing. + * + * \param level Verbosity level of the internal BeagleRT system. 0 by default; higher values will + * print more information. Presently all positive numbers produce the same level of printing. + */ +void BeagleRT_setVerboseLevel(int level); + + +// *** Audio control functions *** + +/** + * \brief Initialise audio and sensor rendering environment. + * + * This function prepares audio rendering in BeagleRT. It should be called from main() sometime + * after command line option parsing has finished. It will initialise the rendering system, which + * in the process will result in a call to the user-defined setup() function. + * + * \param settings Data structure holding system settings, including numbers of channels, frame sizes, + * volume levels and other information. + * \param userData An opaque pointer to a user-defined data structure which will be passed to + * setup(), render() and cleanup(). You can use this to pass custom information + * to the rendering functions, as an alternative to using global variables. + * + * \return 0 on success, or nonzero if an error occurred. + */ +int BeagleRT_initAudio(BeagleRTInitSettings *settings, void *userData); + +/** + * \brief Begin processing audio and sensor data. + * + * This function will start the BeagleRT audio/sensor system. After this function is called, the + * system will make periodic calls to render() until BeagleRT_stopAudio() is called. + * + * \return 0 on success, or nonzero if an error occurred. + */ +int BeagleRT_startAudio(); + +/** + * \brief Stop processing audio and sensor data. + * + * This function will stop the BeagleRT audio/sensor system. After this function returns, no further + * calls to render() will be issued. + */ +void BeagleRT_stopAudio(); + +/** + * \brief Clean up resources from audio and sensor processing. + * + * This function should only be called after BeagleRT_stopAudio(). It will release any + * internal resources for audio and sensor processing. In the process, it will call the + * user-defined cleanup() function. + */ +void BeagleRT_cleanupAudio(); + +/** @} */ + +/** + * \defgroup levels Audio level controls + * + * These functions control the input and output levels for the audio codec. If a BeagleRT program + * does not call these functions, sensible default levels will be used. + * + * @{ + */ + +// *** Volume and level controls *** + +/** + * \brief Set the level of the audio DAC. + * + * This function sets the level of all audio outputs (headphone, line, speaker). It does + * not affect the level of the (non-audio) analog outputs. + * + * \b Important: do not call this function from within render(), as it does not make + * any guarantees on real-time performance. + * + * \param decibels Level of the DAC output. Valid levels range from -63.5 (lowest) to + * 0 (highest) in steps of 0.5dB. Levels between increments of 0.5 will be rounded down. + * + * \return 0 on success, or nonzero if an error occurred. + */ +int BeagleRT_setDACLevel(float decibels); + +/** + * \brief Set the level of the audio ADC. + * + * This function sets the level of the audio input. It does not affect the level of the + * (non-audio) analog inputs. + * + * \b Important: do not call this function from within render(), as it does not make + * any guarantees on real-time performance. + * + * \param decibels Level of the ADC input. Valid levels range from -12 (lowest) to + * 0 (highest) in steps of 1.5dB. Levels between increments of 1.5 will be rounded down. + * + * \return 0 on success, or nonzero if an error occurred. + */ +int BeagleRT_setADCLevel(float decibels); + +/** + * \brief Set the level of the onboard headphone amplifier. + * + * This function sets the level of the headphone output only (3-pin connector on the BeagleRT + * cape or the output jack on the BeagleBone Audio Cape). It does not affect the level of the + * speakers or the line out pads on the cape. + * + * \b Important: do not call this function from within render(), as it does not make + * any guarantees on real-time performance. + * + * \param decibels Level of the DAC output. Valid levels range from -63.5 (lowest) to + * 0 (highest) in steps of 0.5dB. Levels between increments of 0.5 will be rounded down. + * + * \return 0 on success, or nonzero if an error occurred. + */ +int BeagleRT_setHeadphoneLevel(float decibels); + +/** + * \brief Mute or unmute the onboard speaker amplifiers. + * + * This function mutes or unmutes the amplifiers on the BeagleRT cape. Whether the speakers begin + * muted or unmuted depends on the BeagleRTInitSettings structure passed to BeagleRT_initAudio(). + * + * \b Important: do not call this function from within render(), as it does not make + * any guarantees on real-time performance. + * + * \param mute 0 to enable the speakers, nonzero to mute the speakers. + * + * \return 0 on success, or nonzero if an error occurred. + */ +int BeagleRT_muteSpeakers(int mute); + +/** @} */ + +/** + * \defgroup auxtask Auxiliary task support + * + * These functions are used to create separate real-time tasks (threads) which run at lower + * priority than the audio processing. They can be used, for example, for large time-consuming + * calculations which would take more than one audio frame length to process, or they could be + * used to communicate with external hardware when that communication might block or be delayed. + * + * All auxiliary tasks used by the program should be created in setup(). The tasks + * can then be scheduled at will within the render() function. + * + * @{ + */ + +// *** Functions for creating auxiliary tasks *** + +/** + * \brief Create a new auxiliary task. + * + * This function creates a new auxiliary task which, when scheduled, runs the function specified + * in the first argument. Note that the task does not run until scheduleAuxiliaryTask() is called. + * Auxiliary tasks should be created in setup() and never in render() itself. + * + * The second argument specifies the real-time priority. Valid values are between 0 + * and 99, and usually should be lower than \ref BEAGLERT_AUDIO_PRIORITY. Tasks with higher priority always + * preempt tasks with lower priority. + * + * \param functionToCall Function which will run each time the auxiliary task is scheduled. + * \param priority Xenomai priority level at which the task should run. + * \param name Name for this task, which should be unique system-wide (no other running program should use this name). + */ +AuxiliaryTask BeagleRT_createAuxiliaryTask(void (*functionToCall)(void), int priority, const char *name); + +/** + * \brief Run an auxiliary task which has previously been created. + * + * This function will schedule an auxiliary task to run. When the task runs, the function in the first + * argument of createAuxiliaryTaskLoop() will be called. + * + * scheduleAuxiliaryTask() is typically called from render() to start a lower-priority task. The function + * will not run immediately, but only once any active higher priority tasks have finished. + * + * \param task Task to schedule for running. + */ +void BeagleRT_scheduleAuxiliaryTask(AuxiliaryTask task); + +/** @} */ + +#endif /* BEAGLERT_H_ */
--- a/include/PRU.h Sun Feb 08 00:20:01 2015 +0000 +++ b/include/PRU.h Fri Jul 17 15:28:18 2015 +0100 @@ -9,6 +9,8 @@ #define PRU_H_ #include <stdint.h> +#include <native/intr.h> +#include "../include/BeagleRT.h" class PRU { @@ -21,26 +23,26 @@ public: // Constructor - PRU(); + PRU(BeagleRTContext *input_context); // Destructor ~PRU(); // Prepare the GPIO pins needed for the PRU - int prepareGPIO(int use_spi, int include_test_pin, int include_led); + int prepareGPIO(int include_test_pin, int include_led); // Clean up the GPIO at the end void cleanupGPIO(); // Initialise and open the PRU - int initialise(int pru_num, int frames_per_buffer, int spi_channels, - bool xenomai_test_pin = false); + int initialise(int pru_num, int frames_per_buffer, + int spi_channels, bool xenomai_test_pin = false); // Run the code image in pru_rtaudio_bin.h - int start(); + int start(char * const filename); // Loop: read and write data from the PRU - void loop(); + void loop(RT_INTR *pru_interrupt, void *userData); // Wait for an interrupt from the PRU indicate it is finished void waitForFinish(); @@ -53,21 +55,22 @@ void clearGPIOTestPin(); private: + BeagleRTContext *context; // Overall settings + int pru_number; // Which PRU we use bool running; // Whether the PRU is running - bool spi_enabled; // Whether SPI ADC and DAC are used + bool analog_enabled; // Whether SPI ADC and DAC are used + bool digital_enabled; // Whether digital is used bool gpio_enabled; // Whether GPIO has been prepared bool led_enabled; // Whether a user LED is enabled bool gpio_test_pin_enabled; // Whether the test pin was also enabled - int spi_num_channels; // How many channels to use for SPI ADC/DAC volatile uint32_t *pru_buffer_comm; uint16_t *pru_buffer_spi_dac; uint16_t *pru_buffer_spi_adc; + uint32_t *pru_buffer_digital; int16_t *pru_buffer_audio_dac; int16_t *pru_buffer_audio_adc; - unsigned int spi_buffer_frames; - unsigned int audio_buffer_frames; int xenomai_gpio_fd; // File descriptor for /dev/mem for fast GPIO uint32_t *xenomai_gpio; // Pointer to GPIO registers
--- a/include/RTAudio.h Sun Feb 08 00:20:01 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -/* - * RTAudio.h - * - * Central control code for hard real-time audio on BeagleBone Black - * using PRU and Xenomai Linux extensions. This code began as part - * of the Hackable Instruments project (EPSRC) at Queen Mary University - * of London, 2013-14. - * - * (c) 2014 Victor Zappi and Andrew McPherson - * Queen Mary University of London - */ - - -#ifndef RTAUDIO_H_ -#define RTAUDIO_H_ - -#include "render.h" - -// Useful constants -#define DBOX_CAPE // New custom cape - -#ifdef DBOX_CAPE -#define CODEC_I2C_ADDRESS 0x18 // Address of TLV320AIC3104 codec -#else -#define CODEC_I2C_ADDRESS 0x1B // Address of TLV320AIC3106 codec -#endif - -// Default volume levels -#define DEFAULT_DAC_LEVEL 0.0 -#define DEFAULT_ADC_LEVEL -6.0 -#define DEFAULT_HP_LEVEL -6.0 - -enum { - kAmplifierMutePin = 61 // P8-26 controls amplifier mute -}; - -// Structure which contains initialisation parameters for the -// real-time audio system -typedef struct { - // These items might be adjusted by the user: - int periodSize; // Number of (matrix) frames per period; audio is twice this - int beginMuted; // Whether to begin with the speakers muted - float dacLevel; // Level for the audio DAC output - float adcLevel; // Level for the audio ADC input - float headphoneLevel; // Level for the headphone output - int useMatrix; // Whether to use the matrix - int numMatrixChannels; // How many channels for the ADC and DAC - int verbose; // Whether to use verbose logging - - // These items are hardware-dependent and should only be changed - // to run on different hardware - int codecI2CAddress; // Where the codec can be found on the I2C bus - int ampMutePin; // Pin where amplifier mute can be found -} RTAudioSettings; - -typedef void* AuxiliaryTask; // Opaque data type to keep track of aux tasks - -// Flag that indicates when the audio will stop; can be read or -// set by other components which should end at the same time as the audio -extern bool gShouldStop; - -// Command-line settings -void BeagleRT_defaultSettings(RTAudioSettings *settings); -int BeagleRT_getopt_long(int argc, char *argv[], const char *customShortOptions, - const struct option *customLongOptions, RTAudioSettings *settings); -void BeagleRT_usage(); - -// Basic audio control functions: init, start, stop and clean up -int BeagleRT_initAudio(RTAudioSettings *settings, void *userData); -int BeagleRT_startAudio(); -void BeagleRT_stopAudio(); -void BeagleRT_cleanupAudio(); - -// Volume/level controls -// These return 0 on success - -// Set the level of the DAC; affects all outputs (headphone, line, speaker) -// 0dB is the maximum, -63.5dB is the minimum; 0.5dB steps -int BeagleRT_setDACLevel(float decibels); - -// Set the level of the ADC -// 0dB is the maximum, -12dB is the minimum; 1.5dB steps -int BeagleRT_setADCLevel(float decibels); - -// Set the level of the onboard headphone amplifier; affects headphone -// output only (not line out or speaker) -// 0dB is the maximum, -63.5dB is the minimum; 0.5dB steps -int BeagleRT_setHeadphoneLevel(float decibels); - -// Mute or unmute the onboard speaker amplifiers -// mute == 0 means unmute; otherwise mute -// Returns 0 on success -int BeagleRT_muteSpeakers(int mute); - -// Functions for creating auxiliary tasks -AuxiliaryTask createAuxiliaryTaskLoop(void (*functionToCall)(void), int priority, const char *name); -void scheduleAuxiliaryTask(AuxiliaryTask task); - -void setVerboseLevel(int level); - -#endif /* RTAUDIO_H_ */
--- a/include/Utilities.h Sun Feb 08 00:20:01 2015 +0000 +++ b/include/Utilities.h Fri Jul 17 15:28:18 2015 +0100 @@ -1,24 +1,120 @@ -/* - * Utilities.h +/** + * @file + * @brief Wiring-inspired utility functions and macros * - * Created on: Oct 27, 2014 - * Author: parallels + * Macros and functions for I/O and data processing taking after the Wiring + * (Arduino) language. This code began as part of the Hackable Instruments + * project (EPSRC) at Queen Mary University of London, 2013-14. + * + * (c) 2014-15 Andrew McPherson, Victor Zappi and Giulio Moro, + * Queen Mary University of London */ #ifndef UTILITIES_H_ #define UTILITIES_H_ -extern int gNumAudioChannels; // How many audio channels are present -extern int gNumMatrixChannels; // How many matrix channels are present +#include "BeagleRT.h" -// Macros for accessing the matrix values: usable _only_ within render() +/// Set the given bit in \c word to 1. +#define setBit(word,bit) ((word) | (1 << (bit))) -// Read an analog input from input pin p at frame f -#define analogRead(p, f) (matrixIn[(f)*gNumMatrixChannels + (p)]) -// Write an analog output frame at output pin p, frame f, to value v -#define analogWrite(p, f, v) (matrixOut[(f)*gNumMatrixChannels + (p)] = (uint16_t)(v)) +/// Clear the given bit in \c word to 0. +#define clearBit(word,bit) ((word) &~ (1 << (bit))) +/// Check if the given bit in \c word is 1 (returns nonzero) or 0 (returns zero). +#define getBit(word,bit) (((word) >> (bit)) & 1) + +/// Set/clear the given bit in \c word to \c value. +#define changeBit(word,bit,value) ((clearBit((word),(bit))) | ((value) << (bit))) + +#if 1 +// Note: pinMode(), analogWrite() and digitalWrite() should be able to be called from setup() +// Likewise, thread launch should be able to be called from setup() +// Also, make volume change functions callable from render() thread -- as an aux task? + +float analogReadFrame(BeagleRTContext *context, int frame, int channel); +void analogWriteFrame(BeagleRTContext *context, int frame, int channel, float value); +void analogWriteFrameOnce(BeagleRTContext *context, int frame, int channel, float value); + +int digitalReadFrame(BeagleRTContext *context, int frame, int channel); +void digitalWriteFrame(BeagleRTContext *context, int frame, int channel, int value); +void digitalWriteFrameOnce(BeagleRTContext *context, int frame, int channel, int value); + +void pinModeFrame(BeagleRTContext *context, int frame, int channel, int mode); +void pinModeFrameOnce(BeagleRTContext *context, int frame, int channel, int mode); + +#else + +// Macros for accessing the analog values: usable _only_ within render() + +// Read an Analog input from input pin p at frame f +#define analogRead(p, f) (analogIn[(f)*gNumAnalogChannels + (p)]) +// Write an Analog output frame at output pin p, frame f, to value v +#define analogWriteFrame(p, f, v) (analogOut[(f)*gNumAnalogChannels + (p)] = (v)) +#define analogWrite(pin, frame, value) \ +(({do {\ + for (int _privateI=(frame); _privateI<numAnalogFrames; _privateI++){ \ + analogWriteFrame(pin,_privateI,value); \ + }\ + } while (0);}),(void)0)\ + + +//digital API: +#define setDigitalDirectionFrame(pin,frame,direction) digital[(frame)]=changeBit(digital[(frame)],(pin),(direction)),void(0) +#define setDigitalDirection(pin,frame,direction)\ + (({do {\ + for(int _privateI=(frame); _privateI<numDigitalFrames; _privateI++)\ + setDigitalDirectionFrame(pin,_privateI,direction);\ + } while (0);}), (void)0) +#define digitalWriteAll(frame,value) digital[(frame)]=0xffff0000*(!(!value)); +//sets the bit in the high word, clears the bit in the low word (just in case the direction was not previously set) +#define digitalWriteFrame(pin, frame, value) digital[(frame)]=( changeBit(digital[(frame)], (pin+16), (value)) & (0xffffffff-(1<<(pin))) ) //could have been done with two subsequent assignments +#define digitalWrite(pin, frame, value) \ + (({do {\ + for (int _privateI=(frame); _privateI<numDigitalFrames; _privateI++) \ + digitalWriteFrame(pin,_privateI,value); \ + } while (0);}),(void)0)\ + +#define digitalRead(pin, frame) ( getBit(digital[(frame)], pin+16) ) + +#endif + +/** + * \brief Linearly rescale a number from one range of values to another. + * + * This function linearly scales values of \c x such that the range in_min to + * in_max at the input corresponds to the range out_min to out_max + * at the output. Values outside this range are extrapolated. + * + * This function behaves identically to the function of the same name in Processing. It + * is also similar to the corresponding function in Arduino, except that it supports floating + * point values. + * + * \param x Input value to be mapped. + * \param in_min Lower bound of the input range. + * \param in_max Upper bound of the input range. + * \param out_min Lower bound of the output range. + * \param out_max Upper bound of the output range. + * \return Rescaled value. + */ float map(float x, float in_min, float in_max, float out_min, float out_max); + +/** + * \brief Constrain a number to stay within a given range. + * + * This function constrains \c x to remain within the range min_val to + * max_val. Values of \c x outside this range are clipped to the edges + * of the range. + * + * This function behaves identically to the function of the same name in Processing. It + * is also similar to the corresponding function in Arduino, except that it supports floating + * point values. + * + * \param x Input value to be constrained. + * \param min_val Minimum possible value. + * \param max_val Maximum possible value. + * \return Constrained value. + */ float constrain(float x, float min_val, float max_val); #endif /* UTILITIES_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/client.h Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,22 @@ +/* UDP client in the internet domain */ +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +struct networkData{ + int *counter; + float *variables[16]; + int numVariables; +}; + +void error(const char *); +int setupSockets(int receivePort, int transmitPort, char const*serverName); +int sendMessage(networkData message); +int receiveMessage(networkData message); +void closeSockets();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/digital_gpio_mapping.h Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,72 @@ +#ifndef DIGITAL_MAPPING_H +#define DIGITAL_MAPPING_H + +#define NUM_DIGITALS 16 +extern short int digitalPins[NUM_DIGITALS]; +//GPIO_INPUT and GPIO_OUTPUT values when calling the setDigitalDirection() macro. +//TODO: these are inverted with respect to INPUT_PIN and OUTPUT_PIN defined in GPIOcontrol.h, +//which might lead to unexpected results in case someone uses those in place of these or viceversa +#define GPIO_INPUT 1 +#define GPIO_OUTPUT 0 +#define GPIO_HIGH 1 +#define GPIO_LOW 0 +//mapping GPIO numbers to header pins +//if you want to use different pins/ordering, define here new pins. The ordering here is NOT binding +#define P8_07_GPIO_NO 66 +#define P8_08_GPIO_NO 67 +#define P8_09_GPIO_NO 69 +#define P8_10_GPIO_NO 68 +#define P8_11_GPIO_NO 45 +#define P8_12_GPIO_NO 44 +#define P9_12_GPIO_NO 60 +#define P9_14_GPIO_NO 50 +#define P8_15_GPIO_NO 47 +#define P8_16_GPIO_NO 46 +#define P9_16_GPIO_NO 51 +#define P8_18_GPIO_NO 65 +#define P8_27_GPIO_NO 86 +#define P8_28_GPIO_NO 88 +#define P8_29_GPIO_NO 87 +#define P8_30_GPIO_NO 89 + +//mapping pin headers to bits in the digital word. +//used in the declaration of short int digitalPins[NUM_DIGITALS] below, which is used in PRU::prepareGPIO to export the pins +//if you want to use different pins, declare them above and use them here +//The ordering here is NOT binding, but if you want to use a different ordering, please change it here as well as below and in the PRU, for consistency +#define GPIO_NO_BIT_0 P8_07_GPIO_NO +#define GPIO_NO_BIT_1 P8_08_GPIO_NO +#define GPIO_NO_BIT_2 P8_09_GPIO_NO +#define GPIO_NO_BIT_3 P8_10_GPIO_NO +#define GPIO_NO_BIT_4 P8_11_GPIO_NO +#define GPIO_NO_BIT_5 P8_12_GPIO_NO +#define GPIO_NO_BIT_6 P9_12_GPIO_NO +#define GPIO_NO_BIT_7 P9_14_GPIO_NO +#define GPIO_NO_BIT_8 P8_15_GPIO_NO +#define GPIO_NO_BIT_9 P8_16_GPIO_NO +#define GPIO_NO_BIT_10 P9_16_GPIO_NO +#define GPIO_NO_BIT_11 P8_18_GPIO_NO +#define GPIO_NO_BIT_12 P8_27_GPIO_NO +#define GPIO_NO_BIT_13 P8_28_GPIO_NO +#define GPIO_NO_BIT_14 P8_29_GPIO_NO +#define GPIO_NO_BIT_15 P8_30_GPIO_NO + +//mapping bits in the digital word to pin headers, so that pin header name can be used instead of but number +//The ordering here IS binding. If you want to use different pins/ordering, please do it above as well as here and in the PRU, for consistency +#define P8_07 0 +#define P8_08 1 +#define P8_09 2 +#define P8_10 3 +#define P8_11 4 +#define P8_12 5 +#define P9_12 6 +#define P9_14 7 +#define P8_15 8 +#define P8_16 9 +#define P9_16 10 +#define P8_18 11 +#define P8_27 12 +#define P8_28 13 +#define P8_29 14 +#define P8_30 15 + +#endif
--- a/include/pru_rtaudio_bin.h Sun Feb 08 00:20:01 2015 +0000 +++ b/include/pru_rtaudio_bin.h Fri Jul 17 15:28:18 2015 +0100 @@ -5,6 +5,276 @@ /* This file is generated by the PRU assembler. */ const unsigned int PRUcode[] = { + 0x7b00000e, + 0x244804c2, + 0x24c13482, + 0xf1002282, + 0x240000e8, + 0x240000e7, + 0xd104fb07, + 0x1d0de2e2, + 0xc914fb03, + 0x1f0de8e8, + 0x79000005, + 0x1f0de7e7, + 0x79000003, + 0x1f0de2e2, + 0x79000001, + 0xd105fb07, + 0x1d0ce2e2, + 0xc915fb03, + 0x1f0ce8e8, + 0x79000005, + 0x1f0ce7e7, + 0x79000003, + 0x1f0ce2e2, + 0x79000001, + 0xd106fb07, + 0x1d1ce2e2, + 0xc916fb03, + 0x1f1ce8e8, + 0x79000005, + 0x1f1ce7e7, + 0x79000003, + 0x1f1ce2e2, + 0x79000001, + 0xd107fb07, + 0x1d12e2e2, + 0xc917fb03, + 0x1f12e8e8, + 0x79000005, + 0x1f12e7e7, + 0x79000003, + 0x1f12e2e2, + 0x79000001, + 0xd108fb07, + 0x1d0fe2e2, + 0xc918fb03, + 0x1f0fe8e8, + 0x79000005, + 0x1f0fe7e7, + 0x79000003, + 0x1f0fe2e2, + 0x79000001, + 0xd109fb07, + 0x1d0ee2e2, + 0xc919fb03, + 0x1f0ee8e8, + 0x79000005, + 0x1f0ee7e7, + 0x79000003, + 0x1f0ee2e2, + 0x79000001, + 0xd10afb07, + 0x1d13e2e2, + 0xc91afb03, + 0x1f13e8e8, + 0x79000005, + 0x1f13e7e7, + 0x79000003, + 0x1f13e2e2, + 0x79000001, + 0x244804c3, + 0x24c13483, + 0xe1002382, + 0x24481ac3, + 0x24c13483, + 0xf1002383, + 0x240000e5, + 0x240000e4, + 0xd100fb07, + 0x1d02e3e3, + 0xc910fb03, + 0x1f02e5e5, + 0x79000005, + 0x1f02e4e4, + 0x79000003, + 0x1f02e3e3, + 0x79000001, + 0xd101fb07, + 0x1d03e3e3, + 0xc911fb03, + 0x1f03e5e5, + 0x79000005, + 0x1f03e4e4, + 0x79000003, + 0x1f03e3e3, + 0x79000001, + 0xd102fb07, + 0x1d05e3e3, + 0xc912fb03, + 0x1f05e5e5, + 0x79000005, + 0x1f05e4e4, + 0x79000003, + 0x1f05e3e3, + 0x79000001, + 0xd103fb07, + 0x1d04e3e3, + 0xc913fb03, + 0x1f04e5e5, + 0x79000005, + 0x1f04e4e4, + 0x79000003, + 0x1f04e3e3, + 0x79000001, + 0xd10bfb07, + 0x1d01e3e3, + 0xc91bfb03, + 0x1f01e5e5, + 0x79000005, + 0x1f01e4e4, + 0x79000003, + 0x1f01e3e3, + 0x79000001, + 0xd10cfb07, + 0x1d16e3e3, + 0xc91cfb03, + 0x1f16e5e5, + 0x79000005, + 0x1f16e4e4, + 0x79000003, + 0x1f16e3e3, + 0x79000001, + 0xd10dfb07, + 0x1d18e3e3, + 0xc91dfb03, + 0x1f18e5e5, + 0x79000005, + 0x1f18e4e4, + 0x79000003, + 0x1f18e3e3, + 0x79000001, + 0xd10efb07, + 0x1d17e3e3, + 0xc91efb03, + 0x1f17e5e5, + 0x79000005, + 0x1f17e4e4, + 0x79000003, + 0x1f17e3e3, + 0x79000001, + 0xd10ffb07, + 0x1d19e3e3, + 0xc91ffb03, + 0x1f19e5e5, + 0x79000005, + 0x1f19e4e4, + 0x79000003, + 0x1f19e3e3, + 0x79000001, + 0x24481ac2, + 0x24c13482, + 0xe1002283, + 0x244804c2, + 0x24c13882, + 0x24481ac3, + 0x24c13883, + 0xf1002282, + 0xf1002383, + 0xc904fb06, + 0xc90de203, + 0x1f14fbfb, + 0x79000003, + 0x1d14fbfb, + 0x79000001, + 0xc905fb06, + 0xc90ce203, + 0x1f15fbfb, + 0x79000003, + 0x1d15fbfb, + 0x79000001, + 0xc906fb06, + 0xc91ce203, + 0x1f16fbfb, + 0x79000003, + 0x1d16fbfb, + 0x79000001, + 0xc907fb06, + 0xc912e203, + 0x1f17fbfb, + 0x79000003, + 0x1d17fbfb, + 0x79000001, + 0xc908fb06, + 0xc90fe203, + 0x1f18fbfb, + 0x79000003, + 0x1d18fbfb, + 0x79000001, + 0xc909fb06, + 0xc90ee203, + 0x1f19fbfb, + 0x79000003, + 0x1d19fbfb, + 0x79000001, + 0xc90afb06, + 0xc913e203, + 0x1f1afbfb, + 0x79000003, + 0x1d1afbfb, + 0x79000001, + 0xc900fb06, + 0xc902e303, + 0x1f10fbfb, + 0x79000003, + 0x1d10fbfb, + 0x79000001, + 0xc901fb06, + 0xc903e303, + 0x1f11fbfb, + 0x79000003, + 0x1d11fbfb, + 0x79000001, + 0xc902fb06, + 0xc905e303, + 0x1f12fbfb, + 0x79000003, + 0x1d12fbfb, + 0x79000001, + 0xc903fb06, + 0xc904e303, + 0x1f13fbfb, + 0x79000003, + 0x1d13fbfb, + 0x79000001, + 0xc90bfb06, + 0xc901e303, + 0x1f1bfbfb, + 0x79000003, + 0x1d1bfbfb, + 0x79000001, + 0xc90cfb06, + 0xc916e303, + 0x1f1cfbfb, + 0x79000003, + 0x1d1cfbfb, + 0x79000001, + 0xc90dfb06, + 0xc918e303, + 0x1f1dfbfb, + 0x79000003, + 0x1d1dfbfb, + 0x79000001, + 0xc90efb06, + 0xc917e303, + 0x1f1efbfb, + 0x79000003, + 0x1d1efbfb, + 0x79000001, + 0xc90ffb06, + 0xc919e303, + 0x1f1ffbfb, + 0x79000003, + 0x1d1ffbfb, + 0x79000001, + 0x244804c2, + 0x24c19082, + 0x24481ac3, + 0x24c19083, + 0xe1006287, + 0xe1006384, + 0x209c0000, 0x240002c3, 0x24202083, 0x240000e2, @@ -24,6 +294,9 @@ 0x81042480, 0x240000f8, 0x240008e9, + 0xf12c3982, + 0x5100e202, + 0x1f03f8f8, 0xf1243982, 0x5100e202, 0x1f01f8f8, @@ -335,6 +608,12 @@ 0x0901f7f7, 0x02f6f7f7, 0x240000ea, + 0xd100f804, + 0x240001c6, + 0x24100086, + 0x79000003, + 0x240001c6, + 0x24140086, 0x240000e1, 0xc901f805, 0x90f2388c, @@ -375,7 +654,7 @@ 0x12e3efef, 0x80f73c8f, 0x0104f7f7, - 0xc901f85c, + 0xc901f863, 0x24ffffe2, 0x10e2ece7, 0x0904e7e7, @@ -409,6 +688,13 @@ 0x24c1909c, 0xe1003c9b, 0xe14c3a87, + 0xc903f807, + 0x1103e1fb, + 0x6900fb05, + 0xf100269b, + 0x2300019c, + 0xe100269b, + 0x0104e6e6, 0xf1443a9b, 0xcf00fbff, 0xf1503a87, @@ -465,13 +751,13 @@ 0x0104f3f3, 0x1504f8f8, 0x0101e1e1, - 0x6ee9e17f, + 0x6ee9e178, 0x79000004, 0x1504f8f8, 0x0102e1e1, - 0x6ee9e17b, + 0x6ee9e174, 0x0101eaea, - 0x6eebea78, + 0x6eebea71, 0x10f0f0e2, 0x10f1f1f0, 0x10e2e2f1, @@ -481,6 +767,7 @@ 0x1501f8f8, 0x1101f8e2, 0xe1043982, + 0x2400241f, 0xf1203982, 0x00ebe2e2, 0xe1203982, @@ -498,20 +785,8 @@ 0x240190e1, 0x00e1e3e3, 0xe1002382, - 0xc900f807, - 0x241000c2, - 0x24000082, - 0x244804c3, - 0x24c19483, - 0xe1002382, - 0x79000006, - 0x241000c2, - 0x24000082, - 0x244804c3, - 0x24c19083, - 0xe1002382, 0xf1003982, - 0x5700e246, + 0x5700e244, 0x240000fb, 0xe1443d9b, 0xc901f80c,
--- a/include/render.h Sun Feb 08 00:20:01 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * render.h - * - * Created on: May 28, 2014 - * Author: Victor Zappi - */ - -#ifndef RENDER_H_ -#define RENDER_H_ - -// uint types -#include <stdint.h> - -// Mappings from pin numbers on PCB to actual DAC channels -// This gives the DAC and ADC connectors the same effective pinout -#define DAC_PIN0 6 -#define DAC_PIN1 4 -#define DAC_PIN2 2 -#define DAC_PIN3 0 -#define DAC_PIN4 1 -#define DAC_PIN5 3 -#define DAC_PIN6 5 -#define DAC_PIN7 7 - -#define ADC_PIN0 0 -#define ADC_PIN1 1 -#define ADC_PIN2 2 -#define ADC_PIN3 3 -#define ADC_PIN4 4 -#define ADC_PIN5 5 -#define ADC_PIN6 6 -#define ADC_PIN7 7 - -#define MATRIX_MAX 65535.0 - -extern int gNumAudioChannels; // How many audio channels are present -extern int gNumMatrixChannels; // How many matrix channels are present - -bool initialise_render(int numMatrixChannels, int numAudioChannels, - int numMatrixFramesPerPeriod, - int numAudioFramesPerPeriod, - float matrixSampleRate, float audioSampleRate, - void *userData); - -void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, - uint16_t *matrixIn, uint16_t *matrixOut); - -void render_medium_prio(); -void render_low_prio(); - -void schedule_render_medium_prio(); -void schedule_render_low_prio(); - - -void cleanup_render(); - -#endif /* RENDER_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/projects/analogDigitalDemo/main.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,108 @@ +/* + * assignment1_crossover + * RTDSP 2015 + * + * First assignment for ECS732 RTDSP, to implement a 2-way audio crossover + * using the BeagleBone Black. + * + * Andrew McPherson and Victor Zappi + * Queen Mary, University of London + */ + +#include <iostream> +#include <cstdlib> +#include <libgen.h> +#include <signal.h> +#include <getopt.h> +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> + +#include <BeagleRT.h> + +using namespace std; + +// Handle Ctrl-C by requesting that the audio rendering stop +void interrupt_handler(int var) +{ + gShouldStop = true; +} + +// Print usage information +void usage(const char * processName) +{ + cerr << "Usage: " << processName << " [options]" << endl; + + BeagleRT_usage(); + + cerr << " --help [-h]: Print this menu\n"; +} + +int main(int argc, char *argv[]) +{ + BeagleRTInitSettings settings; // Standard audio settings + float frequency = 1000.0; // Frequency of crossover + + struct option customOptions[] = + { + {"help", 0, NULL, 'h'}, + {"frequency", 1, NULL, 'f'}, + {NULL, 0, NULL, 0} + }; + + // Set default settings + BeagleRT_defaultSettings(&settings); + + // Parse command-line arguments + while (1) { + int c; + if ((c = BeagleRT_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0) + break; + switch (c) { + case 'h': + usage(basename(argv[0])); + exit(0); + case 'f': + frequency = atof(optarg); + if(frequency < 20.0) + frequency = 20.0; + if(frequency > 5000.0) + frequency = 5000.0; + break; + case '?': + default: + usage(basename(argv[0])); + exit(1); + } + } + + // Initialise the PRU audio device + if(BeagleRT_initAudio(&settings, &frequency) != 0) { + cout << "Error: unable to initialise audio" << endl; + return -1; + } + + // Start the audio device running + if(BeagleRT_startAudio()) { + cout << "Error: unable to start real-time audio" << endl; + return -1; + } + + // Set up interrupt handler to catch Control-C + signal(SIGINT, interrupt_handler); + signal(SIGTERM, interrupt_handler); + + // Run until told to stop + while(!gShouldStop) { + usleep(100000); + } + + // Stop the audio device + BeagleRT_stopAudio(); + + // Clean up any resources allocated for audio + BeagleRT_cleanupAudio(); + + // All done! + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/projects/analogDigitalDemo/render.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,91 @@ + /* + * + * Andrew McPherson and Victor Zappi + * Queen Mary, University of London + */ + +#include <BeagleRT.h> +#include <Utilities.h> +#include <cmath> +#include <rtdk.h> + +// setup() is called once before the audio rendering starts. +// Use it to perform any initialisation and allocation which is dependent +// on the period size or sample rate. +// +// userData holds an opaque pointer to a data structure that was passed +// in from the call to initAudio(). +// +// Return true on success; returning false halts the program. + +bool setup(BeagleRTContext *context, void *userData) +{ + return true; +} + +// render() is called regularly at the highest priority by the audio engine. +// Input and output are given from the audio hardware and the other +// ADCs and DACs (if available). If only audio is available, numAnalogFrames +// will be 0. + +void render(BeagleRTContext *context, void *userData) +/* +we assume that gNumAnalogChannels=8, numAnalogFrames==8 and numDigitalFrames==numAudioFrames + * */ +{ + if((context->audioSampleCount&31)==0){ //every 32 frames... + //ANALOG channels + analogWriteFrame(context, 0, 0, analogReadFrame(context, 0,0)); + // read the input0 at frame0 and write it to output0 frame0. Using analogWrite will fill the rest of the buffer with the same value + // The value at the last frame will persist through the successive buffers until is set again. + // This effectively is a pass-through with downsampling by 32 times + analogWriteFrame(context, 0, 3, 1.0); // write 1.0 to channel3 from frame0 to the end of the buffer + analogWriteFrame(context, 4, 3, 0.1); // write 0.1 to channel3 from frame4 to the end of the buffer + analogWriteFrameOnce(context, 6, 3, 0.2); //write 0.2 to channel3 only on frame 6 + //this buffer for channel 3 will look like this: 1 1 1 1 0.1 0.1 0.2 0.1 + //the next buffers for channel 3 will be filled up with 0.1 .... + //DIGITAL channels + digitalWriteFrame(context, 0, P8_07, GPIO_HIGH); //sets all the frames to HIGH for channel 0 + digitalWriteFrameOnce(context, 4, P8_07, GPIO_LOW); //only frame 4 will be LOW for channel 0 + // in this buffer the frames of channel 0 will look like this: 1 1 1 1 0 1 1 1 ...... 1 + // in the next buffer each frame of channel 0 will be initialized to 1 (the last value of this buffer) + digitalWriteFrame(context, 0, P8_08, GPIO_HIGH); + digitalWriteFrame(context, 2, P8_08, GPIO_LOW); + digitalWriteFrame(context, 4, P8_08, GPIO_HIGH); + digitalWriteFrame(context, 5, P8_08, GPIO_LOW); + pinModeFrame(context, 0, P9_16, GPIO_INPUT); // set channel 10 to input + // in this buffer the frames of channel 1 will look like this: 1 1 0 0 1 0 0 0 .... 0 + // in the next buffer each frame of channel 1 will be initialized to 0 (the last value of this buffer) + } + for(unsigned int n=0; n<context->audioFrames; n++){ + for(unsigned int c=0; c<context->audioChannels; c++){ + context->audioOut[n*context->audioChannels + c]=context->audioIn[n*context->audioChannels + c]; + } + //use digital channels 2-8 to create a 7 bit binary counter + context->digital[n]=context->digital[n] & (~0b111111100); // set to zero (GPIO_OUTPUT) the bits in the lower word + context->digital[n]=context->digital[n] & ((~0b111111100<<16) | 0xffff ); //initialize to zero the bits in the higher word (output value) + context->digital[n]=context->digital[n] | ( ((context->audioSampleCount&0b1111111)<<(16+2)) ) ; // set the bits in the higher word to the desired output value, keeping the lower word unchanged + digitalWriteFrame(context, n, P8_29, digitalReadFrame(context, n, P8_30)); // echo the input from from channel 15 to channel 14 + digitalWriteFrame(context, n, P8_28, digitalReadFrame(context, n, P9_16)); // echo the input from from channel 10 to channel 13 + pinModeFrame(context, 0, P8_30, 0); //set channel 15 to input + } + + for(unsigned int n=0; n<context->analogFrames; n++){ + analogWriteFrame(context, n, 1, (context->audioSampleCount&8191)/8192.0); // writes a single frame. channel 1 is a ramp that follows gCountFrames + analogWriteFrame(context, n, 2, analogReadFrame(context, n, 2)); // writes a single frame. channel2 is just a passthrough +// rt_printf("Analog out frame %d :",n); +// for(int c=0; c<gNumAnalogChannels; c++) +// rt_printf("%.1f ",analogOut[n*gNumAnalogChannels + c]); +// rt_printf("\n"); + } + return; + +} + +// cleanup() is called once at the end, after the audio has stopped. +// Release any resources that were allocated in setup(). + +void cleanup(BeagleRTContext *context, void *userData) +{ + // Nothing to do here +}
--- a/projects/audio_in_FFT/main.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/audio_in_FFT/main.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -10,7 +10,7 @@ #include <libgen.h> #include <signal.h> #include <getopt.h> -#include "../../include/RTAudio.h" +#include <BeagleRT.h> using namespace std; @@ -33,7 +33,7 @@ int main(int argc, char *argv[]) { - RTAudioSettings settings; // Standard audio settings + BeagleRTInitSettings settings; // Standard audio settings int fftSize = 64; // Size of the FFT, in samples struct option customOptions[] = @@ -46,7 +46,7 @@ // Set default settings BeagleRT_defaultSettings(&settings); - settings.useMatrix = 0; // No matrix usage by default + settings.useAnalog = 0; // No matrix usage by default // Parse command-line arguments while (1) {
--- a/projects/audio_in_FFT/render.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/audio_in_FFT/render.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -6,7 +6,7 @@ */ -#include "../../include/render.h" +#include <BeagleRT.h> #include <rtdk.h> #include <NE10.h> // neon library #include <cmath> @@ -23,7 +23,7 @@ ne10_fft_cpx_float32_t* frequencyDomain; ne10_fft_cfg_float32_t cfg; -// initialise_render() is called once before the audio rendering starts. +// setup() is called once before the audio rendering starts. // Use it to perform any initialisation and allocation which is dependent // on the period size or sample rate. // @@ -32,11 +32,7 @@ // // Return true on success; returning false halts the program. -bool initialise_render(int numMatrixChannels, int numAudioChannels, - int numMatrixFramesPerPeriod, - int numAudioFramesPerPeriod, - float matrixSampleRate, float audioSampleRate, - void *userData) +bool setup(BeagleRTContext *context, void *userData) { // Retrieve a parameter passed in from the initAudio() call gFFTSize = *(int *)userData; @@ -57,11 +53,11 @@ // ADCs and DACs (if available). If only audio is available, numMatrixFrames // will be 0. -void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, - uint16_t *matrixIn, uint16_t *matrixOut) +void render(BeagleRTContext *context, void *userData) { - for(int n = 0; n < numAudioFrames; n++) { - timeDomainIn[gReadPointer].r = (ne10_float32_t) ((audioIn[n*gNumAudioChannels] + audioIn[n*gNumAudioChannels+1]) * 0.5); + for(unsigned int n = 0; n < context->audioFrames; n++) { + timeDomainIn[gReadPointer].r = (ne10_float32_t) ((context->audioIn[n*context->audioChannels] + + context->audioIn[n*context->audioChannels+1]) * 0.5); timeDomainIn[gReadPointer].i = 0; if(++gReadPointer >= gFFTSize) @@ -78,16 +74,16 @@ gWritePointer = 0; } - for(int channel = 0; channel < gNumAudioChannels; channel++) - audioOut[n * gNumAudioChannels + channel] = (float) timeDomainOut[gWritePointer].r * gFFTScaleFactor; + for(unsigned int channel = 0; channel < context->audioChannels; channel++) + context->audioOut[n * context->audioChannels + channel] = (float) timeDomainOut[gWritePointer].r * gFFTScaleFactor; gWritePointer++; } } -// cleanup_render() is called once at the end, after the audio has stopped. -// Release any resources that were allocated in initialise_render(). +// cleanup() is called once at the end, after the audio has stopped. +// Release any resources that were allocated in setup(). -void cleanup_render() +void cleanup(BeagleRTContext *context, void *userData) { NE10_FREE(timeDomainIn); NE10_FREE(timeDomainOut);
--- a/projects/basic/main.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/basic/main.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -4,13 +4,13 @@ * Created on: Oct 24, 2014 * Author: parallels */ - +#include <unistd.h> #include <iostream> #include <cstdlib> #include <libgen.h> #include <signal.h> #include <getopt.h> -#include "../../include/RTAudio.h" +#include <BeagleRT.h> using namespace std; @@ -33,7 +33,7 @@ int main(int argc, char *argv[]) { - RTAudioSettings settings; // Standard audio settings + BeagleRTInitSettings settings; // Standard audio settings float frequency = 440.0; // Frequency of oscillator struct option customOptions[] =
--- a/projects/basic/render.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/basic/render.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -6,14 +6,14 @@ */ -#include "../../include/render.h" +#include <BeagleRT.h> #include <cmath> -float gFrequency; +float gFrequency = 440.0; float gPhase; float gInverseSampleRate; -// initialise_render() is called once before the audio rendering starts. +// setup() is called once before the audio rendering starts. // Use it to perform any initialisation and allocation which is dependent // on the period size or sample rate. // @@ -22,16 +22,13 @@ // // Return true on success; returning false halts the program. -bool initialise_render(int numMatrixChannels, int numAudioChannels, - int numMatrixFramesPerPeriod, - int numAudioFramesPerPeriod, - float matrixSampleRate, float audioSampleRate, - void *userData) +bool setup(BeagleRTContext *context, void *userData) { // Retrieve a parameter passed in from the initAudio() call - gFrequency = *(float *)userData; + if(userData != 0) + gFrequency = *(float *)userData; - gInverseSampleRate = 1.0 / audioSampleRate; + gInverseSampleRate = 1.0 / context->audioSampleRate; gPhase = 0.0; return true; @@ -42,24 +39,23 @@ // ADCs and DACs (if available). If only audio is available, numMatrixFrames // will be 0. -void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, - uint16_t *matrixIn, uint16_t *matrixOut) +void render(BeagleRTContext *context, void *userData) { - for(int n = 0; n < numAudioFrames; n++) { + for(unsigned int n = 0; n < context->audioFrames; n++) { float out = 0.8f * sinf(gPhase); gPhase += 2.0 * M_PI * gFrequency * gInverseSampleRate; if(gPhase > 2.0 * M_PI) gPhase -= 2.0 * M_PI; - for(int channel = 0; channel < gNumAudioChannels; channel++) - audioOut[n * gNumAudioChannels + channel] = out; + for(unsigned int channel = 0; channel < context->audioChannels; channel++) + context->audioOut[n * context->audioChannels + channel] = out; } } -// cleanup_render() is called once at the end, after the audio has stopped. -// Release any resources that were allocated in initialise_render(). +// cleanup() is called once at the end, after the audio has stopped. +// Release any resources that were allocated in setup(). -void cleanup_render() +void cleanup(BeagleRTContext *context, void *userData) { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/projects/basic_analog_input/main.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,117 @@ +/* + * main.cpp + * + * Created on: Oct 24, 2014 + * Author: parallels + */ + +#include <iostream> +#include <cstdlib> +#include <libgen.h> +#include <signal.h> +#include <getopt.h> +#include <BeagleRT.h> + +using namespace std; + +int gSensorInputFrequency = 0; +int gSensorInputAmplitude = 1; + +// Handle Ctrl-C by requesting that the audio rendering stop +void interrupt_handler(int var) +{ + gShouldStop = true; +} + +// Print usage information +void usage(const char * processName) +{ + cerr << "Usage: " << processName << " [options]" << endl; + + BeagleRT_usage(); + + cerr << " --frequency [-f] input: Choose the analog input controlling frequency (0-7; default 0)\n"; + cerr << " --amplitude [-a] input: Choose the analog input controlling amplitude (0-7; default 1)\n"; + cerr << " --help [-h]: Print this menu\n"; +} + +int main(int argc, char *argv[]) +{ + BeagleRTInitSettings settings; // Standard audio settings + + struct option customOptions[] = + { + {"help", 0, NULL, 'h'}, + {"frequency", 1, NULL, 'f'}, + {"amplitude", 1, NULL, 'a'}, + {NULL, 0, NULL, 0} + }; + + // Set default settings + BeagleRT_defaultSettings(&settings); + + // Parse command-line arguments + while (1) { + int c; + if ((c = BeagleRT_getopt_long(argc, argv, "hf:a:", customOptions, &settings)) < 0) + break; + switch (c) { + case 'h': + usage(basename(argv[0])); + exit(0); + case 'f': + gSensorInputFrequency = atoi(optarg); + if(gSensorInputFrequency < 0 || gSensorInputFrequency > 7) { + usage(basename(argv[0])); + exit(0); + } + break; + case 'a': + gSensorInputAmplitude = atoi(optarg); + if(gSensorInputAmplitude < 0 || gSensorInputAmplitude > 7) { + usage(basename(argv[0])); + exit(0); + } + break; + case '?': + default: + usage(basename(argv[0])); + exit(1); + } + } + + // Initialise the PRU audio device + if(BeagleRT_initAudio(&settings, 0) != 0) { + cout << "Error: unable to initialise audio" << endl; + return -1; + } + + if(settings.verbose) { + cout << "--> Frequency on input " << gSensorInputFrequency << endl; + cout << "--> Amplitude on input " << gSensorInputAmplitude << endl; + } + + // Start the audio device running + if(BeagleRT_startAudio()) { + cout << "Error: unable to start real-time audio" << endl; + return -1; + } + + // Set up interrupt handler to catch Control-C and SIGTERM + signal(SIGINT, interrupt_handler); + signal(SIGTERM, interrupt_handler); + + // Run until told to stop + while(!gShouldStop) { + usleep(100000); + } + + // Stop the audio device + BeagleRT_stopAudio(); + + // Clean up any resources allocated for audio + BeagleRT_cleanupAudio(); + + // All done! + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/projects/basic_analog_input/render.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,85 @@ +/* + * render.cpp + * + * Created on: Oct 24, 2014 + * Author: parallels + */ + + +#include <BeagleRT.h> +#include <Utilities.h> +#include <rtdk.h> +#include <cmath> + +float gPhase; +float gInverseSampleRate; +int gAudioFramesPerAnalogFrame; + +// These settings are carried over from main.cpp +// Setting global variables is an alternative approach +// to passing a structure to userData in setup() + +extern int gSensorInputFrequency; +extern int gSensorInputAmplitude; + +// setup() is called once before the audio rendering starts. +// Use it to perform any initialisation and allocation which is dependent +// on the period size or sample rate. +// +// userData holds an opaque pointer to a data structure that was passed +// in from the call to initAudio(). +// +// Return true on success; returning false halts the program. + +bool setup(BeagleRTContext *context, void *userData) +{ + if(context->analogFrames == 0 || context->analogFrames > context->audioFrames) { + rt_printf("Error: this example needs analog enabled, with 4 or 8 channels\n"); + return false; + } + + gAudioFramesPerAnalogFrame = context->audioFrames / context->analogFrames; + gInverseSampleRate = 1.0 / context->audioSampleRate; + gPhase = 0.0; + + return true; +} + +// render() is called regularly at the highest priority by the audio engine. +// Input and output are given from the audio hardware and the other +// ADCs and DACs (if available). If only audio is available, numMatrixFrames +// will be 0. + +void render(BeagleRTContext *context, void *userData) +{ + float frequency = 440.0; + float amplitude = 0.8; + + // There are twice as many audio frames as matrix frames since audio sample rate + // is twice as high + + for(unsigned int n = 0; n < context->audioFrames; n++) { + if(!(n % gAudioFramesPerAnalogFrame)) { + // Even audio samples: update frequency and amplitude from the matrix + frequency = map(analogReadFrame(context, n/gAudioFramesPerAnalogFrame, gSensorInputFrequency), 0, 1, 100, 1000); + amplitude = analogReadFrame(context, n/gAudioFramesPerAnalogFrame, gSensorInputAmplitude); + } + + float out = amplitude * sinf(gPhase); + + for(unsigned int channel = 0; channel < context->audioChannels; channel++) + context->audioOut[n * context->audioChannels + channel] = out; + + gPhase += 2.0 * M_PI * frequency * gInverseSampleRate; + if(gPhase > 2.0 * M_PI) + gPhase -= 2.0 * M_PI; + } +} + +// cleanup() is called once at the end, after the audio has stopped. +// Release any resources that were allocated in setup(). + +void cleanup(BeagleRTContext *context, void *userData) +{ + +}
--- a/projects/basic_analog_output/main.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/basic_analog_output/main.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -10,7 +10,7 @@ #include <libgen.h> #include <signal.h> #include <getopt.h> -#include "../../include/RTAudio.h" +#include <BeagleRT.h> using namespace std; @@ -33,7 +33,7 @@ int main(int argc, char *argv[]) { - RTAudioSettings settings; // Standard audio settings + BeagleRTInitSettings settings; // Standard audio settings float frequency = 1.0; // Frequency of LED fades struct option customOptions[] =
--- a/projects/basic_analog_output/render.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/basic_analog_output/render.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -6,20 +6,20 @@ */ -#include "../../include/render.h" -#include "../../include/Utilities.h" +#include <BeagleRT.h> +#include <Utilities.h> #include <rtdk.h> #include <cmath> // Set range for analog outputs designed for driving LEDs -const float kMinimumAmplitude = (1.5 / 5.0) * MATRIX_MAX; -const float kAmplitudeRange = MATRIX_MAX - kMinimumAmplitude; +const float kMinimumAmplitude = (1.5 / 5.0); +const float kAmplitudeRange = 1.0 - kMinimumAmplitude; float gFrequency; float gPhase; float gInverseSampleRate; -// initialise_render() is called once before the audio rendering starts. +// setup() is called once before the audio rendering starts. // Use it to perform any initialisation and allocation which is dependent // on the period size or sample rate. // @@ -28,21 +28,17 @@ // // Return true on success; returning false halts the program. -bool initialise_render(int numMatrixChannels, int numAudioChannels, - int numMatrixFramesPerPeriod, - int numAudioFramesPerPeriod, - float matrixSampleRate, float audioSampleRate, - void *userData) +bool setup(BeagleRTContext *context, void *userData) { // Retrieve a parameter passed in from the initAudio() call gFrequency = *(float *)userData; - if(numMatrixFramesPerPeriod == 0) { + if(context->analogFrames == 0) { rt_printf("Error: this example needs the matrix enabled\n"); return false; } - gInverseSampleRate = 1.0 / matrixSampleRate; + gInverseSampleRate = 1.0 / context->analogSampleRate; gPhase = 0.0; return true; @@ -53,18 +49,15 @@ // ADCs and DACs (if available). If only audio is available, numMatrixFrames // will be 0. -void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, - uint16_t *matrixIn, uint16_t *matrixOut) +void render(BeagleRTContext *context, void *userData) { - for(int n = 0; n < numMatrixFrames; n++) { + for(unsigned int n = 0; n < context->analogFrames; n++) { // Set LED to different phase for each matrix channel float relativePhase = 0.0; - for(int channel = 0; channel < gNumMatrixChannels; channel++) { + for(unsigned int channel = 0; channel < context->analogChannels; channel++) { float out = kMinimumAmplitude + kAmplitudeRange * 0.5f * (1.0f + sinf(gPhase + relativePhase)); - if(out > MATRIX_MAX) - out = MATRIX_MAX; - analogWrite(channel, n, out); + analogWriteFrame(context, n, channel, out); // Advance by pi/4 (1/8 of a full rotation) for each channel relativePhase += M_PI * 0.25; @@ -76,10 +69,10 @@ } } -// cleanup_render() is called once at the end, after the audio has stopped. -// Release any resources that were allocated in initialise_render(). +// cleanup() is called once at the end, after the audio has stopped. +// Release any resources that were allocated in setup(). -void cleanup_render() +void cleanup(BeagleRTContext *context, void *userData) { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/projects/basic_network/main.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,98 @@ +/* + * main.cpp + * + * Created on: Oct 24, 2014 + * Author: parallels + */ + +#include <iostream> +#include <cstdlib> +#include <libgen.h> +#include <signal.h> +#include <getopt.h> +#include <unistd.h> +#include <BeagleRT.h> + +using namespace std; + +// Handle Ctrl-C by requesting that the audio rendering stop +void interrupt_handler(int var) +{ + gShouldStop = true; +} + +// Print usage information +void usage(const char * processName) +{ + cerr << "Usage: " << processName << " [options]" << endl; + + BeagleRT_usage(); + + cerr << " --frequency [-f] frequency: Set the frequency of the oscillator\n"; + cerr << " --help [-h]: Print this menu\n"; +} + +int main(int argc, char *argv[]) +{ + BeagleRTInitSettings settings; // Standard audio settings + float frequency = 440.0; // Frequency of oscillator + + struct option customOptions[] = + { + {"help", 0, NULL, 'h'}, + {"frequency", 1, NULL, 'f'}, + {NULL, 0, NULL, 0} + }; + + // Set default settings + BeagleRT_defaultSettings(&settings); + + // Parse command-line arguments + while (1) { + int c; + if ((c = BeagleRT_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0) + break; + switch (c) { + case 'h': + usage(basename(argv[0])); + exit(0); + case 'f': + frequency = atof(optarg); + break; + case '?': + default: + usage(basename(argv[0])); + exit(1); + } + } + + // Initialise the PRU audio device + if(BeagleRT_initAudio(&settings, &frequency) != 0) { + cout << "Error: unable to initialise audio" << endl; + return -1; + } + + // Start the audio device running + if(BeagleRT_startAudio()) { + cout << "Error: unable to start real-time audio" << endl; + return -1; + } + + // Set up interrupt handler to catch Control-C and SIGTERM + signal(SIGINT, interrupt_handler); + signal(SIGTERM, interrupt_handler); + + // Run until told to stop + while(!gShouldStop) { + usleep(100000); + } + + // Stop the audio device + BeagleRT_stopAudio(); + + // Clean up any resources allocated for audio + BeagleRT_cleanupAudio(); + + // All done! + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/projects/basic_network/render.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,84 @@ +/* + * render.cpp + * + * Created on: Oct 24, 2014 + * Author: parallels + */ + +#include <BeagleRT.h> +#include <cmath> +#include <client.h> + +float gFrequency; +float gPhase; +float gInverseSampleRate; +int gCount=0; +networkData networkObject; +AuxiliaryTask transmitReceiveDataTask; + +void transmitReceiveData(){ + printf("transmitReceiveData auxiliary task has started\n"); + while(!gShouldStop){ + sendMessage(networkObject); + receiveMessage(networkObject); + usleep(1000); + } + closeSockets(); +} + +// setup() is called once before the audio rendering starts. +// Use it to perform any initialisation and allocation which is dependent +// on the period size or sample rate. +// +// userData holds an opaque pointer to a data structure that was passed +// in from the call to initAudio(). +// +// Return true on success; returning false halts the program. +bool setup(BeagleRTContext *context, void *userData) +{ + // Retrieve a parameter passed in from the initAudio() call + gFrequency = *(float *)userData; + + gInverseSampleRate = 1.0 / context->audioSampleRate; + gPhase = 0.0; + + networkObject.counter=&gCount; + networkObject.variables[0]=&gFrequency; + networkObject.variables[1]=&gPhase; + networkObject.numVariables=2; + + setupSockets(settings->receivePort, settings->transmitPort, settings->serverName); + transmitReceiveDataTask= BeagleRT_createAuxiliaryTask(*transmitReceiveData, 80, "transmit-receive-data"); + //scheduleAuxiliaryTask(transmitReceiveDataTask); //here it does not work + return true; +} + +// render() is called regularly at the highest priority by the audio engine. +// Input and output are given from the audio hardware and the other +// ADCs and DACs (if available). If only audio is available, numMatrixFrames +// will be 0. + +void render(BeagleRTContext *context, void *userData) +{ + for(unsigned int n = 0; n < context->audioFrames; n++) { + float out = 0.7f * sinf(gPhase); + gPhase += 2.0 * M_PI * gFrequency * gInverseSampleRate; + if(gPhase > 2.0 * M_PI) + gPhase -= 2.0 * M_PI; + + for(unsigned int channel = 0; channel < context->audioChannels; channel++) + context->audioOut[n * context->audioChannels + channel] = out; + + if(gCount == 0){ + BeagleRT_scheduleAuxiliaryTask(transmitReceiveDataTask); + } + gCount++; + } +} + +// cleanup() is called once at the end, after the audio has stopped. +// Release any resources that were allocated in setup(). + +void cleanup(BeagleRTContext *context, void *userData) +{ +}
--- a/projects/basic_passthru/main.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/basic_passthru/main.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -10,7 +10,7 @@ #include <libgen.h> #include <signal.h> #include <getopt.h> -#include "../../include/RTAudio.h" +#include <BeagleRT.h> using namespace std; @@ -32,7 +32,7 @@ int main(int argc, char *argv[]) { - RTAudioSettings settings; // Standard audio settings + BeagleRTInitSettings settings; // Standard audio settings struct option customOptions[] = {
--- a/projects/basic_passthru/render.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/basic_passthru/render.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -6,11 +6,11 @@ */ -#include "../../include/render.h" -#include "../../include/Utilities.h" +#include <BeagleRT.h> +#include <Utilities.h> #include <rtdk.h> -// initialise_render() is called once before the audio rendering starts. +// setup() is called once before the audio rendering starts. // Use it to perform any initialisation and allocation which is dependent // on the period size or sample rate. // @@ -19,11 +19,7 @@ // // Return true on success; returning false halts the program. -bool initialise_render(int numMatrixChannels, int numAudioChannels, - int numMatrixFramesPerPeriod, - int numAudioFramesPerPeriod, - float matrixSampleRate, float audioSampleRate, - void *userData) +bool setup(BeagleRTContext *context, void *userData) { // Nothing to do here... @@ -35,34 +31,33 @@ // ADCs and DACs (if available). If only audio is available, numMatrixFrames // will be 0. -void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, - uint16_t *matrixIn, uint16_t *matrixOut) +void render(BeagleRTContext *context, void *userData) { // Simplest possible case: pass inputs through to outputs - for(int n = 0; n < numAudioFrames; n++) { - for(int ch = 0; ch < gNumAudioChannels; ch++) - audioOut[n * gNumAudioChannels + ch] = audioIn[n * gNumAudioChannels + ch]; + for(unsigned int n = 0; n < context->audioFrames; n++) { + for(unsigned int ch = 0; ch < context->audioChannels; ch++) + context->audioOut[n * context->audioChannels + ch] = context->audioIn[n * context->audioChannels + ch]; } // Same with matrix, only if matrix is enabled - if(numMatrixFrames != 0) { - for(int n = 0; n < numMatrixFrames; n++) { - for(int ch = 0; ch < gNumMatrixChannels; ch++) { + if(context->analogFrames != 0) { + for(unsigned int n = 0; n < context->analogFrames; n++) { + for(unsigned int ch = 0; ch < context->analogChannels; ch++) { // Two equivalent ways to write this code // The long way, using the buffers directly: - // matrixOut[n * gNumMatrixChannels + ch] = matrixIn[n * gNumMatrixChannels + ch]; + // context->analogOut[n * context->analogChannels + ch] = context->analogIn[n * context->analogChannels + ch]; // Or using the macros: - analogWrite(ch, n, analogRead(ch, n)); + analogWriteFrame(context, n, ch, analogReadFrame(context, n, ch)); } } } } -// cleanup_render() is called once at the end, after the audio has stopped. -// Release any resources that were allocated in initialise_render(). +// cleanup() is called once at the end, after the audio has stopped. +// Release any resources that were allocated in setup(). -void cleanup_render() +void cleanup(BeagleRTContext *context, void *userData) { }
--- a/projects/basic_sensor/main.cpp Sun Feb 08 00:20:01 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -/* - * main.cpp - * - * Created on: Oct 24, 2014 - * Author: parallels - */ - -#include <iostream> -#include <cstdlib> -#include <libgen.h> -#include <signal.h> -#include <getopt.h> -#include "../../include/RTAudio.h" - -using namespace std; - -int gSensorInputFrequency = 0; -int gSensorInputAmplitude = 1; - -// Handle Ctrl-C by requesting that the audio rendering stop -void interrupt_handler(int var) -{ - gShouldStop = true; -} - -// Print usage information -void usage(const char * processName) -{ - cerr << "Usage: " << processName << " [options]" << endl; - - BeagleRT_usage(); - - cerr << " --frequency [-f] input: Choose the analog input controlling frequency (0-7; default 0)\n"; - cerr << " --amplitude [-a] input: Choose the analog input controlling amplitude (0-7; default 1)\n"; - cerr << " --help [-h]: Print this menu\n"; -} - -int main(int argc, char *argv[]) -{ - RTAudioSettings settings; // Standard audio settings - - struct option customOptions[] = - { - {"help", 0, NULL, 'h'}, - {"frequency", 1, NULL, 'f'}, - {"amplitude", 1, NULL, 'a'}, - {NULL, 0, NULL, 0} - }; - - // Set default settings - BeagleRT_defaultSettings(&settings); - - // Parse command-line arguments - while (1) { - int c; - if ((c = BeagleRT_getopt_long(argc, argv, "hf:a:", customOptions, &settings)) < 0) - break; - switch (c) { - case 'h': - usage(basename(argv[0])); - exit(0); - case 'f': - gSensorInputFrequency = atoi(optarg); - if(gSensorInputFrequency < 0 || gSensorInputFrequency > 7) { - usage(basename(argv[0])); - exit(0); - } - break; - case 'a': - gSensorInputAmplitude = atoi(optarg); - if(gSensorInputAmplitude < 0 || gSensorInputAmplitude > 7) { - usage(basename(argv[0])); - exit(0); - } - break; - case '?': - default: - usage(basename(argv[0])); - exit(1); - } - } - - // Initialise the PRU audio device - if(BeagleRT_initAudio(&settings, 0) != 0) { - cout << "Error: unable to initialise audio" << endl; - return -1; - } - - if(settings.verbose) { - cout << "--> Frequency on input " << gSensorInputFrequency << endl; - cout << "--> Amplitude on input " << gSensorInputAmplitude << endl; - } - - // Start the audio device running - if(BeagleRT_startAudio()) { - cout << "Error: unable to start real-time audio" << endl; - return -1; - } - - // Set up interrupt handler to catch Control-C and SIGTERM - signal(SIGINT, interrupt_handler); - signal(SIGTERM, interrupt_handler); - - // Run until told to stop - while(!gShouldStop) { - usleep(100000); - } - - // Stop the audio device - BeagleRT_stopAudio(); - - // Clean up any resources allocated for audio - BeagleRT_cleanupAudio(); - - // All done! - return 0; -}
--- a/projects/basic_sensor/render.cpp Sun Feb 08 00:20:01 2015 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/* - * render.cpp - * - * Created on: Oct 24, 2014 - * Author: parallels - */ - - -#include "../../include/render.h" -#include "../../include/Utilities.h" -#include <rtdk.h> -#include <cmath> - -float gPhase; -float gInverseSampleRate; -int gMatrixFramesPerAudioFrame; - -// These settings are carried over from main.cpp -// Setting global variables is an alternative approach -// to passing a structure to userData in initialise_render() - -extern int gSensorInputFrequency; -extern int gSensorInputAmplitude; - -// initialise_render() is called once before the audio rendering starts. -// Use it to perform any initialisation and allocation which is dependent -// on the period size or sample rate. -// -// userData holds an opaque pointer to a data structure that was passed -// in from the call to initAudio(). -// -// Return true on success; returning false halts the program. - -bool initialise_render(int numMatrixChannels, int numAudioChannels, - int numMatrixFramesPerPeriod, - int numAudioFramesPerPeriod, - float matrixSampleRate, float audioSampleRate, - void *userData) -{ - if(numMatrixFramesPerPeriod == 0 || numMatrixFramesPerPeriod > numAudioFramesPerPeriod) { - rt_printf("Error: this example needs the matrix enabled, with 4 or 8 channels\n"); - return false; - } - - gMatrixFramesPerAudioFrame = numAudioFramesPerPeriod / numMatrixFramesPerPeriod; - gInverseSampleRate = 1.0 / audioSampleRate; - gPhase = 0.0; - - return true; -} - -// render() is called regularly at the highest priority by the audio engine. -// Input and output are given from the audio hardware and the other -// ADCs and DACs (if available). If only audio is available, numMatrixFrames -// will be 0. - -void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, - uint16_t *matrixIn, uint16_t *matrixOut) -{ - float frequency = 0; - float amplitude = 0; - - // There are twice as many audio frames as matrix frames since audio sample rate - // is twice as high - - for(int n = 0; n < numAudioFrames; n++) { - if(!(n % gMatrixFramesPerAudioFrame)) { - // Even audio samples: update frequency and amplitude from the matrix - frequency = map(analogRead(gSensorInputFrequency, n/gMatrixFramesPerAudioFrame), 0, MATRIX_MAX, 100, 1000); - amplitude = (float)analogRead(gSensorInputAmplitude, n/gMatrixFramesPerAudioFrame) / MATRIX_MAX; - } - - float out = amplitude * sinf(gPhase); - - for(int channel = 0; channel < gNumAudioChannels; channel++) - audioOut[n * gNumAudioChannels + channel] = out; - - gPhase += 2.0 * M_PI * frequency * gInverseSampleRate; - if(gPhase > 2.0 * M_PI) - gPhase -= 2.0 * M_PI; - } -} - -// cleanup_render() is called once at the end, after the audio has stopped. -// Release any resources that were allocated in initialise_render(). - -void cleanup_render() -{ - -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/projects/cape_test/main.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,97 @@ +/* + * main.cpp + * + * Created on: Oct 24, 2014 + * Author: parallels + */ +#include <unistd.h> +#include <iostream> +#include <cstdlib> +#include <libgen.h> +#include <signal.h> +#include <getopt.h> +#include <BeagleRT.h> + +using namespace std; + +// Handle Ctrl-C by requesting that the audio rendering stop +void interrupt_handler(int var) +{ + gShouldStop = true; +} + +// Print usage information +void usage(const char * processName) +{ + cerr << "Usage: " << processName << " [options]" << endl; + + BeagleRT_usage(); + + cerr << " --frequency [-f] frequency: Set the frequency of the oscillator\n"; + cerr << " --help [-h]: Print this menu\n"; +} + +int main(int argc, char *argv[]) +{ + BeagleRTInitSettings settings; // Standard audio settings + float frequency = 440.0; // Frequency of oscillator + + struct option customOptions[] = + { + {"help", 0, NULL, 'h'}, + {"frequency", 1, NULL, 'f'}, + {NULL, 0, NULL, 0} + }; + + // Set default settings + BeagleRT_defaultSettings(&settings); + + // Parse command-line arguments + while (1) { + int c; + if ((c = BeagleRT_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0) + break; + switch (c) { + case 'h': + usage(basename(argv[0])); + exit(0); + case 'f': + frequency = atof(optarg); + break; + case '?': + default: + usage(basename(argv[0])); + exit(1); + } + } + + // Initialise the PRU audio device + if(BeagleRT_initAudio(&settings, &frequency) != 0) { + cout << "Error: unable to initialise audio" << endl; + return -1; + } + + // Start the audio device running + if(BeagleRT_startAudio()) { + cout << "Error: unable to start real-time audio" << endl; + return -1; + } + + // Set up interrupt handler to catch Control-C and SIGTERM + signal(SIGINT, interrupt_handler); + signal(SIGTERM, interrupt_handler); + + // Run until told to stop + while(!gShouldStop) { + usleep(100000); + } + + // Stop the audio device + BeagleRT_stopAudio(); + + // Clean up any resources allocated for audio + BeagleRT_cleanupAudio(); + + // All done! + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/projects/cape_test/render.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,141 @@ +/* + * render.cpp + * + * Created on: Oct 24, 2014 + * Author: parallels + */ + + +#include <BeagleRT.h> +#include <cmath> + +#define ANALOG_LOW (2048.0 / 65536.0) +#define ANALOG_HIGH (50000.0 / 65536.0) + +const int gDACPinOrder[] = {6, 4, 2, 0, 1, 3, 5, 7}; + +uint64_t gLastErrorFrame = 0; +uint32_t gEnvelopeSampleCount = 0; +float gEnvelopeValue = 0.5; +float gEnvelopeDecayRate = 0.9995; + +// setup() is called once before the audio rendering starts. +// Use it to perform any initialisation and allocation which is dependent +// on the period size or sample rate. +// +// userData holds an opaque pointer to a data structure that was passed +// in from the call to initAudio(). +// +// Return true on success; returning false halts the program. + +bool setup(BeagleRTContext *context, void *userData) +{ + return true; +} + +// render() is called regularly at the highest priority by the audio engine. +// Input and output are given from the audio hardware and the other +// ADCs and DACs (if available). If only audio is available, numMatrixFrames +// will be 0. + +void render(BeagleRTContext *context, void *userData) +{ + static float phase = 0.0; + static int sampleCounter = 0; + static int invertChannel = 0; + float frequency = 0; + + // Play a sine wave on the audio output + for(unsigned int n = 0; n < context->audioFrames; n++) { + context->audioOut[2*n] = context->audioOut[2*n + 1] = gEnvelopeValue * sinf(phase); + + // If one second has gone by with no error, play one sound, else + // play another + if(context->audioSampleCount + n - gLastErrorFrame > 44100) { + gEnvelopeValue *= gEnvelopeDecayRate; + gEnvelopeSampleCount++; + if(gEnvelopeSampleCount > 22050) { + gEnvelopeValue = 0.5; + gEnvelopeSampleCount = 0; + } + frequency = 880.0; + } + else { + gEnvelopeValue = 0.5; + frequency = 220.0; + } + + phase += 2.0 * M_PI * frequency / 44100.0; + if(phase >= 2.0 * M_PI) + phase -= 2.0 * M_PI; + } + + for(unsigned int n = 0; n < context->analogFrames; n++) { + // Change outputs every 512 samples + if(sampleCounter < 512) { + for(int k = 0; k < 8; k++) { + if(k == invertChannel) + context->analogOut[n*8 + gDACPinOrder[k]] = ANALOG_HIGH; + else + context->analogOut[n*8 + gDACPinOrder[k]] = 0; + } + } + else { + for(int k = 0; k < 8; k++) { + if(k == invertChannel) + context->analogOut[n*8 + gDACPinOrder[k]] = 0; + else + context->analogOut[n*8 + gDACPinOrder[k]] = ANALOG_HIGH; + } + } + + // Read after 256 samples: input should be low + if(sampleCounter == 256) { + for(int k = 0; k < 8; k++) { + if(k == invertChannel) { + if(context->analogIn[n*8 + k] < ANALOG_HIGH) { + rt_printf("FAIL [output %d, input %d] -- output HIGH input %f (inverted)\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]); + gLastErrorFrame = context->audioSampleCount + n; + } + } + else { + if(context->analogIn[n*8 + k] > ANALOG_LOW) { + rt_printf("FAIL [output %d, input %d] -- output LOW --> input %f\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]); + gLastErrorFrame = context->audioSampleCount + n; + } + } + } + } + else if(sampleCounter == 768) { + for(int k = 0; k < 8; k++) { + if(k == invertChannel) { + if(context->analogIn[n*8 + k] > ANALOG_LOW) { + rt_printf("FAIL [output %d, input %d] -- output LOW input %f (inverted)\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]); + gLastErrorFrame = context->audioSampleCount + n; + } + } + else { + if(context->analogIn[n*8 + k] < ANALOG_HIGH) { + rt_printf("FAIL [output %d, input %d] -- output HIGH input %f\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]); + gLastErrorFrame = context->audioSampleCount + n; + } + } + } + } + + if(++sampleCounter >= 1024) { + sampleCounter = 0; + invertChannel++; + if(invertChannel >= 8) + invertChannel = 0; + } + } +} + +// cleanup() is called once at the end, after the audio has stopped. +// Release any resources that were allocated in setup(). + +void cleanup(BeagleRTContext *context, void *userData) +{ + +}
--- a/projects/d-box/FeedbackOscillator.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/d-box/FeedbackOscillator.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -58,23 +58,16 @@ // Process one sample and store the output value // Returns true if the wavetable needs rendering -int FeedbackOscillator::process(uint16_t input, uint16_t *output) { - float inFloat = input / 65536.0; - float outFloat = coeffs[COEFF_B0] * inFloat + coeffs[COEFF_B1] * lastInput - coeffs[COEFF_A1] * lastOutput; +int FeedbackOscillator::process(float input, float *output) { + float outFloat = coeffs[COEFF_B0] * input + coeffs[COEFF_B1] * lastInput - coeffs[COEFF_A1] * lastOutput; int requestRenderLength = 0; - //outFloat *= 2.0; - - int intOut = outFloat * 65536.0 + 32768; - if(intOut > 65535) - intOut = 65535; - if(intOut < 0) - intOut = 0; - //intOut = (intOut & 0xFF) << 8; - //if(intOut > 65535) - // intOut = 65535; - - *output = (uint16_t)intOut; + if(outFloat < -0.5) + *output = 0; + else if(outFloat > 0.5) + *output = 1; + else + *output = outFloat + 0.5; if(canTrigger && outFloat > 0 && lastOutput <= 0) { triggered = true; @@ -106,7 +99,7 @@ sampleCount++; lastOutput = outFloat; - lastInput = inFloat; + lastInput = input; return requestRenderLength; }
--- a/projects/d-box/FeedbackOscillator.h Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/d-box/FeedbackOscillator.h Fri Jul 17 15:28:18 2015 +0100 @@ -8,8 +8,6 @@ #ifndef FEEDBACKOSCILLATOR_H #define FEEDBACKOSCILLATOR_H -#include <stdint.h> - class FeedbackOscillator { public: @@ -21,7 +19,7 @@ // Process one sample and store the output value // Returns the length of table to interpolate; or 0 if nothing to process further - int process(uint16_t input, uint16_t *output); + int process(float input, float *output); float *wavetable() { return wavetableRead; }
--- a/projects/d-box/main.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/d-box/main.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -33,7 +33,7 @@ // get_opt_long #include <getopt.h> -#include "../../include/RTAudio.h" +#include <BeagleRT.h> #include "config.h" #include "sensors.h" #include "OscillatorBank.h" @@ -262,11 +262,13 @@ } -void parseArguments(arg_data args, RTAudioSettings *settings) +void parseArguments(arg_data args, BeagleRTInitSettings *settings) { // Default filename; gPartialFilename = strdup("D-Box_sound_250_60_40_h88_2.txt"); + const int kOptionAudioTest = 1000; + // TODO: complete this struct option long_option[] = { @@ -274,10 +276,10 @@ {"audioin", 1, NULL, 'i'}, {"file", 1, NULL, 'f'}, {"keyboard", 1, NULL, 'k'}, - {"audio-test", 0, NULL, 'T'}, - {"sensor-type", 1, NULL, 'S'}, - {"sensor0", 1, NULL, 'Q'}, - {"sensor1", 1, NULL, 'R'}, + {"audio-test", 0, NULL, kOptionAudioTest}, + {"sensor-type", 1, NULL, 't'}, + {"sensor0", 1, NULL, 'q'}, + {"sensor1", 1, NULL, 'r'}, {"log", 1, NULL, 'l'}, {"usesd", 1, NULL, 'u'}, {"oversamp", 1, NULL, 'o'}, @@ -293,7 +295,7 @@ while (1) { int c; - if ((c = BeagleRT_getopt_long(args.argc, args.argv, "hf:ki:sTQ:R:S:l:u:o:n:g:", long_option, settings)) < 0) + if ((c = BeagleRT_getopt_long(args.argc, args.argv, "hf:ki:sq:r:t:l:u:o:n:g:", long_option, settings)) < 0) break; switch (c) { @@ -313,16 +315,16 @@ case 's': forceSensors = true; break; - case 'T': + case kOptionAudioTest: useAudioTest = true; break; - case 'S': + case 't': sensorType = atoi(optarg); break; - case 'Q': + case 'q': touchSensor0Address = atoi(optarg); break; - case 'R': + case 'r': touchSensor1Address = atoi(optarg); break; case 'l': @@ -361,7 +363,7 @@ int main(int argc, char *argv[]) { - RTAudioSettings settings; // Standard audio settings + BeagleRTInitSettings settings; // Standard audio settings RT_TASK rtSensorThread; const char rtSensorThreadName[] = "dbox-sensor"; int oscBankHopSize; @@ -371,7 +373,7 @@ args.argv = argv; parseArguments(args, &settings); - setVerboseLevel(gVerbose); + BeagleRT_setVerboseLevel(gVerbose); if(gVerbose == 1 && useAudioTest) cout << "main() : running in audio test mode" << endl; @@ -415,7 +417,7 @@ if(gVerbose==1) cout << "main() : creating control thread" << endl; - if(rt_task_create(&rtSensorThread, rtSensorThreadName, 0, 95, T_JOINABLE | T_FPU)) { + if(rt_task_create(&rtSensorThread, rtSensorThreadName, 0, BEAGLERT_AUDIO_PRIORITY - 5, T_JOINABLE | T_FPU)) { cout << "Error:unable to create Xenomai control thread" << endl; return -1; }
--- a/projects/d-box/render.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/d-box/render.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -5,8 +5,9 @@ * Author: Victor Zappi */ -#include "../../include/RTAudio.h" -#include "../../include/PRU.h" +#include <BeagleRT.h> +#include <PRU.h> + #include "StatusLED.h" #include "config.h" #include "OscillatorBank.h" @@ -19,6 +20,26 @@ #undef DBOX_CAPE_TEST +// Mappings from pin numbers on PCB to actual DAC channels +// This gives the DAC and ADC connectors the same effective pinout +#define DAC_PIN0 6 +#define DAC_PIN1 4 +#define DAC_PIN2 2 +#define DAC_PIN3 0 +#define DAC_PIN4 1 +#define DAC_PIN5 3 +#define DAC_PIN6 5 +#define DAC_PIN7 7 + +#define ADC_PIN0 0 +#define ADC_PIN1 1 +#define ADC_PIN2 2 +#define ADC_PIN3 3 +#define ADC_PIN4 4 +#define ADC_PIN5 5 +#define ADC_PIN6 6 +#define ADC_PIN7 7 + #define N_OCT 4.0 // maximum number of octaves on sensor 1 extern vector<OscillatorBank*> gOscBanks; @@ -28,7 +49,6 @@ extern StatusLED gStatusLED; extern bool gIsLoading; extern bool gAudioIn; -extern int gPeriodSize; float *gOscillatorBuffer1, *gOscillatorBuffer2; float *gOscillatorBufferRead, *gOscillatorBufferWrite; @@ -57,7 +77,7 @@ // sensor 0. extern float gSensor0LatestTouchPos; extern int gSensor0LatestTouchNum; -uint16_t gPitchLatestInput = 0; +float gPitchLatestInput = 0; extern float gSensor1LatestTouchPos[]; //extern float gSensor1LatestTouchSizes[]; @@ -73,9 +93,9 @@ // Loop points from matrix input 4 const int gLoopPointsInputBufferSize = 256; -uint16_t gLoopPointsInputBuffer[gLoopPointsInputBufferSize]; +float gLoopPointsInputBuffer[gLoopPointsInputBufferSize]; int gLoopPointsInputBufferPointer = 0; -int gLoopPointMin = 0, gLoopPointMax = 0; +float gLoopPointMin = 0, gLoopPointMax = 0; // multiplier to activate or mute audio in int audioInStatus = 0; @@ -85,10 +105,10 @@ // pitch vars float octaveSplitter; -u_int16_t semitones[((int)N_OCT*12)+1]; +float semitones[((int)N_OCT*12)+1]; float deltaTouch = 0; -float deltaWeightP = 0.5; -float deltaWeightI = 0.0005; +float deltaWeightP = 0.5 / 65536.0; +float deltaWeightI = 0.0005 / 65536.0; // filter vars ne10_fir_instance_f32_t filter[2]; @@ -122,22 +142,21 @@ float *tableIn, float *tableOut, float *sineTable, float sineMix); -inline uint16_t hysteresis_oscillator(uint16_t input, uint16_t risingThreshold, - uint16_t fallingThreshold, bool *rising); +inline float hysteresis_oscillator(float input, float risingThreshold, + float fallingThreshold, bool *rising); + +void render_medium_prio(); +void render_low_prio(); #ifdef DBOX_CAPE_TEST void render_capetest(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, uint16_t *matrixIn, uint16_t *matrixOut); #endif -bool initialise_render(int numMatrixChannels, int numAudioChannels, - int numMatrixFramesPerPeriod, - int numAudioFramesPerPeriod, - float matrixSampleRate, float audioSampleRate, - void *userData) { +bool setup(BeagleRTContext *context, void *userData) { int oscBankHopSize = *(int *)userData; - if(numMatrixChannels != 8) { + if(context->analogChannels != 8) { printf("Error: D-Box needs matrix enabled with 8 channels.\n"); return false; } @@ -145,19 +164,19 @@ // Allocate two buffers for rendering oscillator bank samples // One will be used for writing in the background while the other is used for reading // on the audio thread. 8-byte alignment needed for the NEON code. - if(posix_memalign((void **)&gOscillatorBuffer1, 8, oscBankHopSize * gNumAudioChannels * sizeof(float))) { + if(posix_memalign((void **)&gOscillatorBuffer1, 8, oscBankHopSize * context->audioChannels * sizeof(float))) { printf("Error allocating render buffers\n"); return false; } - if(posix_memalign((void **)&gOscillatorBuffer2, 8, oscBankHopSize * gNumAudioChannels * sizeof(float))) { + if(posix_memalign((void **)&gOscillatorBuffer2, 8, oscBankHopSize * context->audioChannels * sizeof(float))) { printf("Error allocating render buffers\n"); return false; } gOscillatorBufferWrite = gOscillatorBuffer1; gOscillatorBufferRead = gOscillatorBuffer2; - memset(gOscillatorBuffer1, 0, oscBankHopSize * gNumAudioChannels * sizeof(float)); - memset(gOscillatorBuffer2, 0, oscBankHopSize * gNumAudioChannels * sizeof(float)); + memset(gOscillatorBuffer1, 0, oscBankHopSize * context->audioChannels * sizeof(float)); + memset(gOscillatorBuffer2, 0, oscBankHopSize * context->audioChannels * sizeof(float)); // Initialise the dynamic wavetable used by the oscillator bank // It should match the size of the static one already allocated in the OscillatorBank object @@ -168,18 +187,18 @@ return false; } - gFeedbackOscillator.initialise(8192, 10.0, matrixSampleRate); + gFeedbackOscillator.initialise(8192, 10.0, context->analogSampleRate); for(int n = 0; n < gDynamicWavetableLength + 1; n++) gDynamicWavetable[n] = 0; // pitch - float midPos = (float)65535/2.0; - octaveSplitter = round((float)65535/(N_OCT)); + float midPos = 0.5; + octaveSplitter = 1.0 / N_OCT; int numOfSemi = 12*N_OCT; int middleSemitone = 12*N_OCT/2; int lastSemitone = middleSemitone+numOfSemi/2; - float inc = (float)65535/(N_OCT*12.0); + float inc = 1.0 / (N_OCT*12.0); int i = -1; for(int semi=middleSemitone; semi<=lastSemitone; semi++) semitones[semi] = ( midPos + (++i)*inc) + 0.5; @@ -191,7 +210,7 @@ audioInStatus = 1; // filter - blockSize = 2*gPeriodSize; + blockSize = context->audioFrames; filterState[0] = (ne10_float32_t *) NE10_MALLOC ((FILTER_TAP_NUM+blockSize-1) * sizeof (ne10_float32_t)); filterState[1] = (ne10_float32_t *) NE10_MALLOC ((FILTER_TAP_NUM+blockSize-1) * sizeof (ne10_float32_t)); filterIn[0] = (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t)); @@ -202,24 +221,23 @@ ne10_fir_init_float(&filter[1], FILTER_TAP_NUM, filterTaps, filterState[1], blockSize); // peak outputs - PeakBurst[0].setAttackRate(.00001 * matrixSampleRate); - PeakBurst[1].setAttackRate(.00001 * matrixSampleRate); - PeakBurst[0].setDecayRate(.5 * matrixSampleRate); - PeakBurst[1].setDecayRate(.5 * matrixSampleRate); + PeakBurst[0].setAttackRate(.00001 * context->analogSampleRate); + PeakBurst[1].setAttackRate(.00001 * context->analogSampleRate); + PeakBurst[0].setDecayRate(.5 * context->analogSampleRate); + PeakBurst[1].setDecayRate(.5 * context->analogSampleRate); PeakBurst[0].setSustainLevel(0.0); PeakBurst[1].setSustainLevel(0.0); // Initialise auxiliary tasks - if((gMediumPriorityRender = createAuxiliaryTaskLoop(&render_medium_prio, 90, "dbox-calculation-medium")) == 0) + if((gMediumPriorityRender = BeagleRT_createAuxiliaryTask(&render_medium_prio, BEAGLERT_AUDIO_PRIORITY - 10, "dbox-calculation-medium")) == 0) return false; - if((gLowPriorityRender = createAuxiliaryTaskLoop(&render_low_prio, 85, "dbox-calculation-low")) == 0) + if((gLowPriorityRender = BeagleRT_createAuxiliaryTask(&render_low_prio, BEAGLERT_AUDIO_PRIORITY - 15, "dbox-calculation-low")) == 0) return false; return true; } -void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, - uint16_t *matrixIn, uint16_t *matrixOut) +void render(BeagleRTContext *context, void *userData) { #ifdef DBOX_CAPE_TEST render_capetest(numMatrixFrames, numAudioFrames, audioIn, audioOut, matrixIn, matrixOut); @@ -229,10 +247,10 @@ if(gOscBanks[gCurrentOscBank]->state==bank_playing) { - assert(gNumAudioChannels == 2); + assert(context->audioChannels == 2); #ifdef OLD_OSCBANK - memset(audioOut, 0, numAudioFrames * gNumAudioChannels * sizeof(float)); + memset(audioOut, 0, numAudioFrames * * sizeof(float)); /* Render the oscillator bank. The oscillator bank function is written in NEON assembly * and it strips out all extra checks, so find out in advance whether we can render a whole @@ -269,18 +287,18 @@ gOscBanks[gCurrentOscBank]->oscillatorAmplitudeDerivatives, gDynamicWavetable/*gOscBanks[gCurrentOscBank]->lookupTable*/); framesRemaining -= gOscBanks[gCurrentOscBank]->hopCounter; - audioOutWithOffset += gNumAudioChannels * gOscBanks[gCurrentOscBank]->hopCounter; + audioOutWithOffset += * gOscBanks[gCurrentOscBank]->hopCounter; gOscBanks[gCurrentOscBank]->sampleCount += gOscBanks[gCurrentOscBank]->hopCounter; gOscBanks[gCurrentOscBank]->nextHop(); } } #else - for(int n = 0; n < numAudioFrames; n++) { - audioOut[2*n] = gOscillatorBufferRead[gOscillatorBufferReadPointer++]+audioIn[2*n]*audioInStatus; - audioOut[2*n + 1] = gOscillatorBufferRead[gOscillatorBufferReadPointer++]+audioIn[2*n+1]*audioInStatus; + for(unsigned int n = 0; n < context->audioFrames; n++) { + context->audioOut[2*n] = gOscillatorBufferRead[gOscillatorBufferReadPointer++]+context->audioIn[2*n]*audioInStatus; + context->audioOut[2*n + 1] = gOscillatorBufferRead[gOscillatorBufferReadPointer++]+context->audioIn[2*n+1]*audioInStatus; - filterIn[0][n] = fabs(audioIn[2*n]); // rectify for peak detection in 1 - filterIn[1][n] = fabs(audioIn[2*n+1]); // rectify for peak detection in 2 + filterIn[0][n] = fabs(context->audioIn[2*n]); // rectify for peak detection in 1 + filterIn[1][n] = fabs(context->audioIn[2*n+1]); // rectify for peak detection in 2 /* FIXME why doesn't this work? */ /* @@ -305,19 +323,19 @@ gOscillatorBufferReadPointer = 0; gOscillatorNeedsRender = true; - scheduleAuxiliaryTask(gMediumPriorityRender); + BeagleRT_scheduleAuxiliaryTask(gMediumPriorityRender); } } #endif } else { - for(int n = 0; n < numAudioFrames; n++) { - audioOut[2*n] = audioIn[2*n]*audioInStatus; - audioOut[2*n + 1] = audioIn[2*n+1]*audioInStatus; + for(unsigned int n = 0; n < context->audioFrames; n++) { + context->audioOut[2*n] = context->audioIn[2*n]*audioInStatus; + context->audioOut[2*n + 1] = context->audioIn[2*n+1]*audioInStatus; - filterIn[0][n] = fabs(audioIn[2*n]); // rectify for peak detection in 1 - filterIn[1][n] = fabs(audioIn[2*n+1]); // rectify for peak detection in 2 + filterIn[0][n] = fabs(context->audioIn[2*n]); // rectify for peak detection in 1 + filterIn[1][n] = fabs(context->audioIn[2*n+1]); // rectify for peak detection in 2 } } @@ -325,7 +343,7 @@ ne10_fir_float_neon(&filter[0], filterIn[0], filterOut[0], blockSize); ne10_fir_float_neon(&filter[1], filterIn[1], filterOut[1], blockSize); - for(int n = 0; n < numMatrixFrames; n++) { + for(unsigned int n = 0; n < context->analogFrames; n++) { /* Matrix Out 0, In 0 @@ -333,12 +351,12 @@ * CV loop * Controls pitch of sound */ - int touchPosInt = gSensor0LatestTouchPos * 65536.0; + float touchPosInt = gSensor0LatestTouchPos; if(touchPosInt < 0) touchPosInt = 0; - if(touchPosInt > 65535) touchPosInt = 65535; - matrixOut[n*8 + DAC_PIN0] = touchPosInt; + if(touchPosInt > 1.0) touchPosInt = 1.0; + context->analogOut[n*8 + DAC_PIN0] = touchPosInt; - gPitchLatestInput = matrixIn[n*8 + ADC_PIN0]; + gPitchLatestInput = context->analogIn[n*8 + ADC_PIN0]; /* Matrix Out 7 @@ -351,17 +369,17 @@ if(gSensor0LatestTouchNum>0) { // current pitch is gPitchLatestInput, already retrieved - semitoneIndex = ( ( (float)gPitchLatestInput / 65535)*12*N_OCT )+0.5; // closest semitone + semitoneIndex = ( gPitchLatestInput * 12 * N_OCT )+0.5; // closest semitone deltaTarget = (semitones[semitoneIndex]-gPitchLatestInput); // delta between pitch and target - deltaTouch += deltaTarget*deltaWeightI; // update feedback [previous + current] + deltaTouch += deltaTarget*(deltaWeightI); // update feedback [previous + current] } else deltaTouch = 0; - int nextOut = touchPosInt + deltaTarget*deltaWeightP + deltaTouch; // add feedback to touch -> next out + float nextOut = touchPosInt + deltaTarget*deltaWeightP + deltaTouch; // add feedback to touch -> next out if(nextOut < 0) nextOut = 0; // clamp - if(nextOut > 65535) nextOut = 65535; // clamp - matrixOut[n*8 + DAC_PIN7] = nextOut; // send next nextOut + if(nextOut > 1.0) nextOut = 1.0; // clamp + context->analogOut[n*8 + DAC_PIN7] = nextOut; // send next nextOut /* @@ -371,7 +389,8 @@ * Controls speed of playback */ bool wasRising = gSpeedHysteresisOscillatorRising; - matrixOut[n*8 + DAC_PIN1] = hysteresis_oscillator(matrixIn[n*8 + ADC_PIN1], 48000, 16000, &gSpeedHysteresisOscillatorRising); + context->analogOut[n*8 + DAC_PIN1] = hysteresis_oscillator(context->analogIn[n*8 + ADC_PIN1], 48000.0/65536.0, + 16000.0/65536.0, &gSpeedHysteresisOscillatorRising); // Find interval of zero crossing if(wasRising && !gSpeedHysteresisOscillatorRising) { @@ -394,12 +413,12 @@ * Controls wavetable used for oscillator bank */ - int tableLength = gFeedbackOscillator.process(matrixIn[n*8 + ADC_PIN2], &matrixOut[n*8 + DAC_PIN2]); + int tableLength = gFeedbackOscillator.process(context->analogIn[n*8 + ADC_PIN2], &context->analogOut[n*8 + DAC_PIN2]); if(tableLength != 0) { gFeedbackOscillatorTableLength = tableLength; gFeedbackOscillatorTable = gFeedbackOscillator.wavetable(); gDynamicWavetableNeedsRender = true; - scheduleAuxiliaryTask(gLowPriorityRender); + BeagleRT_scheduleAuxiliaryTask(gLowPriorityRender); } /* @@ -411,10 +430,10 @@ */ volatile int touchCount = gSensor1LatestTouchCount; if(touchCount == 0) - matrixOut[n*8 + DAC_PIN3] = 0; + context->analogOut[n*8 + DAC_PIN3] = 0; else { int touchIndex = (gMatrixSampleCount >> 5) % touchCount; - matrixOut[n*8 + DAC_PIN3] = gSensor1LatestTouchPos[touchIndex] * 56000.0f; + context->analogOut[n*8 + DAC_PIN3] = gSensor1LatestTouchPos[touchIndex] * 56000.0f / 65536.0f; if(touchIndex != gSensor1LastTouchIndex) { // Just changed to a new touch output. Reset the counter. // It will take 2*matrixFrames samples for this output to come back to the @@ -422,33 +441,33 @@ // let's say 24 samples into it. // FIXME this won't work for p > 2 - gSensor1InputDelayCounter = 24 + 2*numMatrixFrames; + gSensor1InputDelayCounter = 24 + 2*context->analogFrames; gSensor1InputIndex = touchIndex; } gSensor1LastTouchIndex = touchIndex; } if(gSensor1InputDelayCounter-- >= 0 && touchCount > 0) { - gSensor1MatrixTouchPos[gSensor1InputIndex] = (float)matrixIn[n*8 + ADC_PIN3] / 65536.0f; + gSensor1MatrixTouchPos[gSensor1InputIndex] = context->analogIn[n*8 + ADC_PIN3]; } /* Matrix Out 4 * * Sensor 1 last pos */ - touchPosInt = gSensor1LatestTouchPos[gSensor1LatestTouchIndex] * 65536.0; + touchPosInt = gSensor1LatestTouchPos[gSensor1LatestTouchIndex]; if(touchPosInt < 0) touchPosInt = 0; - if(touchPosInt > 65535) touchPosInt = 65535; - matrixOut[n*8 + DAC_PIN4] = touchPosInt; + if(touchPosInt > 1.0) touchPosInt = 1.0; + context->analogOut[n*8 + DAC_PIN4] = touchPosInt; /* Matrix In 4 * * Loop points selector */ - gLoopPointsInputBuffer[gLoopPointsInputBufferPointer++] = matrixIn[n*8 + ADC_PIN4]; + gLoopPointsInputBuffer[gLoopPointsInputBufferPointer++] = context->analogIn[n*8 + ADC_PIN4]; if(gLoopPointsInputBufferPointer >= gLoopPointsInputBufferSize) { // Find min and max values - uint16_t loopMax = 0, loopMin = 65535; + float loopMax = 0, loopMin = 1.0; for(int i = 0; i < gLoopPointsInputBufferSize; i++) { if(gLoopPointsInputBuffer[i] < loopMin) loopMin = gLoopPointsInputBuffer[i]; @@ -482,8 +501,8 @@ PeakBurst[0].process(1); - int convAudio = burstOut*peak[0]*65535; - matrixOut[n*8 + DAC_PIN5] = convAudio; + float convAudio = burstOut*peak[0]; + context->analogOut[n*8 + DAC_PIN5] = convAudio; prevFiltered[0] = filterOut[0][n*2+1]; if(prevFiltered[0]>1) prevFiltered[0] = 1; @@ -492,8 +511,8 @@ * * Dissonance, via changing frequency motion of partials */ - float amount = (float)matrixIn[n*8 + ADC_PIN5] / 65536.0f; - gOscBanks[gCurrentOscBank]->freqMovement = 1-amount; + float amount = (float)context->analogIn[n*8 + ADC_PIN5]; + gOscBanks[gCurrentOscBank]->freqMovement = 1.0 - amount; @@ -516,8 +535,8 @@ PeakBurst[1].process(1); - convAudio = burstOut*peak[1]*65535; - matrixOut[n*8 + DAC_PIN6] = convAudio; + convAudio = burstOut*peak[1]; + context->analogOut[n*8 + DAC_PIN6] = convAudio; prevFiltered[1] = filterOut[1][n*2+1]; if(prevFiltered[1]>1) prevFiltered[1] = 1; @@ -529,14 +548,14 @@ if(!gIsLoading) { // Use hysteresis to avoid jumping back and forth between sounds if(gOscBanks.size() > 1) { - int input = matrixIn[n*8 + ADC_PIN6]; - const int hystValue = 16000; + float input = context->analogIn[n*8 + ADC_PIN6]; + const float hystValue = 16000.0 / 65536.0; - int upHysteresisValue = ((gCurrentOscBank + 1) * 65536 + hystValue) / gOscBanks.size(); - int downHysteresisValue = (gCurrentOscBank * 65536 - hystValue) / gOscBanks.size(); + float upHysteresisValue = ((gCurrentOscBank + 1) + hystValue) / gOscBanks.size(); + float downHysteresisValue = (gCurrentOscBank - hystValue) / gOscBanks.size(); if(input > upHysteresisValue || input < downHysteresisValue) { - gNextOscBank = input * gOscBanks.size() / 65536; + gNextOscBank = input * gOscBanks.size(); if(gNextOscBank < 0) gNextOscBank = 0; if((unsigned)gNextOscBank >= gOscBanks.size()) @@ -551,8 +570,8 @@ * FSR from primary touch sensor * Value ranges from 0-1799 */ - gLastFSRValue = matrixIn[n*8 + ADC_PIN7] * (1799.0 / 65535.0); - //gLastFSRValue = 1799 - matrixIn[n*8 + ADC_PIN7] * (1799.0 / 65535.0); + gLastFSRValue = context->analogIn[n*8 + ADC_PIN7] * 1799.0; + //gLastFSRValue = 1799 - context->analogIn[n*8 + ADC_PIN7] * (1799.0 / 65535.0); //dbox_printf("%i\n",gLastFSRValue); gMatrixSampleCount++; @@ -569,7 +588,7 @@ gOscillatorNeedsRender = false; /* Render one frame into the write buffer */ - memset(gOscillatorBufferWrite, 0, gOscBanks[gCurrentOscBank]->hopCounter * gNumAudioChannels * sizeof(float)); + memset(gOscillatorBufferWrite, 0, gOscBanks[gCurrentOscBank]->hopCounter * 2 * sizeof(float)); /* assumes 2 audio channels */ oscillator_bank_neon(gOscBanks[gCurrentOscBank]->hopCounter, gOscillatorBufferWrite, gOscBanks[gCurrentOscBank]->actPartNum, gOscBanks[gCurrentOscBank]->lookupTableSize, @@ -579,7 +598,7 @@ gOscBanks[gCurrentOscBank]->oscillatorAmplitudeDerivatives, /*gOscBanks[gCurrentOscBank]->lookupTable*/gDynamicWavetable); - gOscillatorBufferWriteCurrentSize = gOscBanks[gCurrentOscBank]->hopCounter * gNumAudioChannels; + gOscillatorBufferWriteCurrentSize = gOscBanks[gCurrentOscBank]->hopCounter * 2; /* Update the pitch right before the hop * Total CV range +/- N_OCT octaves @@ -660,7 +679,7 @@ gOscBanks[gCurrentOscBank]->lookupTable, sineMix); } - if(gLoopPointMin >= 60000 && gLoopPointMax >= 60000) { + if(gLoopPointMin >= 60000.0/65536.0 && gLoopPointMax >= 60000.0/65536.0) { // KLUDGE! if(gCurrentOscBank == 0) gOscBanks[gCurrentOscBank]->setLoopHops(50, ((float)gOscBanks[gCurrentOscBank]->getLastHop() * 0.6) - 1); @@ -668,8 +687,8 @@ gOscBanks[gCurrentOscBank]->setLoopHops(5, ((float)gOscBanks[gCurrentOscBank]->getLastHop() * 0.7) - 1); } else { - float normLoopPointMin = (float)gLoopPointMin * gOscBanks[gCurrentOscBank]->getLastHop() / 65535.0; - float normLoopPointMax = (float)gLoopPointMax * gOscBanks[gCurrentOscBank]->getLastHop() / 65535.0; + float normLoopPointMin = (float)gLoopPointMin * gOscBanks[gCurrentOscBank]->getLastHop(); + float normLoopPointMax = (float)gLoopPointMax * gOscBanks[gCurrentOscBank]->getLastHop(); int intLoopPointMin = normLoopPointMin; if(intLoopPointMin < 1) @@ -712,7 +731,7 @@ } // Clean up at the end of render -void cleanup_render() +void cleanup(BeagleRTContext *context, void *userData) { free(gOscillatorBuffer1); free(gOscillatorBuffer2); @@ -744,9 +763,9 @@ } // Create a hysteresis oscillator with a matrix input and output -inline uint16_t hysteresis_oscillator(uint16_t input, uint16_t risingThreshold, uint16_t fallingThreshold, bool *rising) +inline float hysteresis_oscillator(float input, float risingThreshold, float fallingThreshold, bool *rising) { - uint16_t value; + float value; if(*rising) { if(input > risingThreshold) { @@ -754,12 +773,12 @@ value = 0; } else - value = 65535; + value = 1.0; } else { if(input < fallingThreshold) { *rising = true; - value = 65535; + value = 1.0; } else value = 0;
--- a/projects/filter_FIR/main.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/filter_FIR/main.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -12,7 +12,8 @@ #include <string> #include <getopt.h> #include <sndfile.h> // to load audio files -#include "../../include/RTAudio.h" + +#include <BeagleRT.h> #include "SampleData.h" using namespace std; @@ -90,7 +91,7 @@ int main(int argc, char *argv[]) { - RTAudioSettings settings; // Standard audio settings + BeagleRTInitSettings settings; // Standard audio settings string fileName; // Name of the sample to load SampleData sampleData; // User define structure to pass data retrieved from file to render function
--- a/projects/filter_FIR/render.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/filter_FIR/render.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -6,11 +6,8 @@ */ -#include "../../include/render.h" -#include "../../include/RTAudio.h" // to schedule lower prio parallel process -#include <rtdk.h> +#include <BeagleRT.h> #include <cmath> -#include <stdio.h> #include <NE10.h> // neon library #include "SampleData.h" #include "FIRfilter.h" @@ -25,8 +22,7 @@ ne10_uint32_t blockSize; ne10_float32_t *gFIRfilterState; -void initialise_filter(); - +void initialise_filter(BeagleRTContext *context); // Task for handling the update of the frequencies using the matrix AuxiliaryTask gTriggerSamplesTask; @@ -34,10 +30,7 @@ bool initialise_trigger(); void trigger_samples(); -int gPeriodSize; // Period size in sensor frames - - -// initialise_render() is called once before the audio rendering starts. +// setup() is called once before the audio rendering starts. // Use it to perform any initialisation and allocation which is dependent // on the period size or sample rate. // @@ -46,20 +39,15 @@ // // Return true on success; returning false halts the program. -bool initialise_render(int numMatrixChannels, int numAudioChannels, - int numMatrixFramesPerPeriod, - int numAudioFramesPerPeriod, - float matrixSampleRate, float audioSampleRate, - void *userData) +bool setup(BeagleRTContext *context, void *userData) { // Retrieve a parameter passed in from the initAudio() call gSampleData = *(SampleData *)userData; gReadPtr = -1; - gPeriodSize = numMatrixFramesPerPeriod; - initialise_filter(); + initialise_filter(context); // Initialise auxiliary tasks if(!initialise_trigger()) @@ -73,10 +61,9 @@ // ADCs and DACs (if available). If only audio is available, numMatrixFrames // will be 0. -void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, - uint16_t *matrixIn, uint16_t *matrixOut) +void render(BeagleRTContext *context, void *userData) { - for(int n = 0; n < numAudioFrames; n++) { + for(unsigned int n = 0; n < context->audioFrames; n++) { float in = 0; // If triggered... @@ -91,21 +78,21 @@ ne10_fir_float_neon(&gFIRfilter, gFIRfilterIn, gFIRfilterOut, blockSize); - for(int n = 0; n < numAudioFrames; n++) { - for(int channel = 0; channel < gNumAudioChannels; channel++) - audioOut[n * gNumAudioChannels + channel] = gFIRfilterOut[n]; // ...and put it in both left and right channel + for(unsigned int n = 0; n < context->audioFrames; n++) { + for(unsigned int channel = 0; channel < context->audioChannels; channel++) + context->audioOut[n * context->audioChannels + channel] = gFIRfilterOut[n]; // ...and put it in both left and right channel } // Request that the lower-priority task run at next opportunity - scheduleAuxiliaryTask(gTriggerSamplesTask); + BeagleRT_scheduleAuxiliaryTask(gTriggerSamplesTask); } // Initialise NE10 data structures to define FIR filter -void initialise_filter() +void initialise_filter(BeagleRTContext *context) { - blockSize = 2*gPeriodSize; + blockSize = context->audioFrames; gFIRfilterState = (ne10_float32_t *) NE10_MALLOC ((FILTER_TAP_NUM+blockSize-1) * sizeof (ne10_float32_t)); gFIRfilterIn = (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t)); gFIRfilterOut = (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t)); @@ -118,7 +105,7 @@ bool initialise_trigger() { - if((gTriggerSamplesTask = createAuxiliaryTaskLoop(&trigger_samples, 50, "beaglert-trigger-samples")) == 0) + if((gTriggerSamplesTask = BeagleRT_createAuxiliaryTask(&trigger_samples, 50, "beaglert-trigger-samples")) == 0) return false; rt_printf("Press 'a' to trigger sample, 's' to stop\n"); @@ -161,10 +148,10 @@ -// cleanup_render() is called once at the end, after the audio has stopped. -// Release any resources that were allocated in initialise_render(). +// cleanup() is called once at the end, after the audio has stopped. +// Release any resources that were allocated in setup(). -void cleanup_render() +void cleanup(BeagleRTContext *context, void *userData) { delete[] gSampleData.samples;
--- a/projects/filter_IIR/main.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/filter_IIR/main.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -12,7 +12,8 @@ #include <string> #include <getopt.h> #include <sndfile.h> // to load audio files -#include "../../include/RTAudio.h" + +#include <BeagleRT.h> #include "SampleData.h" using namespace std; @@ -92,7 +93,7 @@ int main(int argc, char *argv[]) { - RTAudioSettings settings; // Standard audio settings + BeagleRTInitSettings settings; // Standard audio settings string fileName; // Name of the sample to load SampleData sampleData; // User define structure to pass data retrieved from file to render function
--- a/projects/filter_IIR/render.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/filter_IIR/render.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -6,8 +6,7 @@ */ -#include "../../include/render.h" -#include "../../include/RTAudio.h" // to schedule lower prio parallel process +#include <BeagleRT.h> // to schedule lower prio parallel process #include <rtdk.h> #include <cmath> #include <stdio.h> @@ -45,7 +44,7 @@ extern float gCutFreq; -// initialise_render() is called once before the audio rendering starts. +// setup() is called once before the audio rendering starts. // Use it to perform any initialisation and allocation which is dependent // on the period size or sample rate. // @@ -54,11 +53,7 @@ // // Return true on success; returning false halts the program. -bool initialise_render(int numMatrixChannels, int numAudioChannels, - int numMatrixFramesPerPeriod, - int numAudioFramesPerPeriod, - float matrixSampleRate, float audioSampleRate, - void *userData) +bool setup(BeagleRTContext *context, void *userData) { // Retrieve a parameter passed in from the initAudio() call @@ -80,10 +75,9 @@ // ADCs and DACs (if available). If only audio is available, numMatrixFrames // will be 0. -void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, - uint16_t *matrixIn, uint16_t *matrixOut) +void render(BeagleRTContext *context, void *userData) { - for(int n = 0; n < numAudioFrames; n++) { + for(unsigned int n = 0; n < context->audioFrames; n++) { float sample = 0; float out = 0; @@ -101,14 +95,14 @@ gLastY[1] = gLastY[0]; gLastY[0] = out; - for(int channel = 0; channel < gNumAudioChannels; channel++) - audioOut[n * gNumAudioChannels + channel] = out; // ...and put it in both left and right channel + for(unsigned int channel = 0; channel < context->audioChannels; channel++) + context->audioOut[n * context->audioChannels + channel] = out; // ...and put it in both left and right channel } // Request that the lower-priority tasks run at next opportunity - scheduleAuxiliaryTask(gChangeCoeffTask); - scheduleAuxiliaryTask(gInputTask); + BeagleRT_scheduleAuxiliaryTask(gChangeCoeffTask); + BeagleRT_scheduleAuxiliaryTask(gInputTask); } // First calculation of coefficients @@ -145,10 +139,10 @@ bool initialise_aux_tasks() { - if((gChangeCoeffTask = createAuxiliaryTaskLoop(&check_coeff, 90, "beaglert-check-coeff")) == 0) + if((gChangeCoeffTask = BeagleRT_createAuxiliaryTask(&check_coeff, 90, "beaglert-check-coeff")) == 0) return false; - if((gInputTask = createAuxiliaryTaskLoop(&read_input, 50, "beaglert-read-input")) == 0) + if((gInputTask = BeagleRT_createAuxiliaryTask(&read_input, 50, "beaglert-read-input")) == 0) return false; rt_printf("Press 'a' to trigger sample, 's' to stop\n"); @@ -218,10 +212,10 @@ -// cleanup_render() is called once at the end, after the audio has stopped. -// Release any resources that were allocated in initialise_render(). +// cleanup() is called once at the end, after the audio has stopped. +// Release any resources that were allocated in setup(). -void cleanup_render() +void cleanup(BeagleRTContext *context, void *userData) { delete[] gSampleData.samples; }
--- a/projects/oscillator_bank/main.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/oscillator_bank/main.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -10,7 +10,7 @@ #include <libgen.h> #include <signal.h> #include <getopt.h> -#include "../../include/RTAudio.h" +#include <BeagleRT.h> using namespace std; @@ -37,7 +37,7 @@ int main(int argc, char *argv[]) { - RTAudioSettings settings; // Standard audio settings + BeagleRTInitSettings settings; // Standard audio settings struct option customOptions[] = {
--- a/projects/oscillator_bank/render.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/oscillator_bank/render.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -6,8 +6,8 @@ */ -#include "../../include/RTAudio.h" -#include "../../include/Utilities.h" +#include <BeagleRT.h> +#include <Utilities.h> #include <rtdk.h> #include <cstdlib> #include <cmath> @@ -34,7 +34,7 @@ // These settings are carried over from main.cpp // Setting global variables is an alternative approach -// to passing a structure to userData in initialise_render() +// to passing a structure to userData in setup() extern int gNumOscillators; extern int gWavetableLength; @@ -50,7 +50,7 @@ float *lookupTable); } -// initialise_render() is called once before the audio rendering starts. +// setup() is called once before the audio rendering starts. // Use it to perform any initialisation and allocation which is dependent // on the period size or sample rate. // @@ -58,15 +58,11 @@ // in from the call to initAudio(). // // Return true on success; returning false halts the program. -bool initialise_render(int numMatrixChannels, int numAudioChannels, - int numMatrixFramesPerPeriod, - int numAudioFramesPerPeriod, - float matrixSampleRate, float audioSampleRate, - void *userData) +bool setup(BeagleRTContext *context, void *userData) { srandom(time(NULL)); - if(numAudioChannels != 2) { + if(context->audioChannels != 2) { rt_printf("Error: this example needs stereo audio enabled\n"); return false; } @@ -109,7 +105,7 @@ for(int n = 0; n < gNumOscillators; n++) { gPhases[n] = 0.0; - if(numMatrixFramesPerPeriod == 0) { + if(context->analogFrames == 0) { // Random frequencies when used without matrix gFrequencies[n] = kMinimumFrequency + (kMaximumFrequency - kMinimumFrequency) * ((float)random() / (float)RAND_MAX); } @@ -120,16 +116,34 @@ } // For efficiency, frequency is expressed in change in wavetable position per sample, not Hz or radians - gFrequencies[n] *= (float)gWavetableLength / audioSampleRate; + gFrequencies[n] *= (float)gWavetableLength / context->audioSampleRate; gAmplitudes[n] = ((float)random() / (float)RAND_MAX) / (float)gNumOscillators; gDFrequencies[n] = gDAmplitudes[n] = 0.0; } + increment = 0; + freq = 440.0; + + for(int n = 0; n < gNumOscillators; n++) { + // Update the frequencies to a regular spread, plus a small amount of randomness + // to avoid weird phase effects + float randScale = 0.99 + .02 * (float)random() / (float)RAND_MAX; + float newFreq = freq * randScale; + + // For efficiency, frequency is expressed in change in wavetable position per sample, not Hz or radians + gFrequencies[n] = newFreq * (float)gWavetableLength / context->audioSampleRate; + + freq += increment; + } + // Initialise auxiliary tasks - if((gFrequencyUpdateTask = createAuxiliaryTaskLoop(&recalculate_frequencies, 90, "beaglert-update-frequencies")) == 0) + if((gFrequencyUpdateTask = BeagleRT_createAuxiliaryTask(&recalculate_frequencies, 85, "beaglert-update-frequencies")) == 0) return false; - gAudioSampleRate = audioSampleRate; + //for(int n = 0; n < gNumOscillators; n++) + // rt_printf("%f\n", gFrequencies[n]); + + gAudioSampleRate = context->audioSampleRate; gSampleCount = 0; return true; @@ -140,23 +154,22 @@ // ADCs and DACs (if available). If only audio is available, numMatrixFrames // will be 0. -void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, - uint16_t *matrixIn, uint16_t *matrixOut) +void render(BeagleRTContext *context, void *userData) { // Initialise buffer to 0 - memset(audioOut, 0, 2 * numAudioFrames * sizeof(float)); + memset(context->audioOut, 0, 2 * context->audioFrames * sizeof(float)); // Render audio frames - oscillator_bank_neon(numAudioFrames, audioOut, + oscillator_bank_neon(context->audioFrames, context->audioOut, gNumOscillators, gWavetableLength, gPhases, gFrequencies, gAmplitudes, gDFrequencies, gDAmplitudes, gWavetable); - if(numMatrixFrames != 0 && (gSampleCount += numAudioFrames) >= 128) { + if(context->analogFrames != 0 && (gSampleCount += context->audioFrames) >= 128) { gSampleCount = 0; - gNewMinFrequency = map(matrixIn[0], 0, MATRIX_MAX, 20.0f, 8000.0f); - gNewMaxFrequency = map(matrixIn[1], 0, MATRIX_MAX, 20.0f, 8000.0f); + gNewMinFrequency = map(context->analogIn[0], 0, 1.0, 1000.0f, 8000.0f); + gNewMaxFrequency = map(context->analogIn[1], 0, 1.0, 1000.0f, 8000.0f); // Make sure max >= min if(gNewMaxFrequency < gNewMinFrequency) { @@ -166,7 +179,7 @@ } // Request that the lower-priority task run at next opportunity - scheduleAuxiliaryTask(gFrequencyUpdateTask); + //BeagleRT_scheduleAuxiliaryTask(gFrequencyUpdateTask); } } @@ -194,10 +207,10 @@ } -// cleanup_render() is called once at the end, after the audio has stopped. -// Release any resources that were allocated in initialise_render(). +// cleanup() is called once at the end, after the audio has stopped. +// Release any resources that were allocated in setup(). -void cleanup_render() +void cleanup(BeagleRTContext *context, void *userData) { free(gWavetable); free(gPhases);
--- a/projects/samples/main.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/samples/main.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -12,7 +12,8 @@ #include <string> #include <getopt.h> #include <sndfile.h> // to load audio files -#include "../../include/RTAudio.h" + +#include <BeagleRT.h> #include "SampleData.h" using namespace std; @@ -90,7 +91,7 @@ int main(int argc, char *argv[]) { - RTAudioSettings settings; // Standard audio settings + BeagleRTInitSettings settings; // Standard audio settings string fileName; // Name of the sample to load SampleData sampleData; // User define structure to pass data retrieved from file to render function
--- a/projects/samples/render.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/samples/render.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -6,11 +6,8 @@ */ -#include "../../include/render.h" -#include "../../include/RTAudio.h" // to schedule lower prio parallel process -#include <rtdk.h> +#include <BeagleRT.h> #include <cmath> -#include <stdio.h> #include "SampleData.h" SampleData gSampleData; // User defined structure to get complex data from main @@ -22,7 +19,7 @@ bool initialise_trigger(); void trigger_samples(); -// initialise_render() is called once before the audio rendering starts. +// setup() is called once before the audio rendering starts. // Use it to perform any initialisation and allocation which is dependent // on the period size or sample rate. // @@ -31,11 +28,7 @@ // // Return true on success; returning false halts the program. -bool initialise_render(int numMatrixChannels, int numAudioChannels, - int numMatrixFramesPerPeriod, - int numAudioFramesPerPeriod, - float matrixSampleRate, float audioSampleRate, - void *userData) +bool setup(BeagleRTContext *context, void *userData) { // Retrieve a parameter passed in from the initAudio() call @@ -55,10 +48,9 @@ // ADCs and DACs (if available). If only audio is available, numMatrixFrames // will be 0. -void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, - uint16_t *matrixIn, uint16_t *matrixOut) +void render(BeagleRTContext *context, void *userData) { - for(int n = 0; n < numAudioFrames; n++) { + for(unsigned int n = 0; n < context->audioFrames; n++) { float out = 0; // If triggered... @@ -68,12 +60,12 @@ if(gReadPtr >= gSampleData.sampleLen) gReadPtr = -1; - for(int channel = 0; channel < gNumAudioChannels; channel++) - audioOut[n * gNumAudioChannels + channel] = out; // ...and put it in both left and right channel + for(unsigned int channel = 0; channel < context->audioChannels; channel++) + context->audioOut[n * context->audioChannels + channel] = out; // ...and put it in both left and right channel } // Request that the lower-priority task run at next opportunity - scheduleAuxiliaryTask(gTriggerSamplesTask); + BeagleRT_scheduleAuxiliaryTask(gTriggerSamplesTask); } // Initialise the auxiliary task @@ -81,7 +73,7 @@ bool initialise_trigger() { - if((gTriggerSamplesTask = createAuxiliaryTaskLoop(&trigger_samples, 50, "beaglert-trigger-samples")) == 0) + if((gTriggerSamplesTask = BeagleRT_createAuxiliaryTask(&trigger_samples, 50, "beaglert-trigger-samples")) == 0) return false; rt_printf("Press 'a' to trigger sample, 's' to stop\n"); @@ -124,10 +116,10 @@ -// cleanup_render() is called once at the end, after the audio has stopped. -// Release any resources that were allocated in initialise_render(). +// cleanup() is called once at the end, after the audio has stopped. +// Release any resources that were allocated in setup(). -void cleanup_render() +void cleanup(BeagleRTContext *context, void *userData) { delete[] gSampleData.samples; }
--- a/projects/tank_wars/game.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/tank_wars/game.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -33,6 +33,9 @@ float projectilePositionX, projectilePositionY; float projectileVelocityX, projectileVelocityY; +// Infor needed for sound rendering +bool collisionJustOccurred = false; + // Useful utility function for generating random floating-point values float randomFloat(float low, float hi) { @@ -101,6 +104,7 @@ <= tankRadius * tankRadius) { projectileInMotion = false; + collisionJustOccurred = true; playerHasWon = 2; } else if((tank2X - projectilePositionX)*(tank2X - projectilePositionX) + @@ -108,16 +112,19 @@ <= tankRadius * tankRadius) { projectileInMotion = false; + collisionJustOccurred = true; playerHasWon = 1; } else if(projectilePositionX < 0 || projectilePositionX >= screenWidth) { // Check collision whether projectile has exited the screen to the left or right projectileInMotion = false; + collisionJustOccurred = true; nextPlayersTurn(); } else if(projectilePositionY >= groundLevel[(int)floorf(projectilePositionX)]) { // Check for projectile collision with ground projectileInMotion = false; + collisionJustOccurred = true; nextPlayersTurn(); } } @@ -185,6 +192,20 @@ return playerHasWon; } +bool gameStatusCollisionOccurred() +{ + if(collisionJustOccurred) { + collisionJustOccurred = false; + return true; + } + return false; +} + +float gameStatusProjectileHeight() +{ + return projectilePositionY / (float)screenHeight; +} + // Clean up any allocated memory for the game void cleanupGame() {
--- a/projects/tank_wars/game.h Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/tank_wars/game.h Fri Jul 17 15:28:18 2015 +0100 @@ -26,6 +26,8 @@ bool gameStatusPlayer1Turn(); bool gameStatusProjectileInMotion(); int gameStatusWinner(); +bool gameStatusCollisionOccurred(); +float gameStatusProjectileHeight(); // Render screen; returns length of buffer used int drawGame(float *buffer, int bufferSize);
--- a/projects/tank_wars/main.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/tank_wars/main.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -10,12 +10,54 @@ #include <libgen.h> #include <signal.h> #include <getopt.h> -#include "../../include/RTAudio.h" +#include <sndfile.h> +#include <BeagleRT.h> extern int gScreenFramesPerSecond; +float *gMusicBuffer = 0; +int gMusicBufferLength = 0; +float *gSoundBoomBuffer = 0; +int gSoundBoomBufferLength = 0; + using namespace std; +// Load a sound sample from file +int loadSoundFile(const string& path, float **buffer, int *bufferLength) +{ + SNDFILE *sndfile ; + SF_INFO sfinfo ; + + if (!(sndfile = sf_open (path.c_str(), SFM_READ, &sfinfo))) { + cout << "Couldn't open file " << path << endl; + return 1; + } + + int numChan = sfinfo.channels; + if(numChan != 1) + { + cout << "Error: " << path << " is not a mono file" << endl; + return 1; + } + + *bufferLength = sfinfo.frames * numChan; + *buffer = new float[*bufferLength]; + if(*buffer == 0){ + cout << "Could not allocate buffer" << endl; + return 1; + } + + int subformat = sfinfo.format & SF_FORMAT_SUBMASK; + int readcount = sf_read_float(sndfile, *buffer, *bufferLength); + + // Pad with zeros in case we couldn't read whole file + for(int k = readcount; k < *bufferLength; k++) + (*buffer)[k] = 0; + + sf_close(sndfile); + return 0; +} + // Handle Ctrl-C by requesting that the audio rendering stop void interrupt_handler(int var) { @@ -35,7 +77,9 @@ int main(int argc, char *argv[]) { - RTAudioSettings settings; // Standard audio settings + BeagleRTInitSettings settings; // Standard audio settings + string musicFileName = "music.wav"; + string soundBoomFileName = "boom.wav"; struct option customOptions[] = { @@ -70,6 +114,14 @@ } } + // Load the sound files + if(loadSoundFile(musicFileName, &gMusicBuffer, &gMusicBufferLength) != 0) { + cout << "Warning: unable to load sound file " << musicFileName << endl; + } + if(loadSoundFile(soundBoomFileName, &gSoundBoomBuffer, &gSoundBoomBufferLength) != 0) { + cout << "Warning: unable to load sound file " << soundBoomFileName << endl; + } + // Initialise the PRU audio device if(BeagleRT_initAudio(&settings, 0) != 0) { cout << "Error: unable to initialise audio" << endl; @@ -97,6 +149,12 @@ // Clean up any resources allocated for audio BeagleRT_cleanupAudio(); + // Release sound files + if(gMusicBuffer != 0) + free(gMusicBuffer); + if(gSoundBoomBuffer != 0) + free(gSoundBoomBuffer); + // All done! return 0; }
--- a/projects/tank_wars/render.cpp Sun Feb 08 00:20:01 2015 +0000 +++ b/projects/tank_wars/render.cpp Fri Jul 17 15:28:18 2015 +0100 @@ -6,14 +6,16 @@ */ -#include "../../include/RTAudio.h" -#include "../../include/Utilities.h" +#include <BeagleRT.h> +#include <Utilities.h> #include "game.h" #include <rtdk.h> #include <cmath> #include <cstdlib> #include <time.h> +int gAudioFramesPerMatrixFrame = 2; // Ratio in audio to matrix sample rate + int gInputTank1Angle = 0; // Inputs for the cannon angles int gInputTank2Angle = 1; int gInputLauncher = 2; // Input for launcher FSR @@ -37,8 +39,8 @@ float gLauncherFilterPole = 0.8; float gLauncherPeakValue = 0; float gLauncherPeakFilterPole = 0.999; -float gLauncherNoiseThreshold = 0.01 * MATRIX_MAX; -float gLauncherMinimumPeak = 0.1 * MATRIX_MAX; +float gLauncherNoiseThreshold = 0.01; +float gLauncherMinimumPeak = 0.1; bool gLauncherTriggered = false; // Screen update rate; affects buffer size. Actual contents of buffer @@ -61,9 +63,22 @@ // Auxiliary (low-priority) task for updating the screen AuxiliaryTask gScreenUpdateTask; +// Buffers for music and sound effects +extern float *gMusicBuffer; +extern int gMusicBufferLength; +extern float *gSoundBoomBuffer; +extern int gSoundBoomBufferLength; + +// Current state for sound and music +int gMusicBufferPointer = 0; // 0 means start of buffer... +int gSoundBoomBufferPointer = -1; // -1 means don't play... +float gSoundProjectileOscillatorPhase = 0; +float gSoundProjectileOscillatorGain = 0.2; +float gOscillatorPhaseScaler = 0; + void screen_update(); -// initialise_render() is called once before the audio rendering starts. +// setup() is called once before the audio rendering starts. // Use it to perform any initialisation and allocation which is dependent // on the period size or sample rate. // @@ -72,22 +87,22 @@ // // Return true on success; returning false halts the program. -bool initialise_render(int numMatrixChannels, int numAudioChannels, - int numMatrixFramesPerPeriod, - int numAudioFramesPerPeriod, - float matrixSampleRate, float audioSampleRate, - void *userData) +bool setup(BeagleRTContext *context, void *userData) { srandom(time(NULL)); // Verify we are running with matrix enabled - if(numMatrixFramesPerPeriod == 0 || numMatrixChannels < 4) { + if(context->analogFrames == 0 || context->analogChannels < 4) { rt_printf("Error: this example needs the matrix enabled with at least 4 channels\n"); return false; } + // Initialise audio variables + gAudioFramesPerMatrixFrame = context->audioFrames / context->analogFrames; + gOscillatorPhaseScaler = 2.0 * M_PI / context->audioSampleRate; + // Initialise the screen buffers - gScreenBufferMaxLength = 2 * matrixSampleRate / gScreenFramesPerSecond; + gScreenBufferMaxLength = 2 * context->analogSampleRate / gScreenFramesPerSecond; gScreenBuffer1 = new float[gScreenBufferMaxLength]; gScreenBuffer2 = new float[gScreenBufferMaxLength]; if(gScreenBuffer1 == 0 || gScreenBuffer2 == 0) { @@ -104,12 +119,12 @@ // Initialise the game setupGame(gScreenWidth, gScreenHeight); - gGameFrameInterval = matrixSampleRate / gGameFramesPerSecond; + gGameFrameInterval = context->analogSampleRate / gGameFramesPerSecond; gSamplesUntilNextFrame = gGameFrameInterval; // Initialise auxiliary tasks - if((gScreenUpdateTask = createAuxiliaryTaskLoop(&screen_update, 90, - "beaglert-screen-update")) == 0) + if((gScreenUpdateTask = BeagleRT_createAuxiliaryTask(&screen_update, 90, + "beaglert-screen-update")) == 0) return false; return true; @@ -140,12 +155,45 @@ // ADCs and DACs (if available). If only audio is available, numMatrixFrames // will be 0. -void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, - uint16_t *matrixIn, uint16_t *matrixOut) +void render(BeagleRTContext *context, void *userData) { - for(int n = 0; n < numMatrixFrames; n++) { + int audioIndex = 0; + + for(unsigned int n = 0; n < context->analogFrames; n++) { + for(int k = 0; k < gAudioFramesPerMatrixFrame; k++) { + // Render music and sound + float audioSample = 0; + + // Music plays in a loop + if(gMusicBuffer != 0 && gMusicBufferPointer >= 0) { + audioSample += gMusicBuffer[gMusicBufferPointer++]; + if(gMusicBufferPointer >= gMusicBufferLength) + gMusicBufferPointer = 0; + } + + // Sound effect plays until finished, then stops + if(gSoundBoomBuffer != 0 && gSoundBoomBufferPointer >= 0) { + audioSample += gSoundBoomBuffer[gSoundBoomBufferPointer++]; + if(gSoundBoomBufferPointer >= gSoundBoomBufferLength) + gSoundBoomBufferPointer = -1; + } + + // Oscillator plays to indicate projectile height + if(gameStatusProjectileInMotion()) { + audioSample += gSoundProjectileOscillatorGain * sinf(gSoundProjectileOscillatorPhase); + + gSoundProjectileOscillatorPhase += gOscillatorPhaseScaler * constrain(map(gameStatusProjectileHeight(), + 1.0, 0, 300, 2000), 200, 6000); + if(gSoundProjectileOscillatorPhase > 2.0 * M_PI) + gSoundProjectileOscillatorPhase -= 2.0 * M_PI; + } + + context->audioOut[2*audioIndex] = context->audioOut[2*audioIndex + 1] = audioSample; + audioIndex++; + } + // First-order lowpass filter to remove noise on launch FSR - float rawSample = analogRead(gInputLauncher, n); + float rawSample = analogReadFrame(context, n, gInputLauncher); float launchSample = gLauncherFilterPole * gLauncherLastSample + (1.0f - gLauncherFilterPole) * rawSample; gLauncherLastSample = launchSample; @@ -164,7 +212,7 @@ // Set both cannon strengths but only one will // fire depending on whose turn it is float strength = map(gLauncherPeakValue, - gLauncherMinimumPeak, MATRIX_MAX, + gLauncherMinimumPeak, 1.0, 0.5f, 10.0f); setTank1CannonStrength(strength); setTank2CannonStrength(strength); @@ -179,11 +227,16 @@ // Update game physics and cannon angles gSamplesUntilNextFrame = gGameFrameInterval; - setTank1CannonAngle(map(analogRead(gInputTank1Angle, n), - 0, MATRIX_MAX, M_PI, 0)); - setTank2CannonAngle(map(analogRead(gInputTank2Angle, n), - 0, MATRIX_MAX, M_PI, 0)); + setTank1CannonAngle(map(analogReadFrame(context, n, gInputTank1Angle), + 0, 1.0, M_PI, 0)); + setTank2CannonAngle(map(analogReadFrame(context, n, gInputTank2Angle), + 0, 1.0, M_PI, 0)); nextGameFrame(); + + // Check for collision and start sound accordingly + if(gameStatusCollisionOccurred()) { + gSoundBoomBufferPointer = 0; + } } if(gScreenBufferReadPointer >= gScreenBufferReadLength - 1 @@ -199,21 +252,21 @@ // Rescale screen coordinates to matrix ranges; invert the Y // coordinate to go from normal screen coordinates to scope coordinates - analogWrite(gOutputX, n, constrain(map(x, 0, gScreenWidth, 0, MATRIX_MAX), 0, MATRIX_MAX)); - analogWrite(gOutputY, n, constrain(map(y, 0, gScreenHeight, MATRIX_MAX, 0), 0, MATRIX_MAX)); + analogWriteFrameOnce(context, n, gOutputX, constrain(map(x, 0, gScreenWidth, 0, 1.0), 0, 1.0)); + analogWriteFrameOnce(context, n, gOutputY, constrain(map(y, 0, gScreenHeight, 1.0, 0), 0, 1.0)); } else { // Still not ready! Write 0 until something happens - analogWrite(gOutputX, n, 0); - analogWrite(gOutputY, n, 0); + analogWriteFrameOnce(context, n, gOutputX, 0); + analogWriteFrameOnce(context, n, gOutputY, 0); } if(gameStatusWinner() != 0) { // Blink one LED to show who won // Blink both LEDs when projectile is in motion - uint16_t val = (gSampleCounter % 4000 > 2000) ? MATRIX_MAX : 0; - analogWrite(gOutputPlayer1LED, n, gameStatusWinner() == 1 ? val : 0); - analogWrite(gOutputPlayer2LED, n, gameStatusWinner() == 2 ? val : 0); + float val = (gSampleCounter % 4000 > 2000) ? 1.0 : 0; + analogWriteFrameOnce(context, n, gOutputPlayer1LED, gameStatusWinner() == 1 ? val : 0); + analogWriteFrameOnce(context, n, gOutputPlayer2LED, gameStatusWinner() == 2 ? val : 0); // After 5 seconds, restart the game gSamplesSinceFinish++; @@ -222,24 +275,24 @@ } else if(gameStatusProjectileInMotion()) { // Blink both LEDs when projectile is in motion - uint16_t val = (gSampleCounter % 2000 > 1000) ? MATRIX_MAX : 0; - analogWrite(gOutputPlayer1LED, n, val); - analogWrite(gOutputPlayer2LED, n, val); + float val = (gSampleCounter % 2000 > 1000) ? 1.0 : 0; + analogWriteFrameOnce(context, n, gOutputPlayer1LED, val); + analogWriteFrameOnce(context, n, gOutputPlayer2LED, val); } else if(gameStatusPlayer1Turn()) { - analogWrite(gOutputPlayer1LED, n, MATRIX_MAX); - analogWrite(gOutputPlayer2LED, n, 0); + analogWriteFrameOnce(context, n, gOutputPlayer1LED, 1.0); + analogWriteFrameOnce(context, n, gOutputPlayer2LED, 0); } else { - analogWrite(gOutputPlayer2LED, n, MATRIX_MAX); - analogWrite(gOutputPlayer1LED, n, 0); + analogWriteFrameOnce(context, n, gOutputPlayer2LED, 1.0); + analogWriteFrameOnce(context, n, gOutputPlayer1LED, 0); } // Check if we have reached the point where we should next update if(gScreenBufferReadPointer >= gScreenBufferNextUpdateLocation && !gScreenNextBufferReady) { // Update the screen at lower priority than the audio thread - scheduleAuxiliaryTask(gScreenUpdateTask); + BeagleRT_scheduleAuxiliaryTask(gScreenUpdateTask); } gSampleCounter++; @@ -262,10 +315,10 @@ gScreenNextBufferReady = true; } -// cleanup_render() is called once at the end, after the audio has stopped. -// Release any resources that were allocated in initialise_render(). +// cleanup() is called once at the end, after the audio has stopped. +// Release any resources that were allocated in setup(). -void cleanup_render() +void cleanup(BeagleRTContext *context, void *userData) { // Clean up the game state cleanupGame();
--- a/pru_rtaudio.p Sun Feb 08 00:20:01 2015 +0000 +++ b/pru_rtaudio.p Fri Jul 17 15:28:18 2015 +0100 @@ -31,7 +31,8 @@ #define GPIO_CLEARDATAOUT 0x190 #define GPIO_SETDATAOUT 0x194 -#define PRU0_ARM_INTERRUPT 19 +#define PRU0_ARM_INTERRUPT 19 // Interrupt signalling we're done +#define PRU1_ARM_INTERRUPT 20 // Interrupt signalling a block is ready #define C_ADC_DAC_MEM C24 // PRU0 mem #ifdef DBOX_CAPE @@ -81,7 +82,8 @@ #define COMM_FRAME_COUNT 32 // How many frames have elapse since beginning #define COMM_USE_SPI 36 // Whether or not to use SPI ADC and DAC #define COMM_NUM_CHANNELS 40 // Low 2 bits indicate 8 [0x3], 4 [0x1] or 2 [0x0] channels - +#define COMM_USE_DIGITAL 44 // Whether or not to use DIGITAL + #define MCASP0_BASE 0x48038000 #define MCASP1_BASE 0x4803C000 @@ -180,10 +182,15 @@ #define FLAG_BIT_BUFFER1 0 #define FLAG_BIT_USE_SPI 1 #define FLAG_BIT_MCASP_HWORD 2 // Whether we are on the high word for McASP transmission - +#define FLAG_BIT_USE_DIGITAL 3 // Registers used throughout // r1, r2, r3 are used for temporary storage +#define MEM_DIGITAL_BASE 0x11000 //Base address for DIGITAL : Shared RAM + 0x400 +#define MEM_DIGITAL_BUFFER1_OFFSET 0x400 //Start pointer to DIGITAL_BUFFER1, which is 256 words after. +// 256 is the maximum number of frames allowed + +#define reg_digital_current r6 // Pointer to current storage location of DIGITAL #define reg_num_channels r9 // Number of SPI ADC/DAC channels to use #define reg_frame_current r10 // Current frame count in SPI ADC/DAC transfer #define reg_frame_total r11 // Total frame count for SPI ADC/DAC @@ -205,182 +212,182 @@ // r27, r28 used in macros #define reg_mcasp_addr r29 // Base address for McASP -// Convert float to 16-bit int, multiplying by 32768 -// Converts -1.0 to 1.0 to a full 16-bit range -// input and output can safely be the same register -.macro FLOAT_TO_INT16 -.mparam input, output - // int exponent = ((input >> 23) & 0xFF) - LSR r27, input, 23 // exponent goes in r27 - AND r27, r27, 0xFF +//0 P8_07 36 0x890/090 66 gpio2[2] +//1 P8_08 37 0x894/094 67 gpio2[3] +//2 P8_09 39 0x89c/09c 69 gpio2[5] +//3 P8_10 38 0x898/098 68 gpio2[4] +//4 P8_11 13 0x834/034 45 gpio1[13] +//5 P8_12 12 0x830/030 44 gpio1[12] +//6 P9_12 30 0x878/078 60 gpio1[28] +//7 P9_14 18 0x848/048 50 gpio1[18] +//8 P8_15 15 0x83c/03c 47 gpio1[15] +//9 P8_16 14 0x838/038 46 gpio1[14] +//10 P9_16 19 0x84c/04c 51 gpio1[19] +//11 P8_18 35 0x88c/08c 65 gpio2[1] +//12 P8_27 56 0x8e0/0e0 86 gpio2[22] +//13 P8_28 58 0x8e8/0e8 88 gpio2[24] +//14 P8_29 57 0x8e4/0e4 87 gpio2[23] +//15 P8_30 59 0x8ec/0ec 89 gpio2[25] - // Actual exponent is 127 less than the above; below -15 we - // should return 0. So check if it is less than 112. - QBLE EXPONENT_GREQ_MINUS15, r27, 112 - LDI output, 0 - QBA FLOAT_TO_INT16_DONE -EXPONENT_GREQ_MINUS15: +//generic GPIOs constants +//#define GPIO1 0x4804c000 +#define GPIO2 0x481ac000 +//#define GPIO_CLEARDATAOUT 0x190 //SETDATAOUT is CLEARDATAOUT+4 +#define GPIO_OE 0x134 +#define GPIO_DATAIN 0x138 - // Next check if exponent is greater than or equal to 0 (i.e. - // 127 in our adjusted version. If so we return the max. - QBGT EXPONENT_LT_ZERO, r27, 127 - QBBS NEGATIVE_MAX, input, 31 // Is sign negative? - LDI output, 32767 // Max positive value - QBA FLOAT_TO_INT16_DONE -NEGATIVE_MAX: - LDI output, 32768 // Actually will be -32768 in signed - QBA FLOAT_TO_INT16_DONE -EXPONENT_LT_ZERO: - - // Mask out the mantissa and shift - // int mantissa = (input & 0x7FFFFF) | (1 << 23) - MOV r28, 0x007FFFFF - AND r28, r28, input - SET r28, 23 - - // Shift right by -(exponent - 127 - 8) to produce an int - // after effectively multiplying by 2^15 - // ---> (135 - exponent) - RSB r27, r27, 135 - LSR r28, r28, r27 - - // Finally, check the sign bit and invert if needed - QBBS NEGATIVE_RESULT, input, 31 - // Positive result: but might be 32768 so needs checking - LDI r27, 0x7FFF - MIN output, r27, r28 - QBA FLOAT_TO_INT16_DONE -NEGATIVE_RESULT: - // Take negative: invert the bits and add 1 - LDI r27, 0xFFFF - XOR r28, r28, r27 - ADD r28, r28, 1 - CLR output, r28, 16 // Clear carry bit if present -FLOAT_TO_INT16_DONE: +.macro READ_GPIO_BITS +.mparam gpio_data, gpio_num_bit, digital_bit, digital + QBBC DONE, digital, digital_bit //if the pin is set as an output, nothing to do here + QBBC CLEAR, gpio_data, gpio_num_bit + SET digital, digital_bit+16 + QBA DONE + CLEAR: + CLR digital, digital_bit+16 + QBA DONE + DONE: .endm - -// Convert float to 16-bit unsigned int, multiplying by 65536 -// Converts 0.0 to 1.0 to a full 16-bit range -// input and output can safely be the same register -.macro FLOAT_TO_UINT16 -.mparam input, output - QBBC NONNEGATIVE, input, 31 // Is sign negative? - LDI output, 0 // All < 0 inputs produce 0 output - QBA FLOAT_TO_UINT16_DONE -NONNEGATIVE: - // int exponent = ((input >> 23) & 0xFF) - LSR r27, input, 23 // exponent goes in r27 - AND r27, r27, 0xFF - - // Actual exponent is 127 less than the above; below -16 we - // should return 0. So check if it is less than 111. - QBLE EXPONENT_GREQ_MINUS16, r27, 111 - LDI output, 0 - QBA FLOAT_TO_UINT16_DONE -EXPONENT_GREQ_MINUS16: - - // Next check if exponent is greater than or equal to 0 (i.e. - // 127 in our adjusted version. If so we return the max. - QBGT EXPONENT_LT_ZERO, r27, 127 - LDI output, 65535 // Max positive value - QBA FLOAT_TO_UINT16_DONE -EXPONENT_LT_ZERO: - - // Mask out the mantissa and shift - // int mantissa = (input & 0x7FFFFF) | (1 << 23) - MOV r28, 0x007FFFFF - AND r28, r28, input - SET r28, 23 - - // Shift right by -(exponent - 127 - 7) to produce an int - // after effectively multiplying by 2^16 - // ---> (134 - exponent) - RSB r27, r27, 134 - LSR r28, r28, r27 - - // Check for 65536 and clip at 65535 - LDI r27, 0xFFFF - MIN output, r27, r28 -FLOAT_TO_UINT16_DONE: +.macro SET_GPIO_BITS +.mparam gpio_oe, gpio_setdataout, gpio_cleardataout, gpio_num_bit, digital_bit, digital //sets the bits in GPIO_OE, GPIO_SETDATAOUT and GPIO_CLEARDATAOUT +//Remember that the GPIO_OE Output data enable register behaves as follows for each bit: +//0 = The corresponding GPIO pin is configured as an output. +//1 = The corresponding GPIO pin is configured as an input. + QBBS SETINPUT, digital, digital_bit + CLR gpio_oe, gpio_num_bit //if it is an output, configure pin as output + QBBC CLEARDATAOUT, digital, digital_bit+16 // check the output value. If it is 0, branch + SET gpio_setdataout, gpio_num_bit //if it is 1, set output to high + QBA DONE +CLEARDATAOUT: + SET gpio_cleardataout, gpio_num_bit // set output to low + QBA DONE +SETINPUT: //if it is an input, set the relevant bit + SET gpio_oe, gpio_num_bit + QBA DONE +DONE: .endm - -// Convert a 16-bit int to float. This macro assumes that the upper -// 16 bits of input are 0 and may behave strangely if this is not the case. -// input and output must be different registers -.macro INT16_TO_FLOAT -.mparam input, output - // Check edge cases first: 0 and -32768 (= 32768 in unsigned) - QBNE INPUT_NOT_ZERO, input, 0 - LDI output, 0 - QBA INT16_TO_FLOAT_DONE -INPUT_NOT_ZERO: - LDI r28, 32768 - QBNE INPUT_NOT_MIN, input, r28 - MOV output, 0xBF800000 // -1.0 - QBA INT16_TO_FLOAT_DONE -INPUT_NOT_MIN: - // Check for negative values = values with bit 15 set - MOV output, input - QBBC NEGATIVE_DONE, output, 15 - LDI r28, 0xFFFF - XOR output, output, r28 - ADD output, output, 1 - CLR output, 16 // Clear any carry bit -NEGATIVE_DONE: - // Now we need to find the highest bit that is 1 in order to determine - // the exponent - LMBD r28, output, 1 +QBA START // when first starting, go to START, skipping this section. - // Calculate exponent field: 127 + 8 + (r28 - 23) = 112 + r28 - ADD r27, r28, 112 - - // Take 23 minus the result to get the shift - RSB r28, r28, 23 - LSL output, output, r28 +DIGITAL: +//IMPORTANT: do NOT use r28 in this macro, as it contains the return address for JAL +//r27 is now the input word passed in render(), one word per frame +//[31:16]: data(1=high, 0=low), [15:0]: direction (0=output, 1=input) ) - // Now clear bit 23 (implicitly 1) and replace it with the exponent - CLR output, output, 23 - LSL r27, r27, 23 - OR output, output, r27 - - // Put the sign bit back in place - QBBC INT16_TO_FLOAT_DONE, input, 15 - SET output, 31 -INT16_TO_FLOAT_DONE: -.endm -// Convert a 16-bit unsigned int to float. -.macro UINT16_TO_FLOAT -.mparam input, output - MOV output, input - - // Clear upper 16 bits - LDI r27, 0xFFFF - AND output, output, r27 +//Preparing the gpio_oe, gpio_cleardataout and gpio_setdataout for each module +//r2 will hold GPIO1_OE +//load current status of GPIO_OE in r2 + MOV r2, GPIO1 | GPIO_OE + //it takes 190ns to go through the next instruction + LBBO r2, r2, 0, 4 +//GPIO1-start +//process oe and datain and prepare dataout for GPIO1 +//r7 will contain GPIO1_CLEARDATAOUT +//r8 will contain GPIO1_SETDATAOUT + MOV r8, 0 + MOV r7, 0 +//map GPIO_ANALOG to gpio1 pins, +//r2 is gpio1_oe, r8 is gpio1_setdataout, r7 is gpio1_cleardataout, r27 is the input word +//the following operations will read from r27 and update r2,r7,r8 + SET_GPIO_BITS r2, r8, r7, 13, 4, r27 + SET_GPIO_BITS r2, r8, r7, 12, 5, r27 + SET_GPIO_BITS r2, r8, r7, 28, 6, r27 + SET_GPIO_BITS r2, r8, r7, 18, 7, r27 + SET_GPIO_BITS r2, r8, r7, 15, 8, r27 + SET_GPIO_BITS r2, r8, r7, 14, 9, r27 + SET_GPIO_BITS r2, r8, r7, 19, 10, r27 +//set the output enable register for gpio1. + MOV r3, GPIO1 | GPIO_OE //use r3 as a temp register + SBBO r2, r3, 0, 4 //takes two cycles (10ns) +//GPIO1-end +// r2 is now unused - // If zero, we're done - QBEQ UINT16_TO_FLOAT_DONE, output, 0 - - // Now we need to find the highest bit that is 1 in order to determine - // the exponent - LMBD r28, output, 1 +//GPIO2-start +//r3 will hold GPIO1_OE +//load current status of GPIO_OE in r3 + MOV r3, GPIO2 | GPIO_OE +//it takes 200ns to go through the next instructions + LBBO r3, r3, 0, 4 +//process oe and datain and prepare dataout for GPIO2 +//r4 will contain GPIO2_CLEARDATAOUT +//r5 will contain GPIO2_SETDATAOUT + MOV r5, 0 + MOV r4, 0 +//map GPIO_ANALOG to gpio2 pins +//r3 is gpio2_oe, r5 is gpio2_setdataout, r4 is gpio2_cleardataout, r27 is the input word +//the following operations will read from r27 and update r3,r4,r5 + SET_GPIO_BITS r3, r5, r4, 2, 0, r27 + SET_GPIO_BITS r3, r5, r4, 3, 1, r27 + SET_GPIO_BITS r3, r5, r4, 5, 2, r27 + SET_GPIO_BITS r3, r5, r4, 4, 3, r27 + SET_GPIO_BITS r3, r5, r4, 1, 11, r27 + SET_GPIO_BITS r3, r5, r4, 22, 12, r27 + SET_GPIO_BITS r3, r5, r4, 24, 13, r27 + SET_GPIO_BITS r3, r5, r4, 23, 14, r27 + SET_GPIO_BITS r3, r5, r4, 25, 15, r27 +//set the output enable register for gpio2. + MOV r2, GPIO2 | GPIO_OE //use r2 as a temp registerp + SBBO r3, r2, 0, 4 //takes two cycles (10ns) +//GPIO2-end +//r3 is now unused - // Calculate exponent field: 127 + 7 + (r28 - 23) = 111 + r28 - ADD r27, r28, 111 - - // Take 23 minus the result to get the shift - RSB r28, r28, 23 - LSL output, output, r28 +//load current inputs in r2, r3 +//r2 will contain GPIO1_DATAIN +//r3 will contain GPIO2_DATAIN +//load the memory locations + MOV r2, GPIO1 | GPIO_DATAIN + MOV r3, GPIO2 | GPIO_DATAIN + //takes 375 nns to go through the next two instructions +//read the datain + LBBO r2, r2, 0, 4 + LBBO r3, r3, 0, 4 +//now read from r2 and r3 only the channels that are set as input in the lower word of r27 +// and set their value in the high word of r27 +//GPIO1 + READ_GPIO_BITS r2, 13, 4, r27 + READ_GPIO_BITS r2, 12, 5, r27 + READ_GPIO_BITS r2, 28, 6, r27 + READ_GPIO_BITS r2, 18, 7, r27 + READ_GPIO_BITS r2, 15, 8, r27 + READ_GPIO_BITS r2, 14, 9, r27 + READ_GPIO_BITS r2, 19, 10, r27 +//GPIO2 + READ_GPIO_BITS r3, 2, 0, r27 + READ_GPIO_BITS r3, 3, 1, r27 + READ_GPIO_BITS r3, 5, 2, r27 + READ_GPIO_BITS r3, 4, 3, r27 + READ_GPIO_BITS r3, 1, 11, r27 + READ_GPIO_BITS r3, 22, 12, r27 + READ_GPIO_BITS r3, 24, 13, r27 + READ_GPIO_BITS r3, 23, 14, r27 + READ_GPIO_BITS r3, 25, 15, r27 +//r2, r3 are now unused - // Now clear bit 23 (implicitly 1) and replace it with the exponent - CLR output, output, 23 - LSL r27, r27, 23 - OR output, output, r27 -UINT16_TO_FLOAT_DONE: +//now all the setdataout and cleardataout are ready to be written to the GPIO register. +//CLEARDATAOUT and SETDATAOUT are consecutive positions in memory, so we just write 8 bytes to CLEARDATAOUT. +//We can do this because we chose cleardata and setdata registers for a given GPIO to be consecutive +//load the memory addresses to be written to + MOV r2, GPIO1 | GPIO_CLEARDATAOUT //use r2 as a temp register + MOV r3, GPIO2 | GPIO_CLEARDATAOUT //use r3 as a temp register +//write 8 bytes for each GPIO +//takes 30ns in total to go through the following two instructions + SBBO r7, r2, 0, 8 //store r7 and r8 in GPIO1_CLEARDATAOUT and GPIO1_SETDATAOUT + //takes 145ns to be effective when going low, 185ns when going high + SBBO r4, r3, 0, 8 //store r4 and r5 in GPIO2_CLEARDATAOUT and GPIO2_SETDATAOUT + //takes 95ns to be effective when going low, 130ns when going high +//reversing the order of the two lines above will swap the performances between the GPIO modules +//i.e.: the first line will always take 145ns/185ns and the second one will always take 95ns/130ns, +//regardless of whether the order is gpio1-gpio2 or gpio2-gpio1 +JMP r28.w0 // go back to ADC_WRITE_AND_PROCESS_GPIO + +.macro HANG //useful for debugging +DALOOP: +set r30.t14 +clr r30.t14 +QBA DALOOP .endm - + // Bring CS line low to write to DAC .macro DAC_CS_ASSERT MOV r27, DAC_CS_PIN @@ -466,6 +473,30 @@ ADC_CS_UNASSERT .endm +// Complete ADC write+read with chip select and also performs IO for digital +.macro ADC_WRITE_GPIO +.mparam in, out, do_gpio + ADC_CS_ASSERT + ADC_TX in + QBBC GPIO_DONE, reg_flags, FLAG_BIT_USE_DIGITAL //skip if DIGITAL is disabled + AND r27, do_gpio, 0x3 // only do a DIGITAL every 2 SPI I/O + QBNE GPIO_DONE, r27, 0 +//from here to GPIO_DONE takes 1.8us, while usually ADC_WAIT_FOR_FINISH only waits for 1.14us. +//TODO: it would be better to split the DIGITAL stuff in two parts: +//- one taking place during DAC_WRITE which sets the GPIO_OE +//- and the other during ADC_WRITE which actually reads DATAIN and writes CLEAR/SET DATAOUT + //r27 is actually r27, so do not use r27 from here to ... + LBBO r27, reg_digital_current, 0, 4 + JAL r28.w0, DIGITAL // note that this is not called as a macro, but with JAL. r28 will contain the return address + SBBO r27, reg_digital_current, 0, 4 + //..here you can start using r27 again + ADD reg_digital_current, reg_digital_current, 4 //increment pointer +GPIO_DONE: + ADC_WAIT_FOR_FINISH + ADC_RX out + ADC_CS_UNASSERT +.endm + // Write a McASP register .macro MCASP_REG_WRITE .mparam reg, value @@ -537,11 +568,27 @@ // Default number of channels in case SPI disabled LDI reg_num_channels, 8 + // Find out whether we should use DIGITAL + LBBO r2, reg_comm_addr, COMM_USE_DIGITAL, 4 + QBEQ DIGITAL_INIT_DONE, r2, 0 // if we use digital + SET reg_flags, reg_flags, FLAG_BIT_USE_DIGITAL +/* This block of code is not really needed, as the memory is initialized by ARM before the PRU is started. +Will leave it here for future reference +DIGITAL_INIT: //set the digital buffer to 0x0000ffff (all inputs), to prevent unwanted high outputs + //the loop is unrolled by a factor of four just to take advantage of the speed of SBBO on larger byte bursts, but there is no real need for it + MOV r2, 0x0000ffff //value to store. 0x0000ffff means all inputs + MOV r3, MEM_DIGITAL_BASE //start of the digital buffer + MOV r4, MEM_DIGITAL_BASE+2*MEM_DIGITAL_BUFFER1_OFFSET //end of the digital buffer +DIGITAL_INIT_BUFFER_LOOP: + SBBO r2, r3, 0, 4 + ADD r3, r3, 4 //increment pointer + QBGT DIGITAL_INIT_BUFFER_LOOP, r3, r4 //loop until we reach the end of the buffer +*/ +DIGITAL_INIT_DONE: // Find out whether we should use SPI ADC and DAC LBBO r2, reg_comm_addr, COMM_USE_SPI, 4 QBEQ SPI_FLAG_CHECK_DONE, r2, 0 SET reg_flags, reg_flags, FLAG_BIT_USE_SPI - SPI_FLAG_CHECK_DONE: // If we don't use SPI, then skip all this init QBBC SPI_INIT_DONE, reg_flags, FLAG_BIT_USE_SPI @@ -614,45 +661,45 @@ ADC_WRITE r2, r2 SPI_INIT_DONE: - // Prepare McASP0 for audio - MCASP_REG_WRITE MCASP_GBLCTL, 0 // Disable McASP - MCASP_REG_WRITE_EXT MCASP_SRCTL0, 0 // All serialisers off - MCASP_REG_WRITE_EXT MCASP_SRCTL1, 0 - MCASP_REG_WRITE_EXT MCASP_SRCTL2, 0 - MCASP_REG_WRITE_EXT MCASP_SRCTL3, 0 - MCASP_REG_WRITE_EXT MCASP_SRCTL4, 0 - MCASP_REG_WRITE_EXT MCASP_SRCTL5, 0 +// Prepare McASP0 for audio +MCASP_REG_WRITE MCASP_GBLCTL, 0 // Disable McASP +MCASP_REG_WRITE_EXT MCASP_SRCTL0, 0 // All serialisers off +MCASP_REG_WRITE_EXT MCASP_SRCTL1, 0 +MCASP_REG_WRITE_EXT MCASP_SRCTL2, 0 +MCASP_REG_WRITE_EXT MCASP_SRCTL3, 0 +MCASP_REG_WRITE_EXT MCASP_SRCTL4, 0 +MCASP_REG_WRITE_EXT MCASP_SRCTL5, 0 - MCASP_REG_WRITE MCASP_PWRIDLESYSCONFIG, 0x02 // Power on - MCASP_REG_WRITE MCASP_PFUNC, 0x00 // All pins are McASP - MCASP_REG_WRITE MCASP_PDIR, MCASP_OUTPUT_PINS // Set pin direction - MCASP_REG_WRITE MCASP_DLBCTL, 0x00 - MCASP_REG_WRITE MCASP_DITCTL, 0x00 - MCASP_REG_WRITE MCASP_RMASK, MCASP_DATA_MASK // 16 bit data receive - MCASP_REG_WRITE MCASP_RFMT, MCASP_DATA_FORMAT // Set data format - MCASP_REG_WRITE MCASP_AFSRCTL, 0x100 // I2S mode - MCASP_REG_WRITE MCASP_ACLKRCTL, 0x80 // Sample on rising edge - MCASP_REG_WRITE MCASP_AHCLKRCTL, 0x8001 // Internal clock, not inv, /2; irrelevant? - MCASP_REG_WRITE MCASP_RTDM, 0x03 // Enable TDM slots 0 and 1 - MCASP_REG_WRITE MCASP_RINTCTL, 0x00 // No interrupts - MCASP_REG_WRITE MCASP_XMASK, MCASP_DATA_MASK // 16 bit data transmit - MCASP_REG_WRITE MCASP_XFMT, MCASP_DATA_FORMAT // Set data format - MCASP_REG_WRITE MCASP_AFSXCTL, 0x100 // I2S mode - MCASP_REG_WRITE MCASP_ACLKXCTL, 0x00 // Transmit on rising edge, sync. xmit and recv - MCASP_REG_WRITE MCASP_AHCLKXCTL, 0x8001 // External clock from AHCLKX - MCASP_REG_WRITE MCASP_XTDM, 0x03 // Enable TDM slots 0 and 1 - MCASP_REG_WRITE MCASP_XINTCTL, 0x00 // No interrupts +MCASP_REG_WRITE MCASP_PWRIDLESYSCONFIG, 0x02 // Power on +MCASP_REG_WRITE MCASP_PFUNC, 0x00 // All pins are McASP +MCASP_REG_WRITE MCASP_PDIR, MCASP_OUTPUT_PINS // Set pin direction +MCASP_REG_WRITE MCASP_DLBCTL, 0x00 +MCASP_REG_WRITE MCASP_DITCTL, 0x00 +MCASP_REG_WRITE MCASP_RMASK, MCASP_DATA_MASK // 16 bit data receive +MCASP_REG_WRITE MCASP_RFMT, MCASP_DATA_FORMAT // Set data format +MCASP_REG_WRITE MCASP_AFSRCTL, 0x100 // I2S mode +MCASP_REG_WRITE MCASP_ACLKRCTL, 0x80 // Sample on rising edge +MCASP_REG_WRITE MCASP_AHCLKRCTL, 0x8001 // Internal clock, not inv, /2; irrelevant? +MCASP_REG_WRITE MCASP_RTDM, 0x03 // Enable TDM slots 0 and 1 +MCASP_REG_WRITE MCASP_RINTCTL, 0x00 // No interrupts +MCASP_REG_WRITE MCASP_XMASK, MCASP_DATA_MASK // 16 bit data transmit +MCASP_REG_WRITE MCASP_XFMT, MCASP_DATA_FORMAT // Set data format +MCASP_REG_WRITE MCASP_AFSXCTL, 0x100 // I2S mode +MCASP_REG_WRITE MCASP_ACLKXCTL, 0x00 // Transmit on rising edge, sync. xmit and recv +MCASP_REG_WRITE MCASP_AHCLKXCTL, 0x8001 // External clock from AHCLKX +MCASP_REG_WRITE MCASP_XTDM, 0x03 // Enable TDM slots 0 and 1 +MCASP_REG_WRITE MCASP_XINTCTL, 0x00 // No interrupts - MCASP_REG_WRITE_EXT MCASP_SRCTL_R, 0x02 // Set up receive serialiser - MCASP_REG_WRITE_EXT MCASP_SRCTL_X, 0x01 // Set up transmit serialiser - MCASP_REG_WRITE_EXT MCASP_WFIFOCTL, 0x00 // Disable FIFOs - MCASP_REG_WRITE_EXT MCASP_RFIFOCTL, 0x00 +MCASP_REG_WRITE_EXT MCASP_SRCTL_R, 0x02 // Set up receive serialiser +MCASP_REG_WRITE_EXT MCASP_SRCTL_X, 0x01 // Set up transmit serialiser +MCASP_REG_WRITE_EXT MCASP_WFIFOCTL, 0x00 // Disable FIFOs +MCASP_REG_WRITE_EXT MCASP_RFIFOCTL, 0x00 - MCASP_REG_WRITE MCASP_XSTAT, 0xFF // Clear transmit errors - MCASP_REG_WRITE MCASP_RSTAT, 0xFF // Clear receive errors +MCASP_REG_WRITE MCASP_XSTAT, 0xFF // Clear transmit errors +MCASP_REG_WRITE MCASP_RSTAT, 0xFF // Clear receive errors - MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 1) // Set RHCLKRST - MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 9) // Set XHCLKRST +MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 1) // Set RHCLKRST +MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 9) // Set XHCLKRST // The above write sequence will have temporarily changed the AHCLKX frequency // The PLL needs time to settle or the sample rate will be unstable and possibly @@ -663,7 +710,7 @@ MOV r3, GPIO1 + GPIO_SETDATAOUT SBBO r2, r3, 0, 4 - MOV r2, 100000 +MOV r2, 100000 MCASP_INIT_WAIT: SUB r2, r2, 1 QBNE MCASP_INIT_WAIT, r2, 0 @@ -672,30 +719,62 @@ MOV r3, GPIO1 + GPIO_CLEARDATAOUT SBBO r2, r3, 0, 4 - MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 0) // Set RCLKRST - MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 8) // Set XCLKRST - MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 2) // Set RSRCLR - MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 10) // Set XSRCLR - MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 3) // Set RSMRST - MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 11) // Set XSMRST +MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 0) // Set RCLKRST +MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 8) // Set XCLKRST +MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 2) // Set RSRCLR +MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 10) // Set XSRCLR +MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 3) // Set RSMRST +MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 11) // Set XSMRST - MCASP_REG_WRITE_EXT MCASP_XBUF, 0x00 // Write to the transmit buffer to prevent underflow +MCASP_REG_WRITE_EXT MCASP_XBUF, 0x00 // Write to the transmit buffer to prevent underflow - MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 4) // Set RFRST - MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 12) // Set XFRST +MCASP_REG_SET_BIT_AND_POLL MCASP_RGBLCTL, (1 << 4) // Set RFRST +MCASP_REG_SET_BIT_AND_POLL MCASP_XGBLCTL, (1 << 12) // Set XFRST // Initialisation - LBBO reg_frame_total, reg_comm_addr, COMM_BUFFER_FRAMES, 4 // Total frame count (SPI; 0.5x-2x for McASP) - MOV reg_dac_buf0, 0 // DAC buffer 0 start pointer - LSL reg_dac_buf1, reg_frame_total, 1 // DAC buffer 1 start pointer = N[ch]*2[bytes]*bufsize - LMBD r2, reg_num_channels, 1 // Returns 1, 2 or 3 depending on the number of channels - LSL reg_dac_buf1, reg_dac_buf1, r2 // Multiply by 2, 4 or 8 to get the N[ch] scaling above - MOV reg_mcasp_buf0, 0 // McASP DAC buffer 0 start pointer - LSL reg_mcasp_buf1, reg_frame_total, r2 // McASP DAC buffer 1 start pointer = 2[ch]*2[bytes]*(N/4)[samples/spi]*bufsize - CLR reg_flags, reg_flags, FLAG_BIT_BUFFER1 // Bit 0 holds which buffer we are on - MOV r2, 0 - SBBO r2, reg_comm_addr, COMM_FRAME_COUNT, 4 // Start with frame count of 0 - + LBBO reg_frame_total, reg_comm_addr, COMM_BUFFER_FRAMES, 4 // Total frame count (SPI; 0.5x-2x for McASP) + MOV reg_dac_buf0, 0 // DAC buffer 0 start pointer + LSL reg_dac_buf1, reg_frame_total, 1 // DAC buffer 1 start pointer = N[ch]*2[bytes]*bufsize + LMBD r2, reg_num_channels, 1 // Returns 1, 2 or 3 depending on the number of channels + LSL reg_dac_buf1, reg_dac_buf1, r2 // Multiply by 2, 4 or 8 to get the N[ch] scaling above + MOV reg_mcasp_buf0, 0 // McASP DAC buffer 0 start pointer + LSL reg_mcasp_buf1, reg_frame_total, r2 // McASP DAC buffer 1 start pointer = 2[ch]*2[bytes]*(N/4)[samples/spi]*bufsize + CLR reg_flags, reg_flags, FLAG_BIT_BUFFER1 // Bit 0 holds which buffer we are on + MOV r2, 0 + SBBO r2, reg_comm_addr, COMM_FRAME_COUNT, 4 // Start with frame count of 0 +/* This block of code is not really needed, as the memory is initialized by ARM before the PRU is started. +Will leave it here for future reference +//Initialise all SPI and audio buffers (DAC0, DAC1, ADC0, ADC1) to zero. +//This is useful for analog outs so they do not have spikes during the first buffer. +//This is not very useful for audio, as you still hear the initial "tumpf" when the converter starts +//and each sample in the DAC buffer is reset to 0 after it is written to the DAC. + + QBBC SPI_INIT_BUFFER_DONE, reg_flags, FLAG_BIT_USE_SPI +//Initialize SPI buffers +//compute the memory offset of the end of the audio buffer and store it in r4 + SUB r4, reg_dac_buf1, reg_dac_buf0 // length of the buffer, assumes reg_dac_buf1>ref_dac_buf0 + LSL r4, r4, 2 //length of four buffers (DAC0, DAC1, ADC0, ADC1) + ADD r4, reg_dac_buf0, r4 //total offset + MOV r2, 0// value to store + MOV r3, 0 // offset counter +SPI_INIT_BUFFER_LOOP: + SBCO r2, C_ADC_DAC_MEM, r3, 4 + ADD r3, r3, 4 + QBGT SPI_INIT_BUFFER_LOOP, r3, r4 +SPI_INIT_BUFFER_DONE: + +//Initialize audio buffers +//compute the memory offset of the end of the audio buffer and store it in r4 + SUB r4, reg_mcasp_buf1, reg_mcasp_buf0 // length of the buffer, assumes reg_mcasp_buf1>ref_mcasp_buf0 + LSL r4, r4, 2 //length of four buffers (DAC0, DAC1, ADC0, ADC1) + ADD r4, reg_mcasp_buf0, r4 //total offset + MOV r2, 0 // value to store + MOV r3, 0 // offset counter + MCASP_INIT_BUFFER_LOOP: + SBCO r2, C_MCASP_MEM, r3, 4 + ADD r3, r3, 4 + QBGT MCASP_INIT_BUFFER_LOOP, r3, r4 +*/ // Here we are out of sync by one TDM slot since the 0 word transmitted above will have occupied // the first output slot. Send one more word before jumping into the loop. MCASP_DAC_WAIT_BEFORE_LOOP: @@ -714,6 +793,7 @@ MCASP_REG_READ_EXT MCASP_RBUF, r2 WRITE_ONE_BUFFER: + // Write a single buffer of DAC samples and read a buffer of ADC samples // Load starting positions MOV reg_dac_current, reg_dac_buf0 // DAC: reg_dac_current is current pointer @@ -726,7 +806,14 @@ LSL reg_mcasp_adc_current, reg_mcasp_adc_current, 1 ADC reg_mcasp_adc_current, reg_mcasp_adc_current, reg_mcasp_dac_current MOV reg_frame_current, 0 - + QBBS DIGITAL_BASE_CHECK_SET, reg_flags, FLAG_BIT_BUFFER1 //check which buffer we are using for DIGITAL + // if we are here, we are using buffer0 + MOV reg_digital_current, MEM_DIGITAL_BASE + QBA DIGITAL_BASE_CHECK_DONE +DIGITAL_BASE_CHECK_SET: //if we are here, we are using buffer1 + MOV reg_digital_current, MEM_DIGITAL_BASE+MEM_DIGITAL_BUFFER1_OFFSET //so adjust offset appropriately +DIGITAL_BASE_CHECK_DONE: + WRITE_LOOP: // Write N channels to DAC from successive values in memory // At the same time, read N channels from ADC @@ -805,7 +892,7 @@ ADD reg_mcasp_adc_current, reg_mcasp_adc_current, 4 MCASP_ADC_DONE: QBBC SPI_SKIP_WRITE, reg_flags, FLAG_BIT_USE_SPI - + // DAC: transmit low word (first in little endian) MOV r2, 0xFFFF AND r7, reg_dac_data, r2 @@ -826,7 +913,9 @@ LSL r8, r8, AD7699_CHANNEL_OFFSET MOV r7, AD7699_CFG_MASK OR r7, r7, r8 - ADC_WRITE r7, r7 + +//ssssssssssssssssssssssssssss + ADC_WRITE_GPIO r7, r7, r1 // Mask out only the relevant 16 bits and store in reg_adc_data MOV r2, 0xFFFF @@ -872,7 +961,6 @@ ADD r1, r1, 1 QBNE ADC_DAC_LOOP, r1, reg_num_channels QBA ADC_DAC_LOOP_DONE - SPI_SKIP_WRITE: // We get here only if the SPI ADC and DAC are disabled // Just keep the loop going for McASP @@ -898,12 +986,13 @@ MOV r2, reg_mcasp_buf0 MOV reg_mcasp_buf0, reg_mcasp_buf1 MOV reg_mcasp_buf1, r2 + XOR reg_flags, reg_flags, (1 << FLAG_BIT_BUFFER1) //flip the buffer flag // Notify ARM of buffer swap - XOR reg_flags, reg_flags, (1 << FLAG_BIT_BUFFER1) AND r2, reg_flags, (1 << FLAG_BIT_BUFFER1) // Mask out every but low bit SBBO r2, reg_comm_addr, COMM_CURRENT_BUFFER, 4 - + MOV R31.b0, PRU1_ARM_INTERRUPT + 16 // Interrupt to host loop + // Increment the frame count in the comm buffer (for status monitoring) LBBO r2, reg_comm_addr, COMM_FRAME_COUNT, 4 ADD r2, r2, reg_frame_total @@ -926,18 +1015,6 @@ ADD r3, r3, r1 // Address for GPIO clear register SBBO r2, r3, 0, 4 // Clear GPIO pin LED_BLINK_DONE: - - QBBC TESTLOW, reg_flags, FLAG_BIT_BUFFER1 - MOV r2, 1 << 28 - MOV r3, GPIO1 + GPIO_SETDATAOUT - SBBO r2, r3, 0, 4 - QBA TESTDONE -TESTLOW: - MOV r2, 1 << 28 - MOV r3, GPIO1 + GPIO_CLEARDATAOUT - SBBO r2, r3, 0, 4 -TESTDONE: - // Check if we should finish: flag is zero as long as it should run LBBO r2, reg_comm_addr, COMM_SHOULD_STOP, 4 QBEQ WRITE_ONE_BUFFER, r2, 0 @@ -959,7 +1036,6 @@ CLR r2, r2, 1 SBBO r2, r3, 0, 4 SPI_CLEANUP_DONE: - // Signal the ARM that we have finished MOV R31.b0, PRU0_ARM_INTERRUPT + 16 - HALT \ No newline at end of file + HALT
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/resources/network/network_readme.txt Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,24 @@ +Three simple c scripts can be used to test the network, in conjunction with the basic_network project: +udp-client.c, udp-client-sweep.c,d udp-server.c +compile them with gcc -o udp-client udp-client.c and similar +They can be compiled and run from either the host or the bbb + +usage +./udp-client 192.168.7.2 9998 #sends individual messages to the bbb on port 9998 +#enter desired values for frequency (and phase). +123.0;0; + +The parser is currently very stupid, so the format of the message has to be:: +frequencyValue;phaseValue; +example: +700.0;0.1; + +./udp-client-sweep 192.168.7.2 9998 +sends messages every 1ms to control the frequency of the oscillator, thus generating a sine sweep + +./udp-server 9999 +#will print the info received from BeagleRT with the following format +printf("%8d;%.3f;%.3;",gCounter,gFrequency,gPhase); +example: +88201;700.000;0.123; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/resources/network/udp-client-sweep.c Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,59 @@ +/* UDP client in the internet domain */ +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +void error(const char *); +int main(int argc, char *argv[]) +{ + int sock, n; + unsigned int length; + struct sockaddr_in server, from; + struct hostent *hp; + char buffer[256]; + + if (argc != 3) { printf("Usage: server port\n"); + exit(1); + } + + server.sin_family = AF_INET; + hp = gethostbyname(argv[1]); + if (hp==0) error("Unknown host"); + + bcopy((char *)hp->h_addr, + (char *)&server.sin_addr, + hp->h_length); + server.sin_port = htons(atoi(argv[2])); + length=sizeof(struct sockaddr_in); + while (1){ + sock= socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) error("socket"); + bzero(buffer,256); +// printf("Please enter the message: "); +// fgets(buffer,255,stdin); + double freq=50; + while(1){ + freq*=1.001; + if(freq>20000) freq=50; + sprintf(buffer,"%.4f;",freq); + n=sendto(sock,buffer, + strlen(buffer),0,(const struct sockaddr *)&server,length); + if (n < 0) error("Sendto"); + usleep(1000); + } + } + close(sock); + return 0; +} + +void error(const char *msg) +{ + perror(msg); + exit(0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/resources/network/udp-client.c Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,52 @@ +/* UDP client in the internet domain */ +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +void error(const char *); +int main(int argc, char *argv[]) +{ + int sock, n; + unsigned int length; + struct sockaddr_in server, from; + struct hostent *hp; + char buffer[256]; + + if (argc != 3) { printf("Usage: server port\n"); + exit(1); + } + + server.sin_family = AF_INET; + hp = gethostbyname(argv[1]); + if (hp==0) error("Unknown host"); + + bcopy((char *)hp->h_addr, + (char *)&server.sin_addr, + hp->h_length); + server.sin_port = htons(atoi(argv[2])); + length=sizeof(struct sockaddr_in); + while (1){ + sock= socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) error("socket"); + bzero(buffer,256); + printf("Please enter the message: "); + fgets(buffer,255,stdin); + n=sendto(sock,buffer, + strlen(buffer),0,(const struct sockaddr *)&server,length); + if (n < 0) error("Sendto"); + } + close(sock); + return 0; +} + +void error(const char *msg) +{ + perror(msg); + exit(0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/resources/network/udp-server.c Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,54 @@ +/* Creates a datagram server. The port + number is passed as an argument. This + server runs forever */ + +#include <sys/types.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <string.h> +#include <netdb.h> +#include <stdio.h> + +void error(const char *msg) +{ + perror(msg); + exit(0); +} + +int main(int argc, char *argv[]) +{ + int sock, length, n; + socklen_t fromlen; + struct sockaddr_in server; + struct sockaddr_in from; + char buf[1024]; + + if (argc < 2) { + fprintf(stderr, "ERROR, no port provided\n"); + exit(0); + } + + sock=socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) error("Opening socket"); + length = sizeof(server); + bzero(&server,length); + server.sin_family=AF_INET; + server.sin_addr.s_addr=INADDR_ANY; + server.sin_port=htons(atoi(argv[1])); + if (bind(sock,(struct sockaddr *)&server,length)<0) + error("binding"); + fromlen = sizeof(struct sockaddr_in); + while (1) { + n = recvfrom(sock,buf,1024,0,(struct sockaddr *)&from,&fromlen); + if (n < 0) error("recvfrom"); + write(1,"Received a datagram: ",21); + write(1,buf,n); + n = sendto(sock,"Got your message\n",17, + 0,(struct sockaddr *)&from,fromlen); + if (n < 0) error("sendto"); + } + return 0; + } +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/build_project.sh Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,104 @@ +#!/bin/bash +# +# This script compiles a BeagleRT project on the BeagleBone Black and +# optionally runs it. Pass a directory path in the first argument. +# The source files in this directory are copied to the board and compiled. + +BBB_ADDRESS="root@192.168.7.2" +BBB_PATH="~/BeagleRT" +RUN_PROJECT=1 +COMMAND_ARGS= + +function usage +{ + THIS_SCRIPT=`basename "$0"` + echo "Usage: $THIS_SCRIPT [-b path-on-beaglebone] [-c command-line-args] [-n] <directory-with-source-files>" + echo " + This script copies a directory of source files to the BeagleBone, compiles + and runs it. The BeagleRT core files should have first been copied over + using the setup_board.sh script supplied with BeagleRT. + + The source directory should contain at least one .c, .cpp or .S file. + If the argument -n is passed, the output will not be run after compiling. + The argument -b will change the local path on the BeagleBone where the + BeagleRT files are found. The -c option passes command-line arguments to + the BeagleRT program; enclose the argument string in quotes." +} + +OPTIND=1 + +while getopts "b:c:nh" opt; do + case $opt in + b) BBB_PATH=$OPTARG + ;; + c) COMMAND_ARGS=$OPTARG + ;; + n) RUN_PROJECT=0 + ;; + h|\?) usage + exit 1 + esac +done + +shift $((OPTIND-1)) + +# Check that we have a directory containing at least one source file +# as an argument + +if [ -z "$1" ] +then + usage + exit +fi + +FIND_STRING="find $* -maxdepth 10000 -type f " + +C_FILES=$($FIND_STRING -name "*.c") +CPP_FILES=$($FIND_STRING -name "*.cpp") +ASM_FILES=$($FIND_STRING -name "*.S") + +if [[ -z $C_FILES ]] && [[ -z $CPP_FILES ]] && [[ -z $ASM_FILES ]] +then + echo "Please provide a directory containing .c, .cpp or .S files." +# echo "Usage: $THIS_SCRIPT [directory-with-source-files]" + usage + exit +fi + +# Stop BeagleRT and clean out old source files +echo "Stopping BeagleRT and removing old source files..." +ssh -t -t $BBB_ADDRESS "screen -X -S BeagleRT quit ; pkill BeagleRT ; make sourceclean -C $BBB_PATH" + +#concatenate arguments to form path. +BBB_SOURCE_PATH= #initially empty, will be filled with input arguments +for i in "$@" #parse input arguments +do + if [ -d "$1" ] #check if the path is a folder + then #if it is, include all of its files + BBB_SOURCE_PATH+=" ${1}/* " + else + BBB_SOURCE_PATH+=" $1 " + fi + shift + # Copy new souce files to the board +done + +# Copy new source files to the board +echo "Copying new source files to BeagleBone..." +scp $BBB_SOURCE_PATH "$BBB_ADDRESS:$BBB_PATH/source/" + +if [ $? -ne 0 ] +then + echo "Error while copying files" + exit +fi + +# Make new BeagleRT executable and run +if [ $RUN_PROJECT -eq 0 ] +then + echo "Building project..." + ssh $BBB_ADDRESS "make all -C $BBB_PATH" +else + echo "Building and running project..." + ssh $BBB_ADDRESS "make all -C $BBB_PATH && screen -S BeagleRT -d -m $BBB_PATH/BeagleRT $COMMAND_ARGS" +fi \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/connect_to_project.sh Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,8 @@ +#!/bin/bash +# +# This script brings an already running BeagleRT program to the foreground +# in the terminal, so it can be run interactively. + +BBB_ADDRESS="root@192.168.7.2" + +ssh -t $BBB_ADDRESS "screen -S BeagleRT -r" \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/halt_board.sh Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,8 @@ +#!/bin/bash +# +# This script halts the BeagleBone Black. + +BBB_ADDRESS="root@192.168.7.2" + +echo "Shutting down the BeagleBone Black..." +ssh $BBB_ADDRESS "halt" \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/run_project.sh Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,48 @@ +#!/bin/bash +# +# This script runs an already-compiled BeagleRT project on the +# BeagleBone Black. + +BBB_ADDRESS="root@192.168.7.2" +BBB_PATH="~/BeagleRT" +COMMAND_ARGS= +RUN_IN_FOREGROUND=0 + +function usage +{ + THIS_SCRIPT=`basename "$0"` + echo "Usage: $THIS_SCRIPT [-b path-on-beaglebone] [-c command-line-args] [-f]" + + echo " + This script runs a previously compiled BeagleRT project on the + BeagleBone Black. The -b option changes the default path, which + is otherwise $BBB_PATH. The -c option passes command-line arguments + to the BeagleRT program; enclose the argument string in quotes. + The -f argument runs the project in the foreground of the current terminal, + within a screen session that can be detached later." +} + +OPTIND=1 + +while getopts "b:c:fh" opt; do + case $opt in + b) BBB_PATH=$OPTARG + ;; + c) COMMAND_ARGS=$OPTARG + ;; + f) RUN_IN_FOREGROUND=1 + ;; + h|\?) usage + exit 1 + esac +done + +shift $((OPTIND-1)) + +echo "Running BeagleRT..." +if [ $RUN_IN_FOREGROUND -eq 0 ] +then + ssh $BBB_ADDRESS "screen -X -S BeagleRT quit ; pkill BeagleRT ; sleep 0.5 ; screen -S BeagleRT -d -m $BBB_PATH/BeagleRT $COMMAND_ARGS" +else + ssh -t $BBB_ADDRESS "screen -X -S BeagleRT quit ; pkill BeagleRT ; sleep 0.5 ; screen -S BeagleRT $BBB_PATH/BeagleRT $COMMAND_ARGS" +fi \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/set_startup.sh Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,76 @@ +#!/bin/bash +# +# This script enables or disables running BeagleRT when the board starts +# up. + +BBB_ADDRESS="root@192.168.7.2" +BBB_PATH="/root/BeagleRT" +ENABLE_STARTUP=1 +COMMAND_ARGS= +RUN_IN_LOOP=0 + +# This path is hard-coded in the BeagleRT image at present. +BBB_STARTUP_SCRIPT="/root/BeagleRT_startup.sh" + +function usage +{ + THIS_SCRIPT=`basename "$0"` + echo "Usage: $THIS_SCRIPT [-b path-on-beaglebone] [-c command-line-args] [-n] [-l]" + + echo " + This script enables (by default) or disables running the BeagleRT + project at startup. The -n option disables auto-startup, otherwise + auto-startup is enabled. The -b option changes the default path, which + is otherwise $BBB_PATH. The -c option passes command-line arguments to + the BeagleRT program; enclose the argument string in quotes. + The -l option runs the BeagleRT program in a loop, restarting + automatically in the event of a crash." +} + +OPTIND=1 + +while getopts "b:c:nlh" opt; do + case $opt in + b) BBB_PATH=$OPTARG + ;; + c) COMMAND_ARGS=$OPTARG + ;; + n) ENABLE_STARTUP=0 + ;; + l) RUN_IN_LOOP=1 + ;; + h|\?) usage + exit 1 + esac +done + +shift $((OPTIND-1)) + +if [ $ENABLE_STARTUP -eq 0 ] +then + echo "Disabling BeagleRT at startup..." + + ssh $BBB_ADDRESS "echo \"#!/bin/sh +# +# This file is autogenerated by BeagleRT. Do not edit! + +# Run on startup disabled -- nothing to do here\" > $BBB_STARTUP_SCRIPT" + +else + echo "Enabling BeagleRT at startup..." + + SCRIPT_PRERUN= + SCRIPT_POSTRUN= + if [ $RUN_IN_LOOP -ne 0 ] ; then + SCRIPT_PRERUN="bash -c \\\"while true ; do" + SCRIPT_POSTRUN=" ; done \\\" " + fi + + ssh $BBB_ADDRESS "echo \"#!/bin/sh +# +# This file is autogenerated by BeagleRT. Do not edit! + +echo Running BeagleRT... +screen -S BeagleRT -d -m $SCRIPT_PRERUN $BBB_PATH/BeagleRT $COMMAND_ARGS $SCRIPT_POSTRUN\" > $BBB_STARTUP_SCRIPT" + +fi \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/setup_board.sh Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,63 @@ +#!/bin/bash +# +# This script copies the core BeagleRT files to the BeagleBone Black +# in preparation for building projects. It will remove any existing +# BeagleRT directory before copying the files over + +BBB_ADDRESS="root@192.168.7.2" +BBB_PATH="~/BeagleRT" + +function usage +{ + THIS_SCRIPT=`basename "$0"` + echo "Usage: $THIS_SCRIPT [-b path-on-beaglebone]" + + echo " + This script copies the core BeagleRT files to the BeagleBone, REMOVING + any previous files found at that location. This should be done before + running any of the other build scripts in this directory. The -b option + changes the default path, which is otherwise $BBB_PATH." +} + +OPTIND=1 + +while getopts "b:h" opt; do + case $opt in + b) BBB_PATH=$OPTARG + ;; + h|\?) usage + exit 1 + esac +done + +echo "Copying BeagleRT core files to $BBB_PATH" + +shift $((OPTIND-1)) + +# Find location of this script so we can locate the rest of the files +SCRIPTPATH=$(readlink -f "$0") +SCRIPTDIR=$(dirname "$SCRIPTPATH") + +read -p "Warning: this script will DELETE any existing BeagleRT files from your BeagleBone! Continue? " -n 1 -r +echo +if [[ $REPLY =~ ^[Yy]$ ]] +then +# Stop BeagleRT if running and remove all files + echo "Stopping BeagleRT and removing old files." + ssh $BBB_ADDRESS "screen -X -S BeagleRT quit ; pkill BeagleRT; sleep 0.5 ; rm -rf $BBB_PATH ; mkdir $BBB_PATH" + +# Copy relevant files to BeagleBone Black + echo "Copying new files to BeagleBone..." + scp -r $SCRIPTDIR/../core $SCRIPTDIR/../include $SCRIPTDIR/../Makefile $SCRIPTDIR/../libNE10.a $SCRIPTDIR/../libprussdrv.a $BBB_ADDRESS:$BBB_PATH + + if [ $? -ne 0 ] + then + echo "Error while copying files" + exit + fi +# Make remaining directories needed for building + echo "Creating directory structure on BeagleBone..." + ssh $BBB_ADDRESS "mkdir -p $BBB_PATH/source ; mkdir -p $BBB_PATH/build ; mkdir -p $BBB_PATH/build/core ; mkdir -p $BBB_PATH/build/source" &&\ + echo "Done." +fi +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/stop_running.sh Fri Jul 17 15:28:18 2015 +0100 @@ -0,0 +1,11 @@ +#!/bin/bash +# +# This script stops the BeagleRT program running on the BeagleBone. + +BBB_ADDRESS="root@192.168.7.2" + +echo "Stopping BeagleRT..." + +# The first command should be sufficient to stop any BeagleRT run with +# these scripts; the second will catch any leftovers run other ways +ssh $BBB_ADDRESS "screen -X -S BeagleRT quit ; pkill BeagleRT" \ No newline at end of file