changeset 38:a9af130097e8 staging

GPIO pins are initialised as inputs by ARM to avoid spikes at startup, through gpio_set_dir. The buffers are set to 0x000ffff during initialisation. LastDigitalBuffer is initialized to 0x0000ffff.
author Giulio Moro <giuliomoro@yahoo.it>
date Tue, 12 May 2015 23:48:37 +0100
parents 46571f8f04a1
children 638bc1ae2500
files .cproject core/PRU.cpp include/pru_rtaudio_bin.h pru_rtaudio.bin pru_rtaudio.p
diffstat 5 files changed, 95 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- a/.cproject	Mon May 11 20:11:20 2015 +0100
+++ b/.cproject	Tue May 12 23:48:37 2015 +0100
@@ -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" kind="sourcePath" name="projects/basic_network"/>
+						<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="projects/analogDigitalDemo"/>
 						<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="source"/>
 					</sourceEntries>
 				</configuration>
@@ -177,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" kind="sourcePath" name="projects/basic_network"/>
+						<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="projects/analogDigitalDemo"/>
 						<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="source"/>
 					</sourceEntries>
 				</configuration>
--- a/core/PRU.cpp	Mon May 11 20:11:20 2015 +0100
+++ b/core/PRU.cpp	Tue May 12 23:48:37 2015 +0100
@@ -56,7 +56,7 @@
 #define PRU_FRAME_COUNT		8
 #define PRU_USE_SPI			9
 #define PRU_SPI_NUM_CHANNELS 10
-#define PRU_USE_GPIO_ANALOG 11
+#define PRU_USE_DIGITAL    11
 
 short int digitalPins[NUM_DIGITALS]={
 		GPIO_NO_BIT_0,
@@ -170,16 +170,11 @@
 		for(int i=0; i<gNumDigitalChannels; i++){
 			if(gpio_export(digitalPins[i])) {
 				if(gRTAudioVerbose)
-					cout << "Warning: couldn't export digital GPIO pin " << digitalPins[i] << "\n";
+					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], OUTPUT_PIN)) {
+			if(gpio_set_dir(digitalPins[i], INPUT_PIN)) {
 				if(gRTAudioVerbose)
-					cout << "Couldn't set direction on digital GPIO pin " << digitalPins[i] << "\n";
-				return -1;
-			}
-			if(gpio_set_value(digitalPins[i], HIGH)) {
-				if(gRTAudioVerbose)
-					cout << "Couldn't set value on digital GPIO pin " << digitalPins[i] << "\n";
+					cerr << "Error: Couldn't set direction on digital GPIO pin " << digitalPins[i] << "\n";
 				return -1;
 			}
 		}
@@ -361,18 +356,24 @@
     	pru_buffer_comm[PRU_SPI_NUM_CHANNELS] = 0;
     }
     if(digital_enabled) {
-    	pru_buffer_comm[PRU_USE_GPIO_ANALOG] = 1;
-    	pru_buffer_comm[NUM_DIGITALS] = spi_num_channels;
+    	pru_buffer_comm[PRU_USE_DIGITAL] = 1;
+//TODO: add mask
     }
     else {
-    	pru_buffer_comm[PRU_USE_GPIO_ANALOG] = 0;
-    	pru_buffer_comm[NUM_DIGITALS] = 0;
+    	pru_buffer_comm[PRU_USE_DIGITAL] = 0;
+
     }
 
-    /* Clear ADC and DAC memory */
+    /* 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(spi_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;
@@ -460,7 +461,10 @@
 		rt_printf("Error: couldn't allocate digital buffers\n");
 		return;
 	}
-	
+
+	for(unsigned int n=0; n<digital_buffer_frames; n++){ //initialize lastDigitalFrames to all inputs
+		lastDigitalBuffer[n]= 0x0000ffff;
+	}
 	while(!gShouldStop) {
 		// Wait for PRU to move to buffer 1
 		while(pru_buffer_comm[PRU_CURRENT_BUFFER] == 0 && !gShouldStop) {
--- a/include/pru_rtaudio_bin.h	Mon May 11 20:11:20 2015 +0100
+++ b/include/pru_rtaudio_bin.h	Tue May 12 23:48:37 2015 +0100
@@ -608,13 +608,12 @@
      0x0901f7f7,
      0x02f6f7f7,
      0x240000ea,
-     0xd100f803,
-     0x240000e2,
-     0x79000002,
-     0x240400e2,
+     0xd100f804,
      0x240001c6,
      0x24100086,
-     0x00e2e6e6,
+     0x79000003,
+     0x240001c6,
+     0x24140086,
      0x240000e1,
      0xc901f805,
      0x90f2388c,
@@ -786,7 +785,7 @@
      0x00e1e3e3,
      0xe1002382,
      0xf1003982,
-     0x5700e244,
+     0x5700e245,
      0x240000fb,
      0xe1443d9b,
      0xc901f80c,
Binary file pru_rtaudio.bin has changed
--- a/pru_rtaudio.p	Mon May 11 20:11:20 2015 +0100
+++ b/pru_rtaudio.p	Tue May 12 23:48:37 2015 +0100
@@ -182,9 +182,6 @@
 #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
-/*#define FLAG_BIT_DIGITAL_BUFFER 4 //Whether we are using buffer located at
-                                     // 0:  MEM_DIGITAL_BASE or
-*/                                     // 1: MEM_DIGITAL_BASE + 512
 // Registers used throughout
 
 // r1, r2, r3 are used for temporary storage
@@ -414,7 +411,13 @@
 
 // DIGITAL new code ends here
 
-	
+
+.macro HANG
+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
@@ -597,15 +600,25 @@
 	
       // Find out whether we should use DIGITAL
       LBBO r2, reg_comm_addr, COMM_USE_DIGITAL, 4
-      QBEQ DIGITAL_FLAG_CHECK_DONE, r2, 0
-      SET reg_flags, reg_flags, FLAG_BIT_USE_DIGITAL
-//      SET reg_flags, reg_flags, FLAG_BIT_DIGITAL_BUFFER //set the flag, so that in WRITE_ONE_BUFFER we will start from buffer0
-DIGITAL_FLAG_CHECK_DONE:
+      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
@@ -749,17 +762,49 @@
 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:	
@@ -778,6 +823,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
@@ -792,13 +838,11 @@
       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 r2, 0  //so adjust offset appropriately
+      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 r2, MEM_DIGITAL_BUFFER1_OFFSET //so adjust offset appropriately
+      MOV reg_digital_current, MEM_DIGITAL_BASE+MEM_DIGITAL_BUFFER1_OFFSET //so adjust offset appropriately
 DIGITAL_BASE_CHECK_DONE:
-      MOV reg_digital_current, MEM_DIGITAL_BASE
-      ADD reg_digital_current, reg_digital_current, r2
 
 WRITE_LOOP:
       // Write N channels to DAC from successive values in memory
@@ -899,6 +943,7 @@
       LSL r8, r8, AD7699_CHANNEL_OFFSET
       MOV r7, AD7699_CFG_MASK
       OR r7, r7, r8
+
 //ssssssssssssssssssssssssssss
       ADC_WRITE_GPIO r7, r7, r1