Mercurial > hg > beaglert
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