changeset 288:771a0920c626 prerelease

merge
author Giulio Moro <giuliomoro@yahoo.it>
date Wed, 18 May 2016 01:50:01 +0100
parents 4815ed0f21de (current diff) bfe2e929304b (diff)
children 156e6955ccf6
files
diffstat 7 files changed, 185 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/core/PRU.cpp	Wed May 18 01:46:32 2016 +0100
+++ b/core/PRU.cpp	Wed May 18 01:50:01 2016 +0100
@@ -48,6 +48,8 @@
 #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
+
+// Offsets within CPU <-> PRU communication memory (4 byte slots)
 #define PRU_SHOULD_STOP 	0
 #define PRU_CURRENT_BUFFER  1
 #define PRU_BUFFER_FRAMES   2
@@ -61,8 +63,9 @@
 #define PRU_SPI_NUM_CHANNELS 10
 #define PRU_USE_DIGITAL      11
 #define PRU_PRU_NUMBER       12
+#define PRU_MUX_CONFIG       13
 
-short int digitalPins[NUM_DIGITALS]={
+short int digitalPins[NUM_DIGITALS] = {
 		GPIO_NO_BIT_0,
 		GPIO_NO_BIT_1,
 		GPIO_NO_BIT_2,
@@ -277,7 +280,7 @@
 }
 
 // Initialise and open the PRU
-int PRU::initialise(int pru_num, int frames_per_buffer, int spi_channels, bool xenomai_test_pin)
+int PRU::initialise(int pru_num, int frames_per_buffer, int spi_channels, int mux_channels, bool xenomai_test_pin)
 {
 	uint32_t *pruMem = 0;
 
@@ -337,6 +340,16 @@
     pru_buffer_comm[PRU_SYNC_ADDRESS] = 0;
     pru_buffer_comm[PRU_SYNC_PIN_MASK] = 0;
     pru_buffer_comm[PRU_PRU_NUMBER] = pru_number;
+	
+	if(mux_channels == 2) 
+		pru_buffer_comm[PRU_MUX_CONFIG] = 1;
+	else if(mux_channels == 4)
+		pru_buffer_comm[PRU_MUX_CONFIG] = 2;
+	else if(mux_channels == 8)
+		pru_buffer_comm[PRU_MUX_CONFIG] = 3;
+	else
+		pru_buffer_comm[PRU_MUX_CONFIG] = 0;
+	
     if(led_enabled) {
     	pru_buffer_comm[PRU_LED_ADDRESS] = USERLED3_GPIO_BASE;
     	pru_buffer_comm[PRU_LED_PIN_MASK] = USERLED3_PIN_MASK;
--- a/core/RTAudio.cpp	Wed May 18 01:46:32 2016 +0100
+++ b/core/RTAudio.cpp	Wed May 18 01:50:01 2016 +0100
@@ -98,6 +98,16 @@
 
 int BeagleRT_initAudio(BeagleRTInitSettings *settings, void *userData)
 {
+	// Sanity checks
+	if(settings->pruNumber < 0 || settings->pruNumber > 1) {
+		cout << "Invalid PRU number " << settings->pruNumber << endl;
+		return -1;
+	}
+	if(settings->pruNumber != 1 && settings->numMuxChannels != 0) {
+		cout << "Incompatible settings: multiplexer can only be run using PRU 1\n";
+		return -1;
+	}
+	
 	rt_print_auto_init(1);
 
 	BeagleRT_setVerboseLevel(settings->verbose);
@@ -202,9 +212,10 @@
 		cout << "Error: unable to prepare GPIO for PRU audio\n";
 		return 1;
 	}
-
+	
 	// Get the PRU memory buffers ready to go
-	if(gPRU->initialise(0, gContext.analogFrames, gContext.analogChannels, true)) {
+	if(gPRU->initialise(settings->pruNumber, gContext.analogFrames, gContext.analogChannels,
+		 				settings->numMuxChannels, true)) {
 		cout << "Error: unable to initialise PRU\n";
 		return 1;
 	}
--- a/core/RTAudioCommandLine.cpp	Wed May 18 01:46:32 2016 +0100
+++ b/core/RTAudioCommandLine.cpp	Wed May 18 01:50:01 2016 +0100
@@ -14,6 +14,7 @@
 #define OPT_PRU_FILE 1000
 #define OPT_PGA_GAIN_LEFT 1001
 #define OPT_PGA_GAIN_RIGHT 1002
+#define OPT_PRU_NUMBER 1003
 
 
 enum {
@@ -39,6 +40,7 @@
 	{"transmit-port", 1, NULL, 'T'},
 	{"server-name", 1, NULL, 'S'},
 	{"pru-file", 1, NULL, OPT_PRU_FILE},
+	{"pru-number", 1, NULL, OPT_PRU_NUMBER},
 	{NULL, 0, NULL, 0}
 };
 
@@ -60,8 +62,10 @@
 	for(int n = 0; n < 2; n++)
 		settings->pgaGain[n] = DEFAULT_PGA_GAIN;
 	settings->headphoneLevel = DEFAULT_HP_LEVEL;
+	settings->numMuxChannels = 0;
 
 	settings->verbose = 0;
+	settings->pruNumber = 0;
 	settings->pruFilename[0] = '\0';
 
 	// These two deliberately have no command-line flags by default.
@@ -166,8 +170,16 @@
 			break;
 		case 'C':
 			settings->numAnalogChannels = atoi(optarg);
-			if(settings->numAnalogChannels >= 8)
+			if(settings->numAnalogChannels >= 8) {
+				// Use multiplexer capelet to run larger numbers of channels
+				if(settings->numAnalogChannels >= 64)
+					settings->numMuxChannels = 8;
+				else if(settings->numAnalogChannels >= 32)
+					settings->numMuxChannels = 4;
+				else if(settings->numAnalogChannels >= 16)
+					settings->numMuxChannels = 2;
 				settings->numAnalogChannels = 8;
+			}
 			else if(settings->numAnalogChannels >= 4)
 				settings->numAnalogChannels = 4;
 			else
@@ -220,6 +232,9 @@
 		case OPT_PGA_GAIN_RIGHT:
 			settings->pgaGain[1] = atof(optarg);
 			break;
+		case OPT_PRU_NUMBER:
+			settings->pruNumber = atoi(optarg);
+			break;
 		case '?':
 		default:
 			return c;
@@ -246,6 +261,7 @@
 	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 << "   --pru-number val:                Set the PRU to use for I/O (options: 0 or 1, default: 0)\n";
 	std::cerr << "   --verbose [-v]:                  Enable verbose logging information\n";
 }
 
--- a/include/BeagleRT.h	Wed May 18 01:46:32 2016 +0100
+++ b/include/BeagleRT.h	Wed May 18 01:50:01 2016 +0100
@@ -132,7 +132,11 @@
 	float pgaGain[2];
 	/// Level for the headphone output
 	float headphoneLevel;
+	/// How many channels to use on the multiplexer capelet, if enabled
+	int numMuxChannels;
 
+	/// Which PRU (0 or 1) the code should run on
+	int pruNumber; 
 	/// 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
--- a/include/PRU.h	Wed May 18 01:46:32 2016 +0100
+++ b/include/PRU.h	Wed May 18 01:50:01 2016 +0100
@@ -36,7 +36,8 @@
 
 	// Initialise and open the PRU
 	int initialise(int pru_num, int frames_per_buffer,
-				   int spi_channels, bool xenomai_test_pin = false);
+				   int spi_channels, int mux_channels = 0, 
+				   bool xenomai_test_pin = false);
 
 	// Run the code image in pru_rtaudio_bin.h
 	int start(char * const filename);
--- a/include/pru_rtaudio_bin.h	Wed May 18 01:46:32 2016 +0100
+++ b/include/pru_rtaudio_bin.h	Wed May 18 01:50:01 2016 +0100
@@ -301,6 +301,16 @@
      0xf12c3982,
      0x5100e202,
      0x1f03f8f8,
+     0xf1303982,
+     0x6901e209,
+     0xf1343982,
+     0x1103e2e2,
+     0x5100e206,
+     0x0908e2e2,
+     0x12e2f8f8,
+     0x24ffffc2,
+     0x24ffc082,
+     0x10e2fefe,
      0xf1243982,
      0x5100e202,
      0x1f01f8f8,
@@ -634,7 +644,7 @@
      0x79000002,
      0x0b10eee7,
      0xf1c03d82,
-     0xd500e299,
+     0xd500e28f,
      0xcf05e2fe,
      0x10e7e7fb,
      0x240208fc,
@@ -659,7 +669,7 @@
      0x12e3efef,
      0x80f73c8f,
      0x0104f7f7,
-     0xc901f867,
+     0xc901f889,
      0x24ffffe2,
      0x10e2ece7,
      0x0904e7e7,
@@ -697,7 +707,7 @@
      0x4902e904,
      0x1101eafb,
      0x6900fb08,
-     0x2102b700,
+     0x2102c100,
      0x1103e1fb,
      0x6900fb05,
      0xf100269b,
@@ -758,15 +768,49 @@
      0x12e7eded,
      0x80f3388d,
      0x0104f3f3,
+     0x6903e111,
+     0x240300fc,
+     0x10fcf8fc,
+     0x5100fc0e,
+     0x0b08fcfc,
+     0x1107fefb,
+     0x0101fbfb,
+     0x1107fbfb,
+     0x5103fc04,
+     0x1103fbfb,
+     0x5102fc02,
+     0x1101fbfb,
+     0x24ffffdc,
+     0x24fff89c,
+     0x10fcfefc,
+     0x12fbfcfc,
+     0x10fcfcfe,
+     0x6907e111,
+     0x240300fc,
+     0x10fcf8fc,
+     0x5100fc0e,
+     0x0b08fcfc,
+     0x1138fefb,
+     0x0108fbfb,
+     0x1138fbfb,
+     0x5103fc04,
+     0x1118fbfb,
+     0x5102fc02,
+     0x1108fbfb,
+     0x24ffffdc,
+     0x24ffc79c,
+     0x10fcfefc,
+     0x12fbfcfc,
+     0x10fcfcfe,
      0x1504f8f8,
      0x0101e1e1,
-     0x6ee9e173,
+     0x6ee9e151,
      0x79000004,
      0x1504f8f8,
      0x0102e1e1,
-     0x6ee9e16f,
+     0x6ee9e14d,
      0x0101eaea,
-     0x6eebea6c,
+     0x6eebea4a,
      0x10f0f0e2,
      0x10f1f1f0,
      0x10e2e2f1,
@@ -795,7 +839,7 @@
      0x00e1e3e3,
      0xe1002382,
      0xf1003982,
-     0x5700e23f,
+     0x5700e21d,
      0x240000fb,
      0xe1443d9b,
      0xc901f80c,
--- a/pru_rtaudio.p	Wed May 18 01:46:32 2016 +0100
+++ b/pru_rtaudio.p	Wed May 18 01:50:01 2016 +0100
@@ -84,7 +84,9 @@
 #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 COMM_PRU_NUMBER       48          // Which PRU this code is running on
+#define COMM_MUX_CONFIG       52          // Whether to use the mux capelet, and how many channels
 
+// General constants for McASP peripherals (used for audio codec)
 #define MCASP0_BASE 0x48038000
 #define MCASP1_BASE 0x4803C000
 
@@ -184,7 +186,17 @@
 #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
+#define FLAG_BIT_USE_DIGITAL	3
+	
+#define FLAG_BIT_MUX_CONFIG0	 8		// Mux capelet configuration:
+#define FLAG_BIT_MUX_CONFIG1	 9		// 00 = off, 01 = 2 ch., 10 = 4 ch., 11 = 8 ch.
+#define FLAG_MASK_MUX_CONFIG	 0x0300
+	
+#define FLAG_BIT_MUX_STATE0	10		// Current state of the mux channels
+#define FLAG_BIT_MUX_STATE1	11
+#define FLAG_BIT_MUX_STATE2	12
+#define FLAG_MASK_MUX_STATE	0x1C00
+	
 // Registers used throughout
 
 // r1, r2, r3 are used for temporary storage
@@ -213,6 +225,7 @@
 #define reg_spi_addr		r26		// Base address for SPI
 // r27, r28 used in macros
 #define reg_mcasp_addr		r29		// Base address for McASP
+#define reg_pru1_mux_pins	r30		// Register mapped directly to P8 pins (PRU1 only)
 
 //0  P8_07 36 0x890/090 66 gpio2[2]
 //1  P8_08 37 0x894/094 67 gpio2[3]
@@ -548,7 +561,50 @@
      AND r28, r28, r27
      QBEQ POLL, r28, 0
 .endm
-   
+
+// Multiplexer Capelet: Increment channel on muxes 0-3
+.macro MUX_INCREMENT_0_TO_3
+     MOV r28, FLAG_MASK_MUX_CONFIG
+     AND r28, reg_flags, r28             // Check flags
+     QBEQ DONE, r28, 0                   // Skip if disabled
+     LSR r28, r28, FLAG_BIT_MUX_CONFIG0
+     AND r27, reg_pru1_mux_pins, 0x07    // Current mux channel in r30 bits 2-0
+     ADD r27, r27, 1            // Increment channel
+     AND r27, r27, 0x07         // Mask to 8 channels
+     QBEQ UPDATE, r28, 0x03
+     AND r27, r27, 0x03         // Mask to 4 channels
+     QBEQ UPDATE, r28, 0x02
+     AND r27, r27, 0x01         // Mask to 2 channels
+UPDATE:
+     MOV r28, 0xFFFFFFF8
+     AND r28, reg_pru1_mux_pins, r28  // Mask out low 3 bits of r30
+     OR  r28, r28, r27                // Combine with new value
+     MOV reg_pru1_mux_pins, r28       // Move back to r30 to propagate to pins
+DONE:
+.endm
+
+// Multiplexer Capelet: Increment channel on muxes 4-7
+.macro MUX_INCREMENT_4_TO_7
+     MOV r28, FLAG_MASK_MUX_CONFIG
+     AND r28, reg_flags, r28             // Check flags
+     QBEQ DONE, r28, 0                   // Skip if disabled
+     LSR r28, r28, FLAG_BIT_MUX_CONFIG0
+     AND r27, reg_pru1_mux_pins, 0x38    // Current mux channel in r30 bits 5-3
+     ADD r27, r27, 8            // Increment channel (+1 LSB starting at bit 3)
+     AND r27, r27, 0x38         // Mask to 8 channels
+     QBEQ UPDATE, r28, 0x03
+     AND r27, r27, 0x18         // Mask to 4 channels
+     QBEQ UPDATE, r28, 0x02
+     AND r27, r27, 0x08         // Mask to 2 channels
+UPDATE:
+     MOV r28, 0xFFFFFFC7
+     AND r28, reg_pru1_mux_pins, r28  // Mask out bits 5-3 of r30
+     OR  r28, r28, r27                // Combine with new value
+     MOV reg_pru1_mux_pins, r28       // Move back to r30 to propagate to pins
+DONE:
+.endm
+
+	
 START:
      // Load useful registers for addressing SPI
      MOV reg_comm_addr, SHARED_COMM_MEM_BASE
@@ -601,6 +657,22 @@
      QBGT DIGITAL_INIT_BUFFER_LOOP, r3, r4 //loop until we reach the end of the buffer
 */
 DIGITAL_INIT_DONE:
+     // Check if we should use an external multiplexer capelet
+     // The valid values are 0 (off), 1 (2 ch), 2 (4 ch), 3 (8 ch)
+     // This can only happen on PRU1 because of how the pins are mapped
+     LBBO r2, reg_comm_addr, COMM_PRU_NUMBER, 4
+     QBNE MUX_INIT_DONE, r2, 1
+     LBBO r2, reg_comm_addr, COMM_MUX_CONFIG, 4
+     AND r2, r2, 0x03
+     QBEQ MUX_INIT_DONE, r2, 0
+     // If we get here, we are using the mux. Prepare flags and initial state.
+     LSL r2, r2, FLAG_BIT_MUX_CONFIG0
+     OR  reg_flags, reg_flags, r2
+     // Clear lower 6 bits of r30 which controls the mux pins
+     MOV r2, 0xFFFFFFC0
+     AND reg_pru1_mux_pins, reg_pru1_mux_pins, r2
+MUX_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
@@ -967,6 +1039,14 @@
      SBCO reg_adc_data, C_ADC_DAC_MEM, reg_adc_current, 4
      ADD reg_adc_current, reg_adc_current, 4
 
+     // If enabled, update the multiplexer settings
+     QBNE MUX_0_3_DONE, r1, 3    // Change mux settings for ch0-3 after reading ch. 3
+     MUX_INCREMENT_0_TO_3
+MUX_0_3_DONE:
+     QBNE MUX_4_7_DONE, r1, 7    // Change mux settings for ch4-7 after reading ch. 7
+     MUX_INCREMENT_4_TO_7
+MUX_4_7_DONE:
+	
      // Toggle the high/low word for McASP control (since we send one word out of
      // 32 bits for each pair of SPI channels)
      XOR reg_flags, reg_flags, (1 << FLAG_BIT_MCASP_HWORD)
@@ -987,7 +1067,7 @@
      ADD r1, r1, 2
      QBNE ADC_DAC_LOOP, r1, reg_num_channels
 	
-ADC_DAC_LOOP_DONE:	
+ADC_DAC_LOOP_DONE:
      // Increment number of frames, see if we have more to write
      ADD reg_frame_current, reg_frame_current, 1
      QBNE WRITE_LOOP, reg_frame_current, reg_frame_total