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 &quot;kill -s 2 \`pidof ${BuildArtifactFileName}\` 2&gt;/dev/null; sleep 0.5; scp host:${PWD}/${BuildArtifactFileName} ~/beaglert/ &amp;&amp; echo 'done copying\n' | wall || echo 'error'|wall&quot;">
 					<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++&#10;" id="cdt.managedbuild.tool.gnu.archiver.base.1542380883" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+							<tool command="arm-linux-gnueabihf-g++&#10;" 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="&quot;${workspace_loc:/BeagleRT/include}&quot;"/>
 								</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="&quot;${workspace_loc:/BeagleRT/include}&quot;"/>
 								</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++&#10;" 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++&#10;" 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="&quot;${workspace_loc:/${ProjName}/libprussdrv.a}&quot;"/>
 									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/libNE10.a}&quot;"/>
@@ -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="&quot;${workspace_loc:/BeagleRT/include}&quot;"/>
 								</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 &quot;kill -s 2 \`pidof ${BuildArtifactFileName}\` 2&gt;/dev/null&quot;; 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++&#10;" id="cdt.managedbuild.tool.gnu.archiver.base.810674388" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+							<tool command="arm-linux-gnueabihf-g++&#10;" 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="&quot;${workspace_loc:/BeagleRT/include}&quot;"/>
 								</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="&quot;${workspace_loc:/BeagleRT/include}&quot;"/>
+								</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++&#10;" 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++&#10;" 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="&quot;${workspace_loc:/BeagleRT/include}&quot;"/>
+								</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();
Binary file pru_rtaudio.bin has changed
--- 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