andrewm@0: /* andrewm@0: * PRU.h andrewm@0: * andrewm@0: * Created on: May 27, 2014 andrewm@0: * Author: andrewm andrewm@0: */ andrewm@0: andrewm@0: #ifndef PRU_H_ andrewm@0: #define PRU_H_ andrewm@0: andrewm@0: #include andrewm@45: #include giuliomoro@301: #include "../include/Bela.h" andrewm@0: andrewm@307: /** andrewm@307: * Internal version of the BelaContext struct which does not have const andrewm@307: * elements, so it can be modified by the code. When it's passed to the user andrewm@307: * code, it is typecast to the standard BelaContext. andrewm@307: * andrewm@307: * Important: make sure this retains the same structure as BelaContext! andrewm@307: */ andrewm@307: typedef struct { andrewm@307: /// \brief Buffer holding audio input samples andrewm@307: /// andrewm@307: /// This buffer may be in either interleaved or non-interleaved format, andrewm@307: /// depending on the contents of the BelaInitSettings structure. andrewm@307: /// \b Note: this element is available in render() only. andrewm@307: float *audioIn; andrewm@307: andrewm@307: /// \brief Buffer holding audio output samples andrewm@307: /// andrewm@307: /// This buffer may be in either interleaved or non-interleaved format, andrewm@307: /// depending on the contents of the BelaInitSettings structure. andrewm@307: /// \b Note: this element is available in render() only. andrewm@307: float *audioOut; andrewm@307: andrewm@307: /// \brief Buffer holding analog input samples andrewm@307: /// andrewm@307: /// This buffer may be in either interleaved or non-interleaved format, andrewm@307: /// depending on the contents of the BelaInitSettings structure. andrewm@307: /// \b Note: this element is available in render() only. andrewm@307: float *analogIn; andrewm@307: andrewm@307: /// \brief Buffer holding analog output samples andrewm@307: /// andrewm@307: /// This buffer may be in either interleaved or non-interleaved format, andrewm@307: /// depending on the contents of the BelaInitSettings structure. andrewm@307: /// \b Note: this element is available in render() only. andrewm@307: float *analogOut; andrewm@307: andrewm@307: /// \brief Buffer holding digital input/output samples andrewm@307: /// andrewm@307: /// \b Note: this element is available in render() only. andrewm@307: uint32_t *digital; andrewm@307: andrewm@307: /// Number of audio frames per period andrewm@307: uint32_t audioFrames; giuliomoro@528: /// Number of input audio channels giuliomoro@528: uint32_t audioInChannels; giuliomoro@528: /// Number of output audio channels giuliomoro@528: uint32_t audioOutChannels; andrewm@307: /// Audio sample rate in Hz (currently always 44100.0) andrewm@307: float audioSampleRate; andrewm@307: andrewm@307: /// \brief Number of analog frames per period andrewm@307: /// andrewm@307: /// This will be 0 if analog I/O is disabled. andrewm@307: uint32_t analogFrames; andrewm@307: giuliomoro@528: /// \brief Number of input analog channels andrewm@307: /// giuliomoro@528: /// This will be 0 if analog I/O is disabled. giuliomoro@528: uint32_t analogInChannels; giuliomoro@528: giuliomoro@528: /// \brief Number of output analog channels giuliomoro@528: /// giuliomoro@528: /// This will be 0 if analog I/O is disabled. giuliomoro@528: uint32_t analogOutChannels; andrewm@307: andrewm@307: /// \brief Analog sample rate in Hz andrewm@307: /// andrewm@307: /// The analog sample rate depends on the number of analog channels used. If andrewm@307: /// 8 channels are used, the sample rate is 22050. If 4 channels are used, the sample andrewm@307: /// rate is 44100. If 2 channels are used, the sample rate is 88200. If analog I/O andrewm@307: /// is disabled, the sample rate is 0. andrewm@307: float analogSampleRate; andrewm@307: andrewm@307: /// Number of digital frames per period andrewm@307: uint32_t digitalFrames; andrewm@307: /// \brief Number of digital channels andrewm@307: /// andrewm@307: /// Currently this will always be 16, unless digital I/O is disabled, in which case it will be 0. andrewm@307: uint32_t digitalChannels; andrewm@307: /// Digital sample rate in Hz (currently always 44100.0) andrewm@307: float digitalSampleRate; andrewm@307: andrewm@311: /// \brief Number of elapsed audio frames since the start of rendering. andrewm@307: /// andrewm@311: /// This holds the total number of audio frames as of the beginning of the current period. To andrewm@311: /// find the current number of analog or digital frames elapsed, multiply by the ratio of the andrewm@311: /// sample rates (e.g. half the number of analog frames will have elapsed if the analog sample andrewm@307: /// rate is 22050). andrewm@311: uint64_t audioFramesElapsed; andrewm@307: andrewm@307: /// \brief Other audio/sensor settings andrewm@307: /// andrewm@307: /// Binary combination of flags including: andrewm@307: /// andrewm@307: /// BELA_FLAG_INTERLEAVED: indicates the audio and analog buffers are interleaved andrewm@307: /// andrewm@307: /// BELA_FLAG_ANALOG_OUTPUTS_PERSIST: indicates that writes to the analog outputs will andrewm@307: /// persist for future frames. If not set, writes affect one frame only. andrewm@307: uint32_t flags; andrewm@307: } InternalBelaContext; andrewm@307: andrewm@307: andrewm@0: class PRU andrewm@0: { andrewm@0: private: andrewm@0: static const unsigned int kPruGPIODACSyncPin; andrewm@0: static const unsigned int kPruGPIOADCSyncPin; andrewm@0: static const unsigned int kPruGPIOTestPin; andrewm@0: static const unsigned int kPruGPIOTestPin2; andrewm@0: static const unsigned int kPruGPIOTestPin3; andrewm@0: andrewm@0: public: andrewm@0: // Constructor andrewm@307: PRU(InternalBelaContext *input_context); andrewm@0: andrewm@0: // Destructor andrewm@0: ~PRU(); andrewm@0: andrewm@0: // Prepare the GPIO pins needed for the PRU andrewm@45: int prepareGPIO(int include_test_pin, int include_led); andrewm@0: andrewm@0: // Clean up the GPIO at the end andrewm@0: void cleanupGPIO(); andrewm@0: andrewm@0: // Initialise and open the PRU andrewm@45: int initialise(int pru_num, int frames_per_buffer, andrewm@280: int spi_channels, int mux_channels = 0, andrewm@280: bool xenomai_test_pin = false); andrewm@0: andrewm@15: // Run the code image in pru_rtaudio_bin.h giuliomoro@16: int start(char * const filename); andrewm@0: andrewm@0: // Loop: read and write data from the PRU andrewm@45: void loop(RT_INTR *pru_interrupt, void *userData); andrewm@0: andrewm@0: // Wait for an interrupt from the PRU indicate it is finished andrewm@0: void waitForFinish(); andrewm@0: andrewm@0: // Turn off the PRU when done andrewm@0: void disable(); andrewm@0: andrewm@0: // For debugging: andrewm@0: void setGPIOTestPin(); andrewm@0: void clearGPIOTestPin(); andrewm@0: andrewm@0: private: andrewm@307: InternalBelaContext *context; // Overall settings andrewm@45: andrewm@0: int pru_number; // Which PRU we use andrewm@0: bool running; // Whether the PRU is running andrewm@45: bool analog_enabled; // Whether SPI ADC and DAC are used giuliomoro@19: bool digital_enabled; // Whether digital is used andrewm@0: bool gpio_enabled; // Whether GPIO has been prepared andrewm@0: bool led_enabled; // Whether a user LED is enabled andrewm@303: int mux_channels; // How many mux channels are used (if enabled) andrewm@0: bool gpio_test_pin_enabled; // Whether the test pin was also enabled andrewm@0: andrewm@303: andrewm@0: volatile uint32_t *pru_buffer_comm; andrewm@0: uint16_t *pru_buffer_spi_dac; andrewm@0: uint16_t *pru_buffer_spi_adc; giuliomoro@19: uint32_t *pru_buffer_digital; andrewm@0: int16_t *pru_buffer_audio_dac; andrewm@0: int16_t *pru_buffer_audio_adc; andrewm@0: andrewm@81: float *last_analog_out_frame; andrewm@81: uint32_t *digital_buffer0, *digital_buffer1, *last_digital_buffer; andrewm@81: andrewm@0: int xenomai_gpio_fd; // File descriptor for /dev/mem for fast GPIO andrewm@0: uint32_t *xenomai_gpio; // Pointer to GPIO registers andrewm@0: }; andrewm@0: andrewm@0: andrewm@0: #endif /* PRU_H_ */