changeset 23:182ae9367104 matrix_gpio

- persistency: the last frame of each digital and analogOut buffers is used to initialize all the frames in the next buffer. This means that once a value is set, the pin will hold the value until you change it - AnalogXyz macros have been renamed to analogXyz - the short option -P has been removed. The long option --pru-file has to be used instead
author Giulio Moro <giuliomoro@yahoo.it>
date Tue, 05 May 2015 17:28:00 +0100
parents fbfeb5895efd
children ad5cd8dd99b3 6d64ee8c0754
files .cproject .settings/org.eclipse.cdt.core.prefs core/PRU.cpp core/RTAudioCommandLine.cpp include/Utilities.h projects/analogDigitalDemo/render.cpp
diffstat 6 files changed, 132 insertions(+), 72 deletions(-) [+]
line wrap: on
line diff
--- a/.cproject	Sun May 03 01:10:17 2015 +0100
+++ b/.cproject	Tue May 05 17:28:00 2015 +0100
@@ -5,12 +5,12 @@
 			<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">
@@ -26,32 +26,32 @@
 							</builder>
 							<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">
+								<option id="gnu.cpp.compiler.exe.debug.option.optimization.level.2006448218" name="Optimization Level" superClass="gnu.cpp.compiler.exe.debug.option.optimization.level" useByScannerDiscovery="false" 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" useByScannerDiscovery="false" 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" useByScannerDiscovery="false" 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"/>
 								</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"/>
+								<option id="gnu.cpp.compiler.option.other.other.1516989263" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" 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" useByScannerDiscovery="false" value="true" valueType="boolean"/>
+								<option id="gnu.cpp.compiler.option.dialect.std.904910934" name="Language standard" superClass="gnu.cpp.compiler.option.dialect.std" useByScannerDiscovery="true" 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.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">
+								<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" useByScannerDiscovery="false" 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" useByScannerDiscovery="false" 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" useByScannerDiscovery="false" 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"/>
 								</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"/>
+								<option id="gnu.c.compiler.option.misc.other.835792865" name="Other flags" superClass="gnu.c.compiler.option.misc.other" useByScannerDiscovery="false" 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" useByScannerDiscovery="false" value="true" valueType="boolean"/>
 								<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.308014221" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
 							</tool>
 							<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"/>
@@ -92,7 +92,7 @@
 					<sourceEntries>
 						<entry excluding="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/tank_wars"/>
+						<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="projects/analogDigitalDemo"/>
 						<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="source"/>
 					</sourceEntries>
 				</configuration>
@@ -103,12 +103,12 @@
 			<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">
@@ -157,7 +157,6 @@
 								</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"/>
-									<listOptionValue builtIn="false" value="sndfile"/>
 									<listOptionValue builtIn="false" value="native"/>
 									<listOptionValue builtIn="false" value="xenomai"/>
 								</option>
@@ -178,7 +177,7 @@
 					<sourceEntries>
 						<entry excluding="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/tank_wars"/>
+						<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="projects/analogDigitalDemo"/>
 						<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="source"/>
 					</sourceEntries>
 				</configuration>
--- a/.settings/org.eclipse.cdt.core.prefs	Sun May 03 01:10:17 2015 +0100
+++ b/.settings/org.eclipse.cdt.core.prefs	Tue May 05 17:28:00 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
--- a/core/PRU.cpp	Sun May 03 01:10:17 2015 +0100
+++ b/core/PRU.cpp	Tue May 05 17:28:00 2015 +0100
@@ -432,33 +432,34 @@
 	// 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;
-	float *analogInBuffer, *analogOutBuffer;
-	uint32_t *digitalBuffer0, *digitalBuffer1, *digitalBufferTemp;
+	float *analogInBuffer, *analogOutBuffer, *lastAnalogOutFrame;
+	uint32_t *digitalBuffer0, *digitalBuffer1, *lastDigitalBuffer;
 
 	audioInBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float));
 	audioOutBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float));
 	analogInBuffer = (float *)malloc(spi_num_channels * spi_buffer_frames * sizeof(float));
 	analogOutBuffer = (float *)malloc(spi_num_channels * spi_buffer_frames * sizeof(float));
+	lastAnalogOutFrame = (float *)malloc(spi_num_channels * sizeof(float));
 	digitalBuffer0 = pru_buffer_digital; 
 	digitalBuffer1 = pru_buffer_digital+MEM_DIGITAL_BUFFER1_OFFSET/sizeof(uint32_t);
-   digital_buffer_frames = digital_enabled ? audio_buffer_frames : 0; //TODO: find a more elegant solution for when the digital is disabled e.g.:
+    digital_buffer_frames = digital_enabled ? audio_buffer_frames : 0; //TODO: find a more elegant solution for when the digital is disabled e.g.:
     																	// - embed in the digitalWrite/Read macros a check whether digital is enabled
     																	// - allocate some memory in ARM just to allow render() to run regardless.
     																	//     in this case it can be digitalBuffer0 == digitalBuffer1
 	printf("digital_buffer_frames: %d;\n",digital_buffer_frames);
-    digitalBufferTemp = (uint32_t *)malloc(digital_buffer_frames*sizeof(uint32_t)); //temp buffer to hold previous states
+    lastDigitalBuffer = (uint32_t *)malloc(digital_buffer_frames*sizeof(uint32_t)); //temp buffer to hold previous states
 	if(audioInBuffer == 0 || audioOutBuffer == 0) {
 		rt_printf("Error: couldn't allocate audio buffers\n");
 		return;
 	}
-	if(analogInBuffer == 0 || analogOutBuffer == 0) {
+	if(analogInBuffer == 0 || analogOutBuffer == 0 || lastAnalogOutFrame == 0) {
 		rt_printf("Error: couldn't allocate analog buffers\n");
 		return;
 	}
-	if(digitalBufferTemp == 0) {
+	if(lastDigitalBuffer == 0) {
 		rt_printf("Error: couldn't allocate digital buffers\n");
 		return;
-	} 
+	}
 	
 	while(!gShouldStop) {
 		// Wait for PRU to move to buffer 1
@@ -481,22 +482,33 @@
 		if(spi_enabled) {
 			for(unsigned int n = 0; n < spi_num_channels * spi_buffer_frames; n++)
 				analogInBuffer[n] = (float)pru_buffer_spi_adc[n] / 65536.0;
-        //use past digital values to initialize the array properly:
-        //- pins previously set as outputs will keep their previously set output value,
+			//initialize the output buffer with the values that were in the last frame of the previous output
+			for(int n = 0; n < spi_num_channels; n++){
+				for(unsigned int j = 0; j < spi_buffer_frames; j++){
+					analogOutBuffer[j*spi_buffer_frames + n] = lastAnalogOutFrame[n];
+				}
+			}
+        //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
             if(digital_enabled){
                 for(unsigned int n = 0; n < digital_buffer_frames; n++){ 
-                    uint16_t inputs=digitalBufferTemp[n]&0xffff;//half-word, has 1 for inputs and 0 for outputs
+                    uint16_t inputs=lastDigitalBuffer[n]&0xffff;//half-word, has 1 for inputs and 0 for outputs
 //                    printf("inputs: 0x%x\n",inputs);
                     uint16_t outputs=~inputs; //half-word has 1 for outputs and 0 for inputs;
-                    digitalBuffer0[n]=(digitalBufferTemp[n]&(outputs<<16))| //keep output values set in previous digitalBuffer1[n]
+                    digitalBuffer0[n]=(lastDigitalBuffer[digital_buffer_frames-1]&(outputs<<16))| //keep output values set in the last frame of the previous buffer
                                          (digitalBuffer0[n]&(inputs<<16))   | //inputs from current digitalBuffer0[n];
-                                         (digitalBufferTemp[n]&(inputs));     //keep pin configuration from previous digitalBuffer1[n]
+                                         (lastDigitalBuffer[n]&(inputs));     //keep pin configuration from previous digitalBuffer1[n]
 //                    digitalBuffer0[n]=digitalBufferTemp[n]; //ignores inputs
                 }
             }
 			render(spi_buffer_frames, digital_buffer_frames, audio_buffer_frames, audioInBuffer, audioOutBuffer,
 					analogInBuffer, analogOutBuffer, digitalBuffer0);
+			//remember the content of the lastAnalogOutFrame
+			for(int n = 0; n < spi_num_channels; n++){
+				lastAnalogOutFrame[n] = analogOutBuffer[spi_buffer_frames*(spi_buffer_frames-1) + n];
+			}
 			for(unsigned int n = 0; n < spi_num_channels * spi_buffer_frames; n++) {
 				int out = analogOutBuffer[n] * 65536.0;
 				if(out < 0) out = 0;
@@ -505,7 +517,7 @@
 			}
             if(digital_enabled){ // keep track of past digital values
                 for(unsigned int n = 0; n < digital_buffer_frames; n++){ 
-                    digitalBufferTemp[n]=digitalBuffer0[n];
+                    lastDigitalBuffer[n]=digitalBuffer0[n];
                 }
             }
 		}
@@ -544,24 +556,33 @@
 			audioInBuffer[n] = (float)pru_buffer_audio_adc[n + audio_buffer_frames * 2] / 32768.0;
 
 		if(spi_enabled) {
-			for(unsigned int n = 0; n < spi_num_channels * spi_buffer_frames; n++)
+			 //convert input values TODO: move to PRU
+			for(unsigned int n = 0; n < spi_num_channels * spi_buffer_frames; n++){
 				analogInBuffer[n] = (float)pru_buffer_spi_adc[n + spi_buffer_frames * spi_num_channels] / 65536.0;
-
-            //use past digital values to initialize the array properly:
-            //- pins previously set as outputs will keep their previously set output value,
-            //- pins previously set as inputs will carry the newly read input value
+			}
+			//initialize the output buffer with the values that were in the last frame of the previous output
+			for(int n = 0; n < spi_num_channels; n++){
+				for(unsigned int j = 0; j < spi_buffer_frames; j++){
+					analogOutBuffer[j*spi_buffer_frames + n] = lastAnalogOutFrame[n];
+				}
+			}
             if(digital_enabled){
-                for(unsigned int n = 0; n < digital_buffer_frames; n++){ 
-                    uint16_t inputs=digitalBufferTemp[n]&0xffff;//half-word, has 1 for inputs and 0 for outputs
+                for(unsigned int n = 0; n < digital_buffer_frames; 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 one for inputs;
-                    digitalBuffer1[n]=(digitalBufferTemp[n]&(outputs<<16))| //keep output values set in previous digitalBuffer1[n]
+                    digitalBuffer1[n]=(lastDigitalBuffer[digital_buffer_frames-1]&(outputs<<16))| //keep output values set in the last frame of the  previous buffer
                                          (digitalBuffer1[n]&(inputs<<16))   | //inputs from current digitalBuffer1[n];
-                                         (digitalBufferTemp[n]&(inputs));     //keep pin configuration from previous digitalBuffer1[n]
+                                         (lastDigitalBuffer[n]&(inputs));     //keep pin configuration from previous digitalBuffer1[n]
 //                    digitalBuffer1[n]=digitalBufferTemp[n]; //ignores inputs
                 }
             }
 			render(spi_buffer_frames, digital_buffer_frames, audio_buffer_frames, audioInBuffer, audioOutBuffer,
 					analogInBuffer, analogOutBuffer, digitalBuffer1);
+			//remember the content of the lastAnalogOutFrame
+			for(int n = 0; n < spi_num_channels; n++){
+				lastAnalogOutFrame[n] = analogOutBuffer[spi_buffer_frames*(spi_buffer_frames-1) + n];
+			}
+
 			for(unsigned int n = 0; n < spi_num_channels * spi_buffer_frames; n++) {
 				int out = analogOutBuffer[n] * 65536.0;
 				if(out < 0) out = 0;
@@ -570,7 +591,7 @@
 			}
             if(digital_enabled){ // keep track of past digital values
                 for(unsigned int n = 0; n < digital_buffer_frames; n++){ 
-                    digitalBufferTemp[n]=digitalBuffer1[n];
+                    lastDigitalBuffer[n]=digitalBuffer1[n];
                 }
             }
 		}
@@ -598,7 +619,8 @@
 	free(audioInBuffer);
 	free(audioOutBuffer);
 	free(analogInBuffer);
-    free(digitalBufferTemp);
+	free(lastAnalogOutFrame);
+    free(lastDigitalBuffer);
 }
 
 // Wait for an interrupt from the PRU indicate it is finished
--- a/core/RTAudioCommandLine.cpp	Sun May 03 01:10:17 2015 +0100
+++ b/core/RTAudioCommandLine.cpp	Tue May 05 17:28:00 2015 +0100
@@ -10,6 +10,9 @@
 #include <cstring>
 #include <getopt.h>
 #include "../include/RTAudio.h"
+#ifndef OPT_PRU_FILE
+#define OPT_PRU_FILE -1
+#endif
 
 // Default command-line options for RTAudio
 struct option gDefaultLongOptions[] =
@@ -17,18 +20,17 @@
 	{"period", 1, NULL, 'p'},
 	{"verbose", 0, NULL, 'v'},
 	{"use-analog", 1, NULL, 'm'},
-	{"use-analog-gpio", 1, NULL, 'g'},
+	{"use-digital-gpio", 1, NULL, 'g'},
 	{"analog-channels", 1, NULL, 'C'},
-	{"analog-gpio-channels", 1, NULL, 'G'},
+	{"digital-gpio-channels", 1, NULL, 'G'},
 	{"mute-speaker", 1, NULL, 'M'},
 	{"dac-level", 1, NULL, 'D'},
 	{"adc-level", 1, NULL, 'A'},
 	{"hp-level", 1, NULL, 'H'},
-	{"pru-file",1,NULL,'P'},
+	{"pru-file",1,NULL,OPT_PRU_FILE},
 	{NULL, 0, NULL, 0}
 };
-
-const char gDefaultShortOptions[] = "p:vm:M:C:D:A:H:P:g:G:";
+const char gDefaultShortOptions[] = "p:vm:M:C:D:A:H:g:G:";
 
 // This function sets the default settings for the RTAudioSettings structure
 void BeagleRT_defaultSettings(RTAudioSettings *settings)
@@ -165,7 +167,7 @@
 		case 'H':
 			settings->headphoneLevel = atof(optarg);
 			break;
-		case 'P':
+		case OPT_PRU_FILE:
 			if(strlen(optarg)<MAX_PRU_FILENAME_LENGTH)
 				strcpy(settings->pruFilename, optarg);
 			else
@@ -191,7 +193,7 @@
 	std::cerr << "   --use-gpio-analog [-g] val:      Set whether to use GPIO analog (default: yes)\n";
 	std::cerr << "   --analog-channels [-C] val:      Set the number of ADC/DAC channels (default: 8)\n";
 	std::cerr << "   --analog-gpio-channels [-G] val: Set the number of GPIO channels (default: 16)\n";
-	std::cerr << "   --pru-file [-P] val:             Set an optional external file to use for the PRU binary code\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/include/Utilities.h	Sun May 03 01:10:17 2015 +0100
+++ b/include/Utilities.h	Tue May 05 17:28:00 2015 +0100
@@ -14,13 +14,13 @@
 // 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)])
+#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) \
+#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); \
+		analogWriteFrame(pin,_privateI,value); \
 	}\
 	} while (0);}),(void)0)\
 
--- a/projects/analogDigitalDemo/render.cpp	Sun May 03 01:10:17 2015 +0100
+++ b/projects/analogDigitalDemo/render.cpp	Tue May 05 17:28:00 2015 +0100
@@ -1,4 +1,4 @@
-/*
+    /*
  *
  * First assignment for ECS732 RTDSP, to implement a 2-way audio crossover
  * using the BeagleBone Black.
@@ -29,6 +29,7 @@
 					   void *userData)
 {
 	gNumAnalogChannels=numAnalogChannels;
+    gNumDigitalChannels=numDigitalChannels;
 	return true;
 }
 
@@ -41,32 +42,54 @@
 void render(int numAnalogFrames, int numDigitalFrames, int numAudioFrames, float *audioIn, float *audioOut,
 			float *analogIn, float *analogOut, uint32_t *digital)
 /*
- * Hey, expect buffer underruns to happen here, as we are doing lots of printfs
+we assume that gNumAnalogChannels=8, numAnalogFrames==8 and  numDigitalFrames==numAudioFrames
  * */
 {
 	gNumDigitalFrames=numDigitalFrames;
-	if(gCountFrames==0){ //this will be executed only on the first call to render(), but the bits will go through this cycle for every subsequent buffer
-						// that is, P8_29 will pulse at the beginning of each buffer
+
+	if((gCountFrames&31)==0){ //every 32 frames...
+        //ANALOG channels
+		analogWrite(0, 0, analogRead(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
+        analogWrite(3, 0, 1.0);  // write 1.0 to channel3 from frame0 to the end of the buffer
+        analogWrite(3, 4, 0.1);  // write 0.1  to channel3 from frame4 to the end of the buffer
+        analogWriteFrame(3,6,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
+        digitalWrite(P8_07,0,GPIO_HIGH); //sets all the frames  to HIGH for channel 0
+        digitalWriteFrame(P8_07,4,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)
+        digitalWrite(P8_08,0,GPIO_HIGH);
+        digitalWrite(P8_08,2,GPIO_LOW);
+        digitalWrite(P8_08,4,GPIO_HIGH);
+        digitalWrite(P8_08,5,GPIO_LOW);
+        // 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(int i=1; i<gNumDigitalFrames; i++)
-		digitalWriteAll(i, GPIO_LOW); //write all channels on the given frame. Initialize them to zero
-	digitalWrite(0, 4, GPIO_HIGH); // set pin 0 HIGH from the current frame to the end of the buffer
-	for(int n=0; n<numAnalogFrames; n++) {
-		for(int c=0; c<gNumAnalogChannels; c++)
-			AnalogWriteFrame(c,n,0); //set channel c on frame n to 0, equivalent to analogOut[n*numAnalogChannels+c]=0;
+	for(int n=0; n<numAudioFrames; n++){
+		for(int c=0; c<gNumAudioChannels; c++){
+			audioOut[n*gNumAudioChannels + c]=audioIn[n*gNumAudioChannels + c];
+		}
+        //use digital channels 2-5 to create a 4 bit binary counter
+        digital[n]=digital[n] & (~0b111100); // set to zero (GPIO_OUTPUT) the bits in the lower word
+        digital[n]=digital[n] & (~0b111100<<16); //initialize to zero the bits in the higher word (output value)
+        digital[n]=digital[n] | (n<<(16+2));  // set the bits in the higher word to the desired output value
 	}
-	AnalogWrite(0,3,0.2); //set channel 0 to 0.2 from frame 3 onwards ...
-	AnalogWrite(1,3,0.7); //set channel 1 to 0.7 from frame 3 onwards ...
-	AnalogWrite(2,6,0.5); //set channel 2 to 0.5 from frame 6 onwards ...
-	for(int n=0; n<numAudioFrames; n++){
-		printf("Digital frame %d: 0x%08x;\n",n,digital[n]);
+
+	for(int n=0; n<numAnalogFrames; n++){
+    	analogWriteFrame(1,n,(gCountFrames&8191)/8192.0); // writes a single frame. channel 1 is a ramp that follows gCountFrames
+    	analogWriteFrame(2,n,analogRead(2,n)); // 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");
+		gCountFrames++;
 	}
-	for(int n=0; n<numAnalogFrames; n++){
-		printf("Analog out frame %d :",n);
-		for(int c=0; c<gNumAnalogChannels; c++)
-			printf("%.1f ",analogOut[n*gNumAnalogChannels + c]);
-		printf("\n");
-	}
+	return;
+
 }
 // cleanup_render() is called once at the end, after the audio has stopped.
 // Release any resources that were allocated in initialise_render().