Mercurial > hg > beaglert
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++) { |