diff core/PRU.cpp @ 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 c98863e63174
children a9af130097e8
line wrap: on
line diff
--- 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