Exemplo n.º 1
0
void  aic23b_dac_mute(bool mute)
{
#if (AIC23B_MODE==AIC23B_MODE_DAC)
/*  if(mute==true) {
    pdca_disable(AIC23B_SSC_TX_PDCA_CHANNEL);
  }
  else {
       pdca_enable(AIC23B_SSC_TX_PDCA_CHANNEL);
  }
*/
  if (mute)
  {
    uint32_t save_dac_reload_callback_opt;

    // Disable the reload callback function
    save_dac_reload_callback_opt = aic23b_output_params.callback_opt;
    aic23b_output_params.callback_opt = 0;
    // Disable the transfer complete interruption and wait until the transfer is complete
    pdca_disable_interrupt_reload_counter_zero(AIC23B_SSC_TX_PDCA_CHANNEL);
    while (!(pdca_get_transfer_status(AIC23B_SSC_TX_PDCA_CHANNEL) & PDCA_TRANSFER_COMPLETE));
    // Re-enable the reload callback function
    aic23b_output_params.callback_opt = save_dac_reload_callback_opt;
  }
  else
  {
    // Re-enable the reload interrupt
    pdca_enable_interrupt_reload_counter_zero(AIC23B_SSC_TX_PDCA_CHANNEL);
  }

#endif
}
Exemplo n.º 2
0
Arquivo: ms3.c Projeto: avrxml/asf
void ms3_dac_mute(bool mute)
{
	if (mute) {
		U32 save_dac_reload_callback_opt;

		// Mute all channels
		// ms3_write_reg(MS3_MUTE_VOL_CTRL, 0xAF);

		// Disable the reload callback function
		save_dac_reload_callback_opt = ms3_output_params.callback_opt;
		ms3_output_params.callback_opt = 0;
		// Disable the transfer complete interruption and wait until the transfer is complete
		pdca_disable_interrupt_reload_counter_zero(MS3_SSC_TX_PDCA_CHANNEL);
		while (!(pdca_get_transfer_status(MS3_SSC_TX_PDCA_CHANNEL) & PDCA_TRANSFER_COMPLETE));
		// Re-enable the reload callback function
		ms3_output_params.callback_opt = save_dac_reload_callback_opt;
		// Set as gpio pin
		gpio_enable_gpio(MS3_GPIO_MAP, sizeof(MS3_GPIO_MAP) / sizeof(MS3_GPIO_MAP[0]));
	}
	else {
		// Re-enable the reload interrupt
		pdca_enable_interrupt_reload_counter_zero(MS3_SSC_TX_PDCA_CHANNEL);
		// Unmute all channels
		// ms3_write_reg(MS3_MUTE_VOL_CTRL, 0xA0);
		// Enable SSC interface
		gpio_enable_module(MS3_GPIO_MAP, sizeof(MS3_GPIO_MAP) / sizeof(MS3_GPIO_MAP[0]));
	}
}
Exemplo n.º 3
0
bool aic23b_adc_input(void *sample_buffer, size_t sample_length)
{
  if (!(pdca_get_transfer_status(AIC23B_SSC_RX_PDCA_CHANNEL) &
        PDCA_TRANSFER_COUNTER_RELOAD_IS_ZERO))
    return false;

  if (sample_length)
  {
    pdca_reload_channel(AIC23B_SSC_RX_PDCA_CHANNEL, sample_buffer, sample_length * 2);
    pdca_get_reload_size(AIC23B_SSC_RX_PDCA_CHANNEL);

    if (aic23b_output_params.callback_opt & AUDIO_ADC_OUT_OF_SAMPLE_CB)
      pdca_enable_interrupt_transfer_complete(AIC23B_SSC_RX_PDCA_CHANNEL);
    if (aic23b_output_params.callback_opt & AUDIO_ADC_RELOAD_CB)
      pdca_enable_interrupt_reload_counter_zero(AIC23B_SSC_RX_PDCA_CHANNEL);
  }

  return true;
}
Exemplo n.º 4
0
void aic23b_dac_start(uint32_t sample_rate_hz,
                      uint8_t num_channels,
                      uint8_t bits_per_sample,
                      bool swap_channels,
                      void (*callback)(uint32_t arg),
                      uint32_t callback_opt,
                      uint32_t pba_hz)
{
#if AIC23B_CTRL_INTERFACE == AIC23B_CTRL_INTERFACE_SPI
  static const spi_options_t AIC23B_SPI_OPTIONS =
  {
    .reg          = AIC23B_SPI_NPCS,
    .baudrate     = AIC23B_SPI_MASTER_SPEED,
    .bits         = AIC23B_CTRL_SIZE,
    .spck_delay   = 0,
    .trans_delay  = 0,
    .stay_act     = 0,
    .spi_mode     = 3,
    .modfdis      = 1
  };
  spi_setupChipReg(AIC23B_SPI, &AIC23B_SPI_OPTIONS, pba_hz);
#endif

  aic23b_dac_stop();

  gpio_enable_module(AIC23B_SSC_DAC_GPIO_MAP,
                     sizeof(AIC23B_SSC_DAC_GPIO_MAP) / sizeof(AIC23B_SSC_DAC_GPIO_MAP[0]));

  aic23b_pdc_t pdc;
  pdc.data  = AIC23B_DEFAULT(AIC23B_PDC);
  pdc.off   = 0;
  pdc.clk   = 0;
  pdc.osc   = 0;
  pdc.out   = 0;
  pdc.dac   = 0;
  pdc.adc   = 1;
  pdc.mic   = 1;
  pdc.line  = 1;
  aic23b_set_power_down_state(pdc);

  aic23b_dac_setup(sample_rate_hz,
                   num_channels,
                   bits_per_sample,
                   swap_channels,
                   callback,
                   callback_opt,
                   pba_hz);

  aic23b_aapc_t aapc;
  aapc.data = AIC23B_DEFAULT(AIC23B_AAPC);
  aapc.ste  = 0;
  aapc.dac  = 1;
  aapc.byp  = 0;
  aapc.micm = 1;
  aapc.micb = 0;
  aic23b_set_analog_audio_path(aapc);

  aic23b_dapc_t dapc;
  dapc.data   = AIC23B_DEFAULT(AIC23B_DAPC);
  dapc.dacm   = 0;
  dapc.deemp  = AIC23B_DAPC_DEEMP_NONE;
  dapc.adchp  = 1;
  aic23b_set_digital_audio_path(dapc);

  // set an acceptable start volume
  aic23b_set_headphone_volume(AIC23B_LEFT_CHANNEL | AIC23B_RIGHT_CHANNEL,
                              -30,
                              true);

  aic23b_activate_dig_audio(true);

  INTC_register_interrupt(&aic23b_ssc_tx_pdca_int_handler,
                          AIC23B_SSC_TX_PDCA_IRQ,
                          AIC23B_SSC_TX_PDCA_INT_LEVEL);
}


void aic23b_dac_setup(uint32_t sample_rate_hz,
                      uint8_t num_channels,
                      uint8_t bits_per_sample,
                      bool swap_channels,
                      void (*callback)(uint32_t arg),
                      uint32_t callback_opt,
                      uint32_t pba_hz)
{
#if defined(AIC23B_DAC_USE_RX_CLOCK) && AIC23B_DAC_USE_RX_CLOCK == true
  #if defined(AIC23B_DAC_RX_CLOCK_SET_CALLBACK)
    AIC23B_DAC_RX_CLOCK_SET_CALLBACK(2 * sample_rate_hz *
                                     ((bits_per_sample <= 16) ? 16 :
                                     (bits_per_sample <= 20) ? 20 :
                                     (bits_per_sample <= 24) ? 24 :
                                     32));
  #endif
  ssc_i2s_init(AIC23B_SSC,
               sample_rate_hz,
               bits_per_sample,
               (bits_per_sample <= 16) ? 16 :
               (bits_per_sample <= 20) ? 20 :
               (bits_per_sample <= 24) ? 24 :
                                         32,
               SSC_I2S_MODE_STEREO_OUT_EXT_CLK,
               pba_hz);
#else
  ssc_i2s_init(AIC23B_SSC,
               sample_rate_hz,
               bits_per_sample,
               (bits_per_sample <= 16) ? 16 :
               (bits_per_sample <= 20) ? 20 :
               (bits_per_sample <= 24) ? 24 :
                                         32,
               SSC_I2S_MODE_STEREO_OUT,
               pba_hz);
#endif

  pdca_channel_options_t aic23b_ssc_pdca_options =
  {
    .addr           = NULL,
    .size           = 0,
    .r_addr         = NULL,
    .r_size         = 0,
    .pid            = AIC23B_SSC_TX_PDCA_PID,
    .transfer_size  = (bits_per_sample <=  8) ? PDCA_TRANSFER_SIZE_BYTE      :
                      (bits_per_sample <= 16) ? PDCA_TRANSFER_SIZE_HALF_WORD :
                                                PDCA_TRANSFER_SIZE_WORD
  };
  pdca_init_channel(AIC23B_SSC_TX_PDCA_CHANNEL, &aic23b_ssc_pdca_options);
  pdca_enable(AIC23B_SSC_TX_PDCA_CHANNEL);

#if !defined(AIC23B_DAC_USE_RX_CLOCK) || AIC23B_DAC_USE_RX_CLOCK == false || \
    !defined(AIC23B_DAC_RX_CLOCK_SET_CALLBACK)
  // Set DAC frequency
  aic23b_configure_freq(AIC23B_MCLK_HZ, sample_rate_hz);
#endif

  aic23b_daif_t daif;
  daif.data   = AIC23B_DEFAULT(AIC23B_DAIF);
  daif.ms     = AIC23B_DAIF_MS_SLAVE;
  daif.lrswap = swap_channels;
  daif.lrp    = 0;
  daif.iwl    = (bits_per_sample <= 16) ? AIC23B_DAIF_IWL_16 :
                (bits_per_sample <= 20) ? AIC23B_DAIF_IWL_20 :
                (bits_per_sample <= 24) ? AIC23B_DAIF_IWL_24 :
                                          AIC23B_DAIF_IWL_32;
  daif.fmt    = AIC23B_DAIF_FMT_I2S;
  aic23b_write_reg(AIC23B_DAIF, daif.data);

  aic23b_output_params.num_channels             = num_channels;
  aic23b_output_params.callback                 = callback;
  aic23b_output_params.callback_opt             = callback_opt;
}
#endif

bool aic23b_dac_output(void *sample_buffer, size_t sample_length)
{
  bool global_interrupt_enabled;

  if (!(pdca_get_transfer_status(AIC23B_SSC_TX_PDCA_CHANNEL) &
        PDCA_TRANSFER_COUNTER_RELOAD_IS_ZERO))
    return false;

  if (sample_length)
  {
    if (aic23b_output_params.num_channels == 1)
    {
      int16_t *s16_sample_buffer = sample_buffer;
      int i;

      for (i = sample_length - 1; i >= 0; i--)
      {
        s16_sample_buffer[2 * i + 1] =
        s16_sample_buffer[2 * i]     = s16_sample_buffer[i];
      }
    }

    // The PDCA is not able to synchronize its start of transfer with the SSC
    // start of period, so this has to be done by polling the TF pin.
    // Not doing so may result in channels being swapped randomly.
    if ((global_interrupt_enabled = Is_global_interrupt_enabled()))
      Disable_global_interrupt();
    if (pdca_get_transfer_status(AIC23B_SSC_TX_PDCA_CHANNEL) &
        PDCA_TRANSFER_COMPLETE)
    {
      while (gpio_get_pin_value(AIC23B_SSC_TX_FRAME_SYNC_PIN));
      while (!gpio_get_pin_value(AIC23B_SSC_TX_FRAME_SYNC_PIN));
    }
    pdca_reload_channel(AIC23B_SSC_TX_PDCA_CHANNEL, sample_buffer, sample_length * 2);
    pdca_get_reload_size(AIC23B_SSC_TX_PDCA_CHANNEL);
    if (global_interrupt_enabled)
      Enable_global_interrupt();

    if (aic23b_output_params.callback_opt & AUDIO_DAC_OUT_OF_SAMPLE_CB)
      pdca_enable_interrupt_transfer_complete(AIC23B_SSC_TX_PDCA_CHANNEL);
    if (aic23b_output_params.callback_opt & AUDIO_DAC_RELOAD_CB)
      pdca_enable_interrupt_reload_counter_zero(AIC23B_SSC_TX_PDCA_CHANNEL);
  }
  return true;
}
Exemplo n.º 5
0
//!
//! @brief Entry point of the AK5394A task management
//!
void AK5394A_task(void *pvParameters)
{
  portTickType xLastWakeTime;
  xLastWakeTime = xTaskGetTickCount();
  int i;

  while (TRUE)
  {
	  // All the hardwork is done by the pdca and the interrupt handler.
	  // Just check whether sampling freq is changed, to do rate change etc.

    vTaskDelayUntil(&xLastWakeTime, configTSK_AK5394A_PERIOD);


    if (freq_changed){


    	if (current_freq.frequency == 96000){
	   	pdca_disable_interrupt_reload_counter_zero(PDCA_CHANNEL_SSC_RX);
	    pdca_disable(PDCA_CHANNEL_SSC_RX);

    		gpio_set_gpio_pin(AK5394_DFS0);		// L H  -> 96khz
    		gpio_clr_gpio_pin(AK5394_DFS1);

    		pm_gc_disable(&AVR32_PM, AVR32_PM_GCLK_GCLK1);
    		pm_gc_setup(&AVR32_PM, AVR32_PM_GCLK_GCLK1, // gc
    						  0,                  // osc_or_pll: use Osc (if 0) or PLL (if 1)
    						  1,                  // pll_osc: select Osc0/PLL0 or Osc1/PLL1
    						  1,                  // diven - enabled
    						  0);                 // divided by 2.  Therefore GCLK1 = 6.144Mhz
    		pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_GCLK1);

    	   	if (Is_usb_full_speed_mode()) FB_rate = 96 << 14;
    	    	else FB_rate = (96) << 13;

    	}
    	else if (current_freq.frequency == 192000)
    	{
    	pdca_disable_interrupt_reload_counter_zero(PDCA_CHANNEL_SSC_RX);
        pdca_disable(PDCA_CHANNEL_SSC_RX);

				gpio_clr_gpio_pin(AK5394_DFS0);		// H L -> 192khz
        		gpio_set_gpio_pin(AK5394_DFS1);

           		pm_gc_disable(&AVR32_PM, AVR32_PM_GCLK_GCLK1);
            	pm_gc_setup(&AVR32_PM, AVR32_PM_GCLK_GCLK1, // gc
            						  0,                  // osc_or_pll: use Osc (if 0) or PLL (if 1)
            						  1,                  // pll_osc: select Osc0/PLL0 or Osc1/PLL1
            						  0,                  // diven - disabled
            						  0);                 // GCLK1 = 12.288Mhz
            	pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_GCLK1);

              	if (Is_usb_full_speed_mode()) FB_rate = 192 << 14;
                	else FB_rate = (192) << 13;

    	}
    	else if (current_freq.frequency == 48000) // 48khz
    	{

        	pdca_disable_interrupt_reload_counter_zero(PDCA_CHANNEL_SSC_RX);
            pdca_disable(PDCA_CHANNEL_SSC_RX);

				gpio_clr_gpio_pin(AK5394_DFS0);		// L L  -> 48khz
        		gpio_clr_gpio_pin(AK5394_DFS1);

           		pm_gc_disable(&AVR32_PM, AVR32_PM_GCLK_GCLK1);
            	pm_gc_setup(&AVR32_PM, AVR32_PM_GCLK_GCLK1, // gc
            						  0,                  // osc_or_pll: use Osc (if 0) or PLL (if 1)
            						  1,                  // pll_osc: select Osc0/PLL0 or Osc1/PLL1
            						  1,                  // diven - enabled
            						  1);                 // divided by 4.  Therefore GCLK1 = 3.072Mhz
            	pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_GCLK1);

            	if (Is_usb_full_speed_mode()) FB_rate = 48 << 14;
                	else FB_rate = (48) << 13;


        }

    	// re-sync SSC to LRCK
        // Wait for the next frame synchronization event
        // to avoid channel inversion.  Start with left channel - FS goes low
    	// However, the channels are reversed at 192khz

    	if (current_freq.frequency == 192000) {
			while (gpio_get_pin_value(AK5394_LRCK));
			while (!gpio_get_pin_value(AK5394_LRCK));	// exit when FS goes high
    	}
    	else {
			while (!gpio_get_pin_value(AK5394_LRCK));
			while (gpio_get_pin_value(AK5394_LRCK));	// exit when FS goes low
    	}
        // Enable now the transfer.
        pdca_enable(PDCA_CHANNEL_SSC_RX);

        // Init PDCA channel with the pdca_options.
        pdca_init_channel(PDCA_CHANNEL_SSC_RX, &PDCA_OPTIONS); // init PDCA channel with options.
        pdca_enable_interrupt_reload_counter_zero(PDCA_CHANNEL_SSC_RX);

        // reset freq_changed flag
        freq_changed = FALSE;
    }
    if (usb_alternate_setting_out_changed){
    	if (usb_alternate_setting_out != 1){
    		for (i = 0; i < SPK_BUFFER_SIZE; i++){
    			spk_buffer_0[i] = 0;
    			spk_buffer_1[i] = 0;
    		}
    	};

    	usb_alternate_setting_out_changed = FALSE;
    }
  }
}
Exemplo n.º 6
0
//!
//! @brief This function initializes the hardware/software resources
//! required for device CDC task.
//!
void AK5394A_task_init(void)
{
	// Set up CS4344
	// Set up GLCK1 to provide master clock for CS4344
	gpio_enable_module_pin(GCLK1, GCLK1_FUNCTION);	// for DA_SCLK
													// LRCK is SCLK / 64 generated by TX_SSC
													// so SCLK of 6.144Mhz ===> 96khz

	pm_gc_setup(&AVR32_PM, AVR32_PM_GCLK_GCLK1, // gc
					  0,                  // osc_or_pll: use Osc (if 0) or PLL (if 1)
					  1,                  // pll_osc: select Osc0/PLL0 or Osc1/PLL1
					  1,                  // diven - enabled
					  0);                 // divided by 2.  Therefore GCLK1 = 6.144Mhz
	pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_GCLK1);

	pm_enable_osc1_ext_clock(&AVR32_PM);	// OSC1 is clocked by 12.288Mhz Osc
												// from AK5394A Xtal Oscillator
	pm_enable_clk1(&AVR32_PM, OSC1_STARTUP);

	// Set up AK5394A
	gpio_clr_gpio_pin(AK5394_RSTN);		// put AK5394A in reset
	gpio_clr_gpio_pin(AK5394_DFS0);		// L L  -> 48khz
	gpio_clr_gpio_pin(AK5394_DFS1);
	gpio_set_gpio_pin(AK5394_HPFE);		// enable HP filter
	gpio_clr_gpio_pin(AK5394_ZCAL);		// use VCOML and VCOMR to cal
	gpio_set_gpio_pin(AK5394_SMODE1);	// SMODE1 = H for Master i2s
	gpio_set_gpio_pin(AK5394_SMODE2);	// SMODE2 = H for Master/Slave i2s

    gpio_set_gpio_pin(AK5394_RSTN);		// start AK5394A
    while (gpio_get_pin_value(AK5394_CAL)); // wait till CAL goes low

		// Assign GPIO to SSC.
	  gpio_enable_module(SSC_GPIO_MAP, sizeof(SSC_GPIO_MAP) / sizeof(SSC_GPIO_MAP[0]));
	  gpio_enable_pin_glitch_filter(SSC_RX_CLOCK);
	  gpio_enable_pin_glitch_filter(SSC_RX_DATA);
	  gpio_enable_pin_glitch_filter(SSC_RX_FRAME_SYNC);
	  gpio_enable_pin_glitch_filter(SSC_TX_CLOCK);
	  gpio_enable_pin_glitch_filter(SSC_TX_DATA);
	  gpio_enable_pin_glitch_filter(SSC_TX_FRAME_SYNC);

	  current_freq.frequency = 96000;

	  // set up SSC
	  ssc_i2s_init(ssc, 96000, 24, 32, SSC_I2S_MODE_STEREO_OUT_STEREO_IN, FPBA_HZ);

	  // set up PDCA
	  // In order to avoid long slave handling during undefined length bursts (INCR), the Bus Matrix
	  // provides specific logic in order to re-arbitrate before the end of the INCR transfer.
	  //
	  // HSB Bus Matrix: By default the HSB bus matrix mode is in Undefined length burst type (INCR).
	  // Here we have to put in single access (the undefined length burst is treated as a succession of single
	  // accesses, allowing re-arbitration at each beat of the INCR burst.
	  // Refer to the HSB bus matrix section of the datasheet for more details.
	  //
	  // HSB Bus matrix register MCFG1 is associated with the CPU instruction master interface.
	  AVR32_HMATRIX.mcfg[AVR32_HMATRIX_MASTER_CPU_INSN] = 0x1;

	  audio_buffer_in = 0;
	  spk_buffer_out = 0;
	  // Register PDCA IRQ interrupt.
	  pdca_set_irq();

	  // Init PDCA channel with the pdca_options.
	  pdca_init_channel(PDCA_CHANNEL_SSC_RX, &PDCA_OPTIONS); // init PDCA channel with options.
      pdca_enable_interrupt_reload_counter_zero(PDCA_CHANNEL_SSC_RX);
      pdca_init_channel(PDCA_CHANNEL_SSC_TX, &SPK_PDCA_OPTIONS); // init PDCA channel with options.
       pdca_enable_interrupt_reload_counter_zero(PDCA_CHANNEL_SSC_TX);

       //////////////////////////////////////////////
       // Enable now the transfer.
       pdca_enable(PDCA_CHANNEL_SSC_TX);


	  xTaskCreate(AK5394A_task,
              configTSK_AK5394A_NAME,
              configTSK_AK5394A_STACK_SIZE,
              NULL,
              configTSK_AK5394A_PRIORITY,
              NULL);

}
Exemplo n.º 7
0
/*! \brief Sets the DACs up with new settings.
 *
 * \note The DACs must have been started beforehand.
 */
void tpa6130_dac_setup(uint32_t sample_rate_hz,
                       uint8_t num_channels,
                       uint8_t bits_per_sample,
                       bool swap_channels,
                       void (*callback)(uint32_t arg),
                       uint32_t callback_opt,
                       uint32_t pba_hz)
{
  // save input parameters to local driver data
  tpa6130_output_param.num_channels = num_channels;
  tpa6130_output_param.callback     = callback;
  tpa6130_output_param.callback_opt = callback_opt;

  /* Probe for amplifier and initialize it */
  tpa6130_init();

#if defined(TPA6130_DAC_CLOCK_SET_CALLBACK)
  TPA6130_DAC_CLOCK_SET_CALLBACK(sample_rate_hz);
#else
  /* ABDAC configuration
   * The ABDAC needs the input frequency of its generic clock (bus_hz)
   * Here we use the configuration value from the conf_tpa6130.h file
   * (TPA6130_ABDAC_GCLK_INPUT_HZ).
   * The sample rate specifies the desired sample rate for the ABDAC.
   * The generic clock input must be greater than 256*sample_rate_hz
   * or the setup of the ABDAC will fail silently here.
   * TODO we could add asserts here to detect wrong settings during
   * compile time.
   */
  if(!abdac_set_dac_sample_rate(sample_rate_hz)) {
    // if it is not possible to set correctly the sample rate
    // Use default set function
    abdac_set_dac_hz(TPA6130_ABDAC, TPA6130_ABDAC_GCLK_INPUT_HZ,sample_rate_hz);
  }
#endif

  if(swap_channels)
  {
    abdac_swap_channels(TPA6130_ABDAC);
  }
  abdac_enable(TPA6130_ABDAC);

  /* PDCA setup */
  /*FIXME we use only word as transfer size for now.
   * half-word transfer size will only write to channel0
   * of the ABDAC, this can be used to implement mono */
  pdca_channel_options_t tpa6130_abdac_pdca_options =
  {
    .addr   = NULL,
    .size   = 0,
    .r_addr   = 0,
    .r_size   = 0,
    .pid    = TPA6130_ABDAC_PDCA_PID,
    .transfer_size  = PDCA_TRANSFER_SIZE_WORD
  };

  /* Initialize the PCDA for the ABDAC
   * The channel number can be set in the configuration file
   * with the define TPA6130_ABDAC_PDCA_CHANNEL.
   */
  pdca_init_channel(TPA6130_ABDAC_PDCA_CHANNEL,
    &tpa6130_abdac_pdca_options);
  /* Enable the PDCA channel. Since we did not provide any data
   * yet the channel is in idle mode */
  pdca_enable(TPA6130_ABDAC_PDCA_CHANNEL);

}

/*! \brief Outputs a sample buffer to the DACs.
 * The input requires a sample buffer that consists of words (32-bit)
 * which contain two (16-bit) samples, one for each channel.
 *
 * \note The DACs must have been started beforehand.
 */
bool tpa6130_dac_output(void *sample_buffer, size_t sample_length)
{
  //int global_interrupt_enabled;

  /*Wait until the PDCA loads the reload value to its transfer
   * counter register(TCRR=0). Then we are ready to set up a new
   * transfer */
  if(!(pdca_get_transfer_status(TPA6130_ABDAC_PDCA_CHANNEL) &
    PDCA_TRANSFER_COUNTER_RELOAD_IS_ZERO))
  {
    return false;
  }

  /* Nothing to do if we get no data. */
  if(sample_length)
  {

    /*TODO Do we really need to adjust the buffer for mono*/

    /* While reloading the PDC we do not need any active interrupt*/
    //if((global_interrupt_enabled = cpu_irq_is_enabled()))
    //  cpu_irq_disable();

    /*FIXME This assumes a stereo 16-bit sample size */
    // one sample here consists of 2x16-bit (16-bit stereo)
    pdca_reload_channel(TPA6130_ABDAC_PDCA_CHANNEL,
      sample_buffer, sample_length);

    //if(global_interrupt_enabled)
    //  cpu_irq_enable();

    /*TODO enable transfer complete interrupt
     * Is it possible to move this to setup or other places?*/
    if(tpa6130_output_param.callback_opt & AUDIO_DAC_OUT_OF_SAMPLE_CB)
      pdca_enable_interrupt_transfer_complete(TPA6130_ABDAC_PDCA_CHANNEL);
    if (tpa6130_output_param.callback_opt & AUDIO_DAC_RELOAD_CB)
      pdca_enable_interrupt_reload_counter_zero(TPA6130_ABDAC_PDCA_CHANNEL);
  }
  return true;
}

bool tpa6130_dac_is_volume_muted(void)
{
  return false;
}

void tpa6130_dac_mute(bool mute)
{
  // //1st Version Mute Audio for Play/Pause
/*  int volume=tpa6130_get_volume();
  if(mute==true) {
     //Mute volume
     volume= volume|MUTE_L|MUTE_R;
  }
  else {
     //Unmute volume
     volume= volume&(~(MUTE_L|MUTE_R));

  }
 tpa6130_write_data(TPA6130_VOLUME_AND_MUTE,volume);
*/
  //2n Version Stop PDCA >> No lost of audio when pause
/*  if(mute==true) {
    pdca_disable(TPA6130_ABDAC_PDCA_CHANNEL);
  }
  else {
    pdca_enable(TPA6130_ABDAC_PDCA_CHANNEL);
  }
*/

  // 3rd Version wait until the current buffers are empty and disable the interrupts
  int8_t volume = tpa6130_get_volume();
  if (mute)
  {
    uint32_t save_dac_reload_callback_opt;

    // Mute the audio stream
    volume = volume | MUTE_L | MUTE_R;
    tpa6130_write_data(TPA6130_VOLUME_AND_MUTE, volume);
    // Disable the reload channel of the interrupt
    save_dac_reload_callback_opt = tpa6130_output_param.callback_opt;
    tpa6130_output_param.callback_opt = 0;
    // Disable the reload interruption and wait until the transfer is complete
    pdca_disable_interrupt_reload_counter_zero(TPA6130_ABDAC_PDCA_CHANNEL);
    while (!(pdca_get_transfer_status(TPA6130_ABDAC_PDCA_CHANNEL) & PDCA_TRANSFER_COMPLETE));
    // Restore the reload callback function
    tpa6130_output_param.callback_opt = save_dac_reload_callback_opt;
  }
  else
  {
    // Re-enable the interrupts
    pdca_enable_interrupt_reload_counter_zero(TPA6130_ABDAC_PDCA_CHANNEL);
    // Un-mute the audio stream
    volume = volume & (~(MUTE_L | MUTE_R));
    tpa6130_write_data(TPA6130_VOLUME_AND_MUTE, volume);
  }
}
Exemplo n.º 8
0
Arquivo: ms3.c Projeto: avrxml/asf
void ms3_dac_setup(U32 sample_rate_hz, U8 num_channels, U8 bits_per_sample,
		bool swap_channels, void (*callback)(U32 arg), U32 callback_opt,
		U32 pba_hz)
{
	//configure clock
	if (sample_rate_hz < (8000 + 8021) / 2) {
		usb_stream_resync_frequency = 4096000;
		cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, CS2200_FREF));
	}
	else if (sample_rate_hz < (8021 + 22050) / 2) {
		usb_stream_resync_frequency = 4106752;
		cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, CS2200_FREF));
	}
	else if (sample_rate_hz < (22050 + 32000) / 2) {
		usb_stream_resync_frequency = 11289600;
		cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, CS2200_FREF));
	}
	else if (sample_rate_hz < (32000 + 44100) / 2) {
		usb_stream_resync_frequency = 16384000;
		cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, CS2200_FREF));
	}
	else if (sample_rate_hz < (44100 + 48000) / 2) {
		usb_stream_resync_frequency = 22579200;
		cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, CS2200_FREF));
	}
	else if (sample_rate_hz < (48000 + 88200) / 2) {
		usb_stream_resync_frequency = 24576000;
		cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, CS2200_FREF));
	}

	//configure ssc to use clock on TX_CLOCK pin
	AVR32_SSC.tcmr = (0 << AVR32_SSC_TCMR_CKO_OFFSET)
			| (1 << AVR32_SSC_TCMR_STTDLY_OFFSET)
			| (2 << AVR32_SSC_TCMR_CKS_OFFSET)
			| (7 << AVR32_SSC_TCMR_START_OFFSET)
			| (0x1f << AVR32_SSC_TCMR_PERIOD_OFFSET);

	AVR32_SSC.tfmr = (0xf << AVR32_SSC_TFMR_DATLEN_OFFSET)
			| (1 << AVR32_SSC_TFMR_MSBF_OFFSET)
			| (1 << AVR32_SSC_TFMR_FSOS_OFFSET)
			| (1 << AVR32_SSC_TFMR_FSLENHI_OFFSET)
			| (0xf << AVR32_SSC_TFMR_FSLEN_OFFSET);

	AVR32_SSC.cr = AVR32_SSC_CR_TXEN_MASK;

	//configure DMA
	pdca_channel_options_t ms3_ssc_pdca_options = {
		.addr = NULL,
		.size = 0,
		.r_addr = NULL,
		.r_size = 0,
		.pid = AVR32_PDCA_PID_SSC_TX,
		.transfer_size = (bits_per_sample <=  8)?PDCA_TRANSFER_SIZE_BYTE:
				(bits_per_sample <= 16)?PDCA_TRANSFER_SIZE_HALF_WORD:
				PDCA_TRANSFER_SIZE_WORD
	};
	pdca_init_channel(MS3_SSC_TX_PDCA_CHANNEL, &ms3_ssc_pdca_options);
	pdca_enable(MS3_SSC_TX_PDCA_CHANNEL);

	//configure audio parameters
	ms3_output_params.num_channels = num_channels;
	ms3_output_params.callback = callback;
	ms3_output_params.callback_opt = callback_opt;
}

bool ms3_dac_output(void *sample_buffer, size_t sample_length)
{
	bool global_interrupt_enabled;

	if (!(pdca_get_transfer_status(MS3_SSC_TX_PDCA_CHANNEL) &
			PDCA_TRANSFER_COUNTER_RELOAD_IS_ZERO))
		return false;

	if (sample_length) {
		if (ms3_output_params.num_channels == 1) {
			S16 *s16_sample_buffer = sample_buffer;
			int i;

			for (i = sample_length - 1; i >= 0; i--) {
				s16_sample_buffer[2 * i + 1] =
						s16_sample_buffer[2 * i] =
						s16_sample_buffer[i];
			}
		}

		// The PDCA is not able to synchronize its start of transfer with the SSC
		// start of period, so this has to be done by polling the TF pin.
		// Not doing so may result in channels being swapped randomly.
		if ((global_interrupt_enabled = Is_global_interrupt_enabled()))
			Disable_global_interrupt();

		if (pdca_get_transfer_status(MS3_SSC_TX_PDCA_CHANNEL) &
				PDCA_TRANSFER_COMPLETE) {
			while (gpio_get_pin_value(MS3_SSC_TX_FRAME_SYNC_PIN));
			while (!gpio_get_pin_value(MS3_SSC_TX_FRAME_SYNC_PIN));
		}

		pdca_reload_channel(MS3_SSC_TX_PDCA_CHANNEL, sample_buffer, sample_length * 2);
		pdca_get_reload_size(MS3_SSC_TX_PDCA_CHANNEL);
		if (global_interrupt_enabled)
			Enable_global_interrupt();

		if (ms3_output_params.callback_opt & AUDIO_DAC_OUT_OF_SAMPLE_CB)
			pdca_enable_interrupt_transfer_complete(MS3_SSC_TX_PDCA_CHANNEL);
		if (ms3_output_params.callback_opt & AUDIO_DAC_RELOAD_CB)
			pdca_enable_interrupt_reload_counter_zero(MS3_SSC_TX_PDCA_CHANNEL);
	}

	return true;
}