diff core/PRU.cpp @ 12:a6beeba3a648

Initial support for higher matrix sample rates by reducing the number of channels. Input not tested yet, and not all examples updated to new format.
author andrewm
date Thu, 22 Jan 2015 19:00:22 +0000
parents 8a575ba3ab52
children 901d205d1a3c
line wrap: on
line diff
--- a/core/PRU.cpp	Thu Nov 13 16:02:59 2014 +0100
+++ b/core/PRU.cpp	Thu Jan 22 19:00:22 2015 +0000
@@ -50,8 +50,9 @@
 #define PRU_LED_PIN_MASK	7
 #define PRU_FRAME_COUNT		8
 #define PRU_USE_SPI			9
+#define PRU_SPI_NUM_CHANNELS 10
 
-#define PRU_SAMPLE_INTERVAL_NS 45351	// 22050Hz per SPI sample = 45.351us
+#define PRU_SAMPLE_INTERVAL_NS 11338	// 88200Hz per SPI sample = 11.338us
 
 #define GPIO0_ADDRESS 		0x44E07000
 #define GPIO1_ADDRESS 		0x4804C000
@@ -79,7 +80,7 @@
 // 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), xenomai_gpio_fd(-1), xenomai_gpio(0)
+  gpio_test_pin_enabled(false), spi_num_channels(0), xenomai_gpio_fd(-1), xenomai_gpio(0)
 {
 
 }
@@ -224,7 +225,7 @@
 }
 
 // Initialise and open the PRU
-int PRU::initialise(int pru_num, int frames_per_buffer, bool xenomai_test_pin)
+int PRU::initialise(int pru_num, int frames_per_buffer, int spi_channels, bool xenomai_test_pin)
 {
 	uint32_t *pruMem = 0;
 
@@ -235,6 +236,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;
@@ -250,22 +258,22 @@
     prussdrv_pruintc_init(&pruss_intc_initdata);
 
     spi_buffer_frames = frames_per_buffer;
-    audio_buffer_frames = spi_buffer_frames * 2;
+    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)*2(samples/spi)*bufsize samples later */
-	pru_buffer_audio_adc = &pru_buffer_audio_dac[8 * spi_buffer_frames];
+	/* ADC memory starts 2(ch)*2(buffers)*bufsize samples later */
+	pru_buffer_audio_adc = &pru_buffer_audio_dac[4 * audio_buffer_frames];
 
 	if(spi_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 8(ch)*2(buffers)*bufsize samples */
-		pru_buffer_spi_adc = &pru_buffer_spi_dac[16 * spi_buffer_frames];
+		/* 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];
 	}
 	else {
 		pru_buffer_spi_dac = pru_buffer_spi_adc = 0;
@@ -288,9 +296,11 @@
     }
     if(spi_enabled) {
     	pru_buffer_comm[PRU_USE_SPI] = 1;
+    	pru_buffer_comm[PRU_SPI_NUM_CHANNELS] = spi_num_channels;
     }
     else {
     	pru_buffer_comm[PRU_USE_SPI] = 0;
+    	pru_buffer_comm[PRU_SPI_NUM_CHANNELS] = 0;
     }
 
     /* Clear ADC and DAC memory */
@@ -340,7 +350,7 @@
 void PRU::loop()
 {
 	// Polling interval is 1/4 of the period
-	RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * spi_buffer_frames / 4;
+	RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * (spi_num_channels / 2) * spi_buffer_frames / 4;
 	float *audioInBuffer, *audioOutBuffer;
 
 	audioInBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float));
@@ -410,7 +420,7 @@
 
 		if(spi_enabled)
 			render(spi_buffer_frames, audio_buffer_frames, audioInBuffer, audioOutBuffer,
-					&pru_buffer_spi_adc[spi_buffer_frames * 8], &pru_buffer_spi_dac[spi_buffer_frames * 8]);
+					&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);