comparison 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
comparison
equal deleted inserted replaced
11:517715b23df0 12:a6beeba3a648
48 #define PRU_SYNC_PIN_MASK 5 48 #define PRU_SYNC_PIN_MASK 5
49 #define PRU_LED_ADDRESS 6 49 #define PRU_LED_ADDRESS 6
50 #define PRU_LED_PIN_MASK 7 50 #define PRU_LED_PIN_MASK 7
51 #define PRU_FRAME_COUNT 8 51 #define PRU_FRAME_COUNT 8
52 #define PRU_USE_SPI 9 52 #define PRU_USE_SPI 9
53 53 #define PRU_SPI_NUM_CHANNELS 10
54 #define PRU_SAMPLE_INTERVAL_NS 45351 // 22050Hz per SPI sample = 45.351us 54
55 #define PRU_SAMPLE_INTERVAL_NS 11338 // 88200Hz per SPI sample = 11.338us
55 56
56 #define GPIO0_ADDRESS 0x44E07000 57 #define GPIO0_ADDRESS 0x44E07000
57 #define GPIO1_ADDRESS 0x4804C000 58 #define GPIO1_ADDRESS 0x4804C000
58 #define GPIO_SIZE 0x198 59 #define GPIO_SIZE 0x198
59 #define GPIO_CLEARDATAOUT (0x190 / 4) 60 #define GPIO_CLEARDATAOUT (0x190 / 4)
77 extern int gRTAudioVerbose; 78 extern int gRTAudioVerbose;
78 79
79 // Constructor: specify a PRU number (0 or 1) 80 // Constructor: specify a PRU number (0 or 1)
80 PRU::PRU() 81 PRU::PRU()
81 : pru_number(0), running(false), spi_enabled(false), gpio_enabled(false), led_enabled(false), 82 : pru_number(0), running(false), spi_enabled(false), gpio_enabled(false), led_enabled(false),
82 gpio_test_pin_enabled(false), xenomai_gpio_fd(-1), xenomai_gpio(0) 83 gpio_test_pin_enabled(false), spi_num_channels(0), xenomai_gpio_fd(-1), xenomai_gpio(0)
83 { 84 {
84 85
85 } 86 }
86 87
87 // Destructor 88 // Destructor
222 223
223 gpio_enabled = gpio_test_pin_enabled = false; 224 gpio_enabled = gpio_test_pin_enabled = false;
224 } 225 }
225 226
226 // Initialise and open the PRU 227 // Initialise and open the PRU
227 int PRU::initialise(int pru_num, int frames_per_buffer, bool xenomai_test_pin) 228 int PRU::initialise(int pru_num, int frames_per_buffer, int spi_channels, bool xenomai_test_pin)
228 { 229 {
229 uint32_t *pruMem = 0; 230 uint32_t *pruMem = 0;
230 231
231 if(!gpio_enabled) { 232 if(!gpio_enabled) {
232 rt_printf("initialise() called before GPIO enabled\n"); 233 rt_printf("initialise() called before GPIO enabled\n");
233 return 1; 234 return 1;
234 } 235 }
235 236
236 pru_number = pru_num; 237 pru_number = pru_num;
238
239 /* Set number of SPI ADC / DAC channels to use. This implicitly
240 * also determines the sample rate relative to the audio clock
241 * (half audio clock for 8 channels, full audio clock for 4,
242 * double audio clock for 2)
243 */
244 spi_num_channels = spi_channels;
237 245
238 /* Initialize structure used by prussdrv_pruintc_intc */ 246 /* Initialize structure used by prussdrv_pruintc_intc */
239 /* PRUSS_INTC_INITDATA is found in pruss_intc_mapping.h */ 247 /* PRUSS_INTC_INITDATA is found in pruss_intc_mapping.h */
240 tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA; 248 tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;
241 249
248 256
249 /* Map PRU's INTC */ 257 /* Map PRU's INTC */
250 prussdrv_pruintc_init(&pruss_intc_initdata); 258 prussdrv_pruintc_init(&pruss_intc_initdata);
251 259
252 spi_buffer_frames = frames_per_buffer; 260 spi_buffer_frames = frames_per_buffer;
253 audio_buffer_frames = spi_buffer_frames * 2; 261 audio_buffer_frames = spi_buffer_frames * spi_num_channels / 4;
254 262
255 /* Map PRU memory to pointers */ 263 /* Map PRU memory to pointers */
256 prussdrv_map_prumem (PRUSS0_SHARED_DATARAM, (void **)&pruMem); 264 prussdrv_map_prumem (PRUSS0_SHARED_DATARAM, (void **)&pruMem);
257 pru_buffer_comm = (uint32_t *)&pruMem[PRU_MEM_COMM_OFFSET/sizeof(uint32_t)]; 265 pru_buffer_comm = (uint32_t *)&pruMem[PRU_MEM_COMM_OFFSET/sizeof(uint32_t)];
258 pru_buffer_audio_dac = (int16_t *)&pruMem[PRU_MEM_MCASP_OFFSET/sizeof(uint32_t)]; 266 pru_buffer_audio_dac = (int16_t *)&pruMem[PRU_MEM_MCASP_OFFSET/sizeof(uint32_t)];
259 267
260 /* ADC memory starts 2(ch)*2(buffers)*2(samples/spi)*bufsize samples later */ 268 /* ADC memory starts 2(ch)*2(buffers)*bufsize samples later */
261 pru_buffer_audio_adc = &pru_buffer_audio_dac[8 * spi_buffer_frames]; 269 pru_buffer_audio_adc = &pru_buffer_audio_dac[4 * audio_buffer_frames];
262 270
263 if(spi_enabled) { 271 if(spi_enabled) {
264 prussdrv_map_prumem (pru_number == 0 ? PRUSS0_PRU0_DATARAM : PRUSS0_PRU1_DATARAM, (void **)&pruMem); 272 prussdrv_map_prumem (pru_number == 0 ? PRUSS0_PRU0_DATARAM : PRUSS0_PRU1_DATARAM, (void **)&pruMem);
265 pru_buffer_spi_dac = (uint16_t *)&pruMem[PRU_MEM_DAC_OFFSET/sizeof(uint32_t)]; 273 pru_buffer_spi_dac = (uint16_t *)&pruMem[PRU_MEM_DAC_OFFSET/sizeof(uint32_t)];
266 274
267 /* ADC memory starts after 8(ch)*2(buffers)*bufsize samples */ 275 /* ADC memory starts after N(ch)*2(buffers)*bufsize samples */
268 pru_buffer_spi_adc = &pru_buffer_spi_dac[16 * spi_buffer_frames]; 276 pru_buffer_spi_adc = &pru_buffer_spi_dac[2 * spi_num_channels * spi_buffer_frames];
269 } 277 }
270 else { 278 else {
271 pru_buffer_spi_dac = pru_buffer_spi_adc = 0; 279 pru_buffer_spi_dac = pru_buffer_spi_adc = 0;
272 } 280 }
273 281
286 pru_buffer_comm[PRU_LED_ADDRESS] = 0; 294 pru_buffer_comm[PRU_LED_ADDRESS] = 0;
287 pru_buffer_comm[PRU_LED_PIN_MASK] = 0; 295 pru_buffer_comm[PRU_LED_PIN_MASK] = 0;
288 } 296 }
289 if(spi_enabled) { 297 if(spi_enabled) {
290 pru_buffer_comm[PRU_USE_SPI] = 1; 298 pru_buffer_comm[PRU_USE_SPI] = 1;
299 pru_buffer_comm[PRU_SPI_NUM_CHANNELS] = spi_num_channels;
291 } 300 }
292 else { 301 else {
293 pru_buffer_comm[PRU_USE_SPI] = 0; 302 pru_buffer_comm[PRU_USE_SPI] = 0;
303 pru_buffer_comm[PRU_SPI_NUM_CHANNELS] = 0;
294 } 304 }
295 305
296 /* Clear ADC and DAC memory */ 306 /* Clear ADC and DAC memory */
297 if(spi_enabled) { 307 if(spi_enabled) {
298 for(int i = 0; i < PRU_MEM_DAC_LENGTH / 2; i++) 308 for(int i = 0; i < PRU_MEM_DAC_LENGTH / 2; i++)
338 348
339 // Main loop to read and write data from/to PRU 349 // Main loop to read and write data from/to PRU
340 void PRU::loop() 350 void PRU::loop()
341 { 351 {
342 // Polling interval is 1/4 of the period 352 // Polling interval is 1/4 of the period
343 RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * spi_buffer_frames / 4; 353 RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * (spi_num_channels / 2) * spi_buffer_frames / 4;
344 float *audioInBuffer, *audioOutBuffer; 354 float *audioInBuffer, *audioOutBuffer;
345 355
346 audioInBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float)); 356 audioInBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float));
347 audioOutBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float)); 357 audioOutBuffer = (float *)malloc(2 * audio_buffer_frames * sizeof(float));
348 358
408 for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++) 418 for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++)
409 audioInBuffer[n] = (float)pru_buffer_audio_adc[n + audio_buffer_frames * 2] / 32768.0; 419 audioInBuffer[n] = (float)pru_buffer_audio_adc[n + audio_buffer_frames * 2] / 32768.0;
410 420
411 if(spi_enabled) 421 if(spi_enabled)
412 render(spi_buffer_frames, audio_buffer_frames, audioInBuffer, audioOutBuffer, 422 render(spi_buffer_frames, audio_buffer_frames, audioInBuffer, audioOutBuffer,
413 &pru_buffer_spi_adc[spi_buffer_frames * 8], &pru_buffer_spi_dac[spi_buffer_frames * 8]); 423 &pru_buffer_spi_adc[spi_buffer_frames * spi_num_channels], &pru_buffer_spi_dac[spi_buffer_frames * spi_num_channels]);
414 else 424 else
415 render(0, audio_buffer_frames, audioInBuffer, audioOutBuffer, 0, 0); 425 render(0, audio_buffer_frames, audioInBuffer, audioOutBuffer, 0, 0);
416 426
417 // Convert float back to short 427 // Convert float back to short
418 for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++) { 428 for(unsigned int n = 0; n < 2 * audio_buffer_frames; n++) {