Ejemplo n.º 1
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;
}
Ejemplo n.º 2
0
void aic23b_adc_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_adc_stop();

  gpio_enable_module(AIC23B_SSC_ADC_GPIO_MAP,
                     sizeof(AIC23B_SSC_ADC_GPIO_MAP) / sizeof(AIC23B_SSC_ADC_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   = 1;
  pdc.adc   = 0;
#if (AIC23B_INPUT==AIC23B_INPUT_LINE)
  pdc.mic   = 1;
  pdc.line  = 0;
#elif (AIC23B_INPUT==AIC23B_INPUT_MIC)
  pdc.mic   = 0;
  pdc.line  = 1;
#else
  #error No Input defined in file 'conf_tlv320aic23b.h'
#endif
  aic23b_set_power_down_state(pdc);

  aic23b_adc_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);
#if (AIC23B_INPUT==AIC23B_INPUT_LINE)
  aapc.ste   = 0;
  aapc.dac   = 0;
  aapc.byp   = 0;
  aapc.insel = 0;
  aapc.micm  = 0;
  aapc.micb  = 0;
#elif (AIC23B_INPUT==AIC23B_INPUT_MIC)
  aapc.ste   = 0;
  aapc.dac   = 0;
  aapc.byp   = 0;
  aapc.insel = 1;
  aapc.micm  = 0;
  aapc.micb  = 0;
#else
  #error No Input defined in file 'conf_tlv320aic23b.h'
#endif
  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  = 0;
  aic23b_set_digital_audio_path(dapc);


  aic23b_llicvc_t llivc;
  llivc.data  = AIC23B_DEFAULT(AIC23B_LLICVC);
  llivc.liv   = 20;
  llivc.lim   = 0;
  llivc.lrs   = 1;
  aic23b_write_reg(AIC23B_LLICVC, llivc.data);

  aic23b_rlicvc_t rlivc;
  rlivc.data  = AIC23B_DEFAULT(AIC23B_RLICVC);
  rlivc.riv   = 20;
  rlivc.rim   = 0;
  rlivc.rls   = 1;
  aic23b_write_reg(AIC23B_RLICVC, rlivc.data);

  INTC_register_interrupt(&aic23b_ssc_rx_pdca_int_handler,
                          AIC23B_SSC_RX_PDCA_IRQ,
                          AIC23B_SSC_RX_PDCA_INT_LEVEL);

  aic23b_activate_dig_audio(true);

}

void aic23b_adc_setup(uint32_t sample_rate_hz,
                      uint8_t num_channels,
                      uint8_t bits_per_sample,
                      bool swap_channels,
                      void (*callback)(uint32_t arg),
                      callback_opt,
                      uint32_t pba_hz)
{
  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_IN,
               pba_hz);

  pdca_channel_options_t aic23b_ssc_pdca_options =
  {
    .addr           = NULL,
    .size           = 0,
    .r_addr         = NULL,
    .r_size         = 0,
    .pid            = AIC23B_SSC_RX_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_RX_PDCA_CHANNEL, &aic23b_ssc_pdca_options);
  pdca_enable(AIC23B_SSC_RX_PDCA_CHANNEL);

  // Set ADC frequency
  aic23b_configure_freq(AIC23B_MCLK_HZ, sample_rate_hz);

  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;
}

void aic23b_adc_flush(void)
{
  pdca_disable_interrupt_transfer_complete(AIC23B_SSC_RX_PDCA_CHANNEL);

  while (!(pdca_get_transfer_status(AIC23B_SSC_RX_PDCA_CHANNEL) &
           PDCA_TRANSFER_COMPLETE));
}
Ejemplo n.º 3
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;
    }
  }
}
/*! \brief Initializes SD/MMC resources: GPIO, SPI and SD/MMC.
 */
static void sd_mmc_resources_init(void)
{
  // GPIO pins used for SD/MMC interface
  static const gpio_map_t SD_MMC_SPI_GPIO_MAP =
  {
    {SD_MMC_SPI_SCK_PIN,  SD_MMC_SPI_SCK_FUNCTION },  // SPI Clock.
    {SD_MMC_SPI_MISO_PIN, SD_MMC_SPI_MISO_FUNCTION},  // MISO.
    {SD_MMC_SPI_MOSI_PIN, SD_MMC_SPI_MOSI_FUNCTION},  // MOSI.
    {SD_MMC_SPI_NPCS_PIN, SD_MMC_SPI_NPCS_FUNCTION}   // Chip Select NPCS.
  };

  // SPI options.
  spi_options_t spiOptions =
  {
    .reg          = SD_MMC_SPI_NPCS,
    .baudrate     = SD_MMC_SPI_MASTER_SPEED,  // Defined in conf_sd_mmc_spi.h.
    .bits         = SD_MMC_SPI_BITS,          // Defined in conf_sd_mmc_spi.h.
    .spck_delay   = 0,
    .trans_delay  = 0,
    .stay_act     = 1,
    .spi_mode     = 0,
    .modfdis      = 1
  };

  // Assign I/Os to SPI.
  gpio_enable_module(SD_MMC_SPI_GPIO_MAP,
                     sizeof(SD_MMC_SPI_GPIO_MAP) / sizeof(SD_MMC_SPI_GPIO_MAP[0]));

  // Initialize as master.
  spi_initMaster(SD_MMC_SPI, &spiOptions);

  // Set SPI selection mode: variable_ps, pcs_decode, delay.
  spi_selectionMode(SD_MMC_SPI, 0, 0, 0);

  // Enable SPI module.
  spi_enable(SD_MMC_SPI);

  // Initialize SD/MMC driver with SPI clock (PBA).
  sd_mmc_spi_init(spiOptions, PBA_HZ);
}


/*! \brief Initialize PDCA (Peripheral DMA Controller A) resources for the SPI transfer and start a dummy transfer
 */
void local_pdca_init(void)
{
  // this PDCA channel is used for data reception from the SPI
  pdca_channel_options_t pdca_options_SPI_RX ={ // pdca channel options

    .addr = ram_buffer,
    // memory address. We take here the address of the string dummy_data. This string is located in the file dummy.h

    .size = 512,                              // transfer counter: here the size of the string
    .r_addr = NULL,                           // next memory address after 1st transfer complete
    .r_size = 0,                              // next transfer counter not used here
    .pid = AVR32_PDCA_CHANNEL_USED_RX,        // select peripheral ID - data are on reception from SPI1 RX line
    .transfer_size = PDCA_TRANSFER_SIZE_BYTE  // select size of the transfer: 8,16,32 bits
  };

  // this channel is used to activate the clock of the SPI by sending a dummy variables
  pdca_channel_options_t pdca_options_SPI_TX ={ // pdca channel options

    .addr = (void *)&dummy_data,              // memory address.
                                              // We take here the address of the string dummy_data.
                                              // This string is located in the file dummy.h
    .size = 512,                              // transfer counter: here the size of the string
    .r_addr = NULL,                           // next memory address after 1st transfer complete
    .r_size = 0,                              // next transfer counter not used here
    .pid = AVR32_PDCA_CHANNEL_USED_TX,        // select peripheral ID - data are on reception from SPI1 RX line
    .transfer_size = PDCA_TRANSFER_SIZE_BYTE  // select size of the transfer: 8,16,32 bits
  };

  // Init PDCA transmission channel
  pdca_init_channel(AVR32_PDCA_CHANNEL_SPI_TX, &pdca_options_SPI_TX);

  // Init PDCA Reception channel
  pdca_init_channel(AVR32_PDCA_CHANNEL_SPI_RX, &pdca_options_SPI_RX);

  //! \brief Enable pdca transfer interrupt when completed
  INTC_register_interrupt(&pdca_int_handler, AVR32_PDCA_IRQ_0, AVR32_INTC_INT1);  // pdca_channel_spi1_RX = 0

}


/*! \brief Main function. Execution starts here.
 */
int main(void)
{
  int i, j;


  // Switch the main clock to the external oscillator 0
  pcl_switch_to_osc(PCL_OSC0, FOSC0, OSC0_STARTUP);

  // Initialize debug RS232 with PBA clock
  init_dbg_rs232(PBA_HZ);

  //start test
  print_dbg("\r\nInit SD/MMC Driver");
  print_dbg("\r\nInsert SD/MMC...");

  // Initialize Interrupt Controller
  INTC_init_interrupts();

  // Initialize SD/MMC driver resources: GPIO, SPI and SD/MMC.
  sd_mmc_resources_init();

  // Wait for a card to be inserted
  while (!sd_mmc_spi_mem_check());
  print_dbg("\r\nCard detected!");

  // Read Card capacity
  sd_mmc_spi_get_capacity();
  print_dbg("Capacity = ");
  print_dbg_ulong(capacity >> 20);
  print_dbg(" MBytes");

  // Enable all interrupts.
  Enable_global_interrupt();

  // Initialize PDCA controller before starting a transfer
  local_pdca_init();

  // Read the first sectors number 1, 2, 3 of the card
  for(j = 1; j <= 3; j++)
  {
    // Configure the PDCA channel: the address of memory ram_buffer to receive the data at sector address j
    pdca_load_channel( AVR32_PDCA_CHANNEL_SPI_RX,
                     &ram_buffer,
                     512);

    pdca_load_channel( AVR32_PDCA_CHANNEL_SPI_TX,
                     (void *)&dummy_data,
                     512); //send dummy to activate the clock

    end_of_transfer = false;
    // open sector number j
    if(sd_mmc_spi_read_open_PDCA (j))
    {
      print_dbg("\r\nFirst 512 Bytes of Transfer number ");
      print_dbg_ulong(j);
      print_dbg(" :\r\n");

      spi_write(SD_MMC_SPI,0xFF); // Write a first dummy data to synchronize transfer
      pdca_enable_interrupt_transfer_complete(AVR32_PDCA_CHANNEL_SPI_RX);
      pdca_channelrx =(volatile avr32_pdca_channel_t*) pdca_get_handler(AVR32_PDCA_CHANNEL_SPI_RX); // get the correct PDCA channel pointer
      pdca_channeltx =(volatile avr32_pdca_channel_t*) pdca_get_handler(AVR32_PDCA_CHANNEL_SPI_TX); // get the correct PDCA channel pointer
      pdca_channelrx->cr = AVR32_PDCA_TEN_MASK; // Enable RX PDCA transfer first
      pdca_channeltx->cr = AVR32_PDCA_TEN_MASK; // and TX PDCA transfer

      while(!end_of_transfer);

      // Display the first 2O bytes of the ram_buffer content
      for( i = 0; i < 20; i++)
      {
        print_dbg_char_hex( (U8)(*(ram_buffer + i)));
      }
    }
    else
    {
      print_dbg("\r\n! Unable to open memory \r\n");
    }
  }
  print_dbg("\r\nEnd of the example.\r\n");

  while (1);
}
Ejemplo n.º 5
0
Archivo: lin.c Proyecto: InSoonPark/asf
/*! \brief  This function commands the sending of a LIN header and response, MASTER task only
 *
 * \param l_node Node Value
 * \param l_handle  Handle on the descriptor list
 * \param l_len     Message length corresponding to the message pointed by the handle in the descriptor list
 *
 * \return Status PASS / FAIL
 *
 */
static U8 lin_tx_header_and_response( U8 l_node,
                                      U8 l_handle,
                                      U8 l_len
                                     )
{
if (l_node == 0)
{
        //! Enable Interrupt for Error flags and end ID Reception
        #if ( defined (AVR32_USART_400_H_INCLUDED) ||  \
              defined (AVR32_USART_410_H_INCLUDED) ||  \
              defined (AVR32_USART_420_H_INCLUDED) )
          // PDCA channel options
          pdca_channel_options_t USART_LIN_PDCA_OPTIONS =
          {
            .addr           = (void *)lin_tx_buffer_node0,   // memory address
            .pid            = USART_LIN_NODE0_PDCA_PID_TX,       // select peripheral - data are transmit on USART TX line.
            .size           = (l_len+1),           // transfer counter
            .r_addr         = NULL, // next memory address
            .r_size         = 0,	   // next transfer counter
            .transfer_size  = PDCA_TRANSFER_SIZE_BYTE // select size of the transfer
          };

          pdca_init_channel(USART_LIN_NODE0_TX_PDCA_CHANNEL, &USART_LIN_PDCA_OPTIONS);

          // Copy data of the data contained in the descriptor list into the tx buffer of the PDCA
          memcpy(&lin_tx_buffer_node0[1],lin_descript_list_node0[l_handle].l_pt_data,l_len);

          pdca_enable_interrupt_transfer_complete(USART_LIN_NODE0_TX_PDCA_CHANNEL);

          // Set the ID First
          lin_tx_buffer_node0[0] = lin_descript_list_node0[l_handle].l_id;

          // Start PDCA transfer ID + Data
          pdca_enable(USART_LIN_NODE0_TX_PDCA_CHANNEL);

          usart_lin_set_id_char(usart_lin_node0,lin_descript_list_node0[l_handle].l_id);
      #else
          // PDCA channel options
          pdca_channel_options_t USART_LIN_PDCA_OPTIONS =
          {
            .addr           = (void *)lin_tx_buffer_node0,   // memory address
            .pid            = USART_LIN_NODE0_PDCA_PID_TX,       // select peripheral - data are transmit on USART TX line.
            .size           = (l_len+1),           // transfer counter
            .r_addr         = NULL, // next memory address
            .r_size         = 0,	   // next transfer counter
            .transfer_size  = PDCA_TRANSFER_SIZE_BYTE // select size of the transfer
          };

          pdca_init_channel(USART_LIN_NODE0_TX_PDCA_CHANNEL, &USART_LIN_PDCA_OPTIONS);

          // Copy data of the data contained in the descriptor list into the tx buffer of the PDCA
          memcpy(&lin_tx_buffer_node0[1],lin_descript_list_node0[l_handle].l_pt_data,l_len);

          pdca_enable_interrupt_transfer_complete(USART_LIN_NODE0_TX_PDCA_CHANNEL);

          // Set the ID First
          lin_tx_buffer_node0[0] = lin_descript_list_node0[l_handle].l_id;

          // Start PDCA transfer ID + Data
          pdca_enable(USART_LIN_NODE0_TX_PDCA_CHANNEL);
      #endif
    return PASS;
}
#ifdef USART_LIN_NODE1_INSTANCE
else
{
      //! Enable Interrupt for Error flags and end ID Reception
      #if ( defined (AVR32_USART_400_H_INCLUDED) ||  \
            defined (AVR32_USART_410_H_INCLUDED) ||  \
            defined (AVR32_USART_420_H_INCLUDED) )
        // PDCA channel options
        pdca_channel_options_t USART_LIN_PDCA_OPTIONS =
        {
          .addr           = (void *)lin_tx_buffer_node1,   // memory address
          .pid            = USART_LIN_NODE1_PDCA_PID_TX,       // select peripheral - data are transmit on USART TX line.
          .size           = (l_len+1),           // transfer counter
          .r_addr         = NULL, // next memory address
          .r_size         = 0,	   // next transfer counter
          .transfer_size  = PDCA_TRANSFER_SIZE_BYTE // select size of the transfer
        };

        pdca_init_channel(USART_LIN_NODE1_TX_PDCA_CHANNEL, &USART_LIN_PDCA_OPTIONS);

        // Copy data of the data contained in the descriptor list into the tx buffer of the PDCA
        memcpy(&lin_tx_buffer_node1[1],lin_descript_list_node1[l_handle].l_pt_data,l_len);

        pdca_enable_interrupt_transfer_complete(USART_LIN_NODE1_TX_PDCA_CHANNEL);

        // Set the ID First
        lin_tx_buffer_node1[0] = lin_descript_list_node1[l_handle].l_id;

        // Start PDCA transfer ID + Data
        pdca_enable(USART_LIN_NODE1_TX_PDCA_CHANNEL);

        usart_lin_set_id_char(usart_lin_node1,lin_descript_list_node1[l_handle].l_id);
      #else
        // PDCA channel options
        pdca_channel_options_t USART_LIN_PDCA_OPTIONS =
        {
          .addr           = (void *)lin_tx_buffer_node1,   // memory address
          .pid            = USART_LIN_NODE1_PDCA_PID_TX,       // select peripheral - data are transmit on USART TX line.
          .size           = (l_len+1),           // transfer counter
          .r_addr         = NULL, // next memory address
          .r_size         = 0,	   // next transfer counter
          .transfer_size  = PDCA_TRANSFER_SIZE_BYTE // select size of the transfer
        };

        pdca_init_channel(USART_LIN_NODE1_TX_PDCA_CHANNEL, &USART_LIN_PDCA_OPTIONS);

        // Copy data of the data contained in the descriptor list into the tx buffer of the PDCA
        memcpy(&lin_tx_buffer_node1[1],lin_descript_list_node1[l_handle].l_pt_data,l_len);

        pdca_enable_interrupt_transfer_complete(USART_LIN_NODE1_TX_PDCA_CHANNEL);

        // Set the ID First
        lin_tx_buffer_node1[0] = lin_descript_list_node1[l_handle].l_id;

        // Start PDCA transfer ID + Data
        pdca_enable(USART_LIN_NODE1_TX_PDCA_CHANNEL);
      #endif
    return PASS;
}
#endif
}

/*! \brief  This function commands the sending of a LIN response, SLAVE task of MASTER or SLAVE node.
 *
 * \param l_node Node Value
 * \param l_handle  Handle on the descriptor list
 * \param l_data    Pointer on the data corresponding to the message pointed by the handle in the descriptor list
 * \param l_len     Message length corresponding to the message pointed by the handle in the descriptor list
 *
 * \return Status PASS / FAIL
 *
 */
static U8 lin_tx_response (          U8 l_node,
                                     U8 l_handle,
                                     U8 *l_data,
                                     U8 l_len
                                    ) {

if (l_node == 0)
{
      // PDCA channel options
      pdca_channel_options_t USART_LIN_PDCA_OPTIONS =
      {
        .addr = (void *)lin_tx_buffer_node0,   // memory address
        .pid = USART_LIN_NODE0_PDCA_PID_TX,  // select peripheral - data are transmit on USART TX line.
        .size = (l_len),                 // transfer counter
        .r_addr = NULL,                 // next memory address
        .r_size = 0,	                  // next transfer counter
        .transfer_size = PDCA_TRANSFER_SIZE_BYTE  // select size of the transfer
      };

      pdca_init_channel(USART_LIN_NODE0_TX_PDCA_CHANNEL, &USART_LIN_PDCA_OPTIONS);

      // Copy data of the data contained in the descriptor list into the tx buffer of the PDCA
      memcpy(&lin_tx_buffer_node0[0],lin_descript_list_node0[l_handle].l_pt_data,l_len+1);

       pdca_enable_interrupt_transfer_complete(USART_LIN_NODE0_TX_PDCA_CHANNEL);
      // Start PDCA transfer Data
      pdca_enable(USART_LIN_NODE0_TX_PDCA_CHANNEL);
    return 1;
}
#ifdef USART_LIN_NODE1_INSTANCE
else
{
    // PDCA channel options
    pdca_channel_options_t USART_LIN_PDCA_OPTIONS =
    {
      .addr = (void *)lin_tx_buffer_node1,   // memory address
      .pid = USART_LIN_NODE1_PDCA_PID_TX,  // select peripheral - data are transmit on USART TX line.
      .size = (l_len),                 // transfer counter
      .r_addr = NULL,                 // next memory address
      .r_size = 0,	                  // next transfer counter
      .transfer_size = PDCA_TRANSFER_SIZE_BYTE  // select size of the transfer
    };

    pdca_init_channel(USART_LIN_NODE1_TX_PDCA_CHANNEL, &USART_LIN_PDCA_OPTIONS);

    // Copy data of the data contained in the descriptor list into the tx buffer of the PDCA
    memcpy(&lin_tx_buffer_node1[0],lin_descript_list_node1[l_handle].l_pt_data,l_len+1);

     pdca_enable_interrupt_transfer_complete(USART_LIN_NODE1_TX_PDCA_CHANNEL);
    // Start PDCA transfer Data
    pdca_enable(USART_LIN_NODE1_TX_PDCA_CHANNEL);
    return 1;
}
#endif
}

/*! \brief  This function commands the reception of a LIN response, SLAVE task of MASTER or SLAVE node.
 *
 * \param l_node Node Value
 * \param l_handle  Handle on the descriptor list
 * \param l_len     Message length corresponding to the message pointed by the handle in the descriptor list
 *
 * \return Status PASS / FAIL
 *
 */
static U8 lin_rx_response ( U8 l_node,
                            U8 l_handle,
                            U8 l_len
                          ) {

if (l_node == 0)
{
    // PDCA channel options
    pdca_channel_options_t USART_LIN_PDCA_OPTIONS =
    {
      .addr = (void *)lin_rx_buffer_node0,   // memory address
      .pid = USART_LIN_NODE0_PDCA_PID_RX,  // select peripheral - data are transmit on USART TX line.
      .size = (l_len),                 // transfer counter
      .r_addr = NULL,                 // next memory address
      .r_size = 0,	                  // next transfer counter
      .transfer_size = PDCA_TRANSFER_SIZE_BYTE  // select size of the transfer
    };

    pdca_init_channel(USART_LIN_NODE0_RX_PDCA_CHANNEL, &USART_LIN_PDCA_OPTIONS);

     pdca_enable_interrupt_transfer_complete(USART_LIN_NODE0_RX_PDCA_CHANNEL);
    // Start PDCA transfer Data
    pdca_enable(USART_LIN_NODE0_RX_PDCA_CHANNEL);
    return 1;
}
#ifdef USART_LIN_NODE1_INSTANCE
else
{
    // PDCA channel options
    pdca_channel_options_t USART_LIN_PDCA_OPTIONS =
    {
      .addr = (void *)lin_rx_buffer_node1,   // memory address
      .pid = USART_LIN_NODE1_PDCA_PID_RX,  // select peripheral - data are transmit on USART TX line.
      .size = (l_len),                 // transfer counter
      .r_addr = NULL,                 // next memory address
      .r_size = 0,	                  // next transfer counter
      .transfer_size = PDCA_TRANSFER_SIZE_BYTE  // select size of the transfer
    };

    pdca_init_channel(USART_LIN_NODE1_RX_PDCA_CHANNEL, &USART_LIN_PDCA_OPTIONS);

     pdca_enable_interrupt_transfer_complete(USART_LIN_NODE1_RX_PDCA_CHANNEL);
    // Start PDCA transfer Data
    pdca_enable(USART_LIN_NODE1_RX_PDCA_CHANNEL);
    return 1;
}
#endif
}


/*! \brief  This function reads (empties) the reception data buffer when a LIN response
 *          had been received. This function is additional of the `lin_rx_response()'
 *          function.
 *
 * \param l_node Node Value
 * \param l_data    Pointer on the data corresponding to the message pointed by the handle in the descriptor list
 *
 * \return Status PASS / FAIL
 *
 */
static void lin_get_response (U8 l_node, U8 *l_data) {

U8 i, l_len;
if (l_node == 0)
{
    l_len = usart_lin_get_data_length(usart_lin_node0);
    for (i = 0; i < l_len; i++) {
        (*l_data++) = lin_rx_buffer_node0[i];
    }
}
#ifdef USART_LIN_NODE1_INSTANCE
else
{
    l_len = usart_lin_get_data_length(usart_lin_node1);
    for (i = 0; i < l_len; i++) {
        (*l_data++) = lin_rx_buffer_node1[i];
    }
}
#endif

}
Ejemplo 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);

}
Ejemplo n.º 7
0
/**
 ** PDCA Init.
 **/
void init_pdca(void)
{
  // PDCA channel 0/1 options
  static const pdca_channel_options_t PDCA_CH_OPTIONS =
  {
    .addr = (void *)aDataTransfered,          // memory address
    .pid = AVR32_PDCA_PID_USART2_TX,          // select peripheral - data are transmit on USART TX line.
    .size = 0,                                // transfer counter
    .r_addr = (void *)aDataTransfered,        // next memory address
    .r_size = sizeof(aDataTransfered),        // next transfer counter
    .transfer_size = PDCA_TRANSFER_SIZE_BYTE, // select size of one data packet
    .etrig = true                          // Trigger transfer on event.
  };

  Disable_global_interrupt();

  // Initialize interrupt vectors.
  INTC_init_interrupts();

  // Register the PDCA interrupt handler to the interrupt controller.
  INTC_register_interrupt(&pdca_int_handler, PDCA_CHANNEL_IRQ, AVR32_INTC_INT0);

  Enable_global_interrupt();

  // Init PDCA channel with the pdca_options.
  pdca_init_channel(PDCA_CHANNEL_USART, &PDCA_CH_OPTIONS);
  pdca_channel = pdca_get_handler(PDCA_CHANNEL_USART); // For use in the pdca interrupt handler.

  // Enable pdca transfer error interrupt & transfer complete interrupt.
  pdca_enable_interrupt_transfer_error(PDCA_CHANNEL_USART);
  pdca_enable_interrupt_transfer_complete(PDCA_CHANNEL_USART);

  // Enable the PEVC channel "PDCA CHANNEL 0/1 ONE-ITEM-TRANSFER"
  PEVC_CHANNELS_ENABLE(ppevc, 1<<PEVC_PDCA_SOT_USER);

  // Enable the PDCA.
  pdca_enable(PDCA_CHANNEL_USART);
}

/**
 ** AST Init.
 **/
void init_ast(void)
{

  avr32_ast_pir0_t pir = {
    .insel = 14 // Set a event every second
  };

  ast_calendar_t ast_calendar;
  ast_calendar.FIELD.sec  = 30;
  ast_calendar.FIELD.min  = 45;
  ast_calendar.FIELD.hour = 12;
  ast_calendar.FIELD.day  = 7;
  ast_calendar.FIELD.month= 10;
  ast_calendar.FIELD.year = 9;

  scif_osc32_opt_t opt;
  opt.mode = SCIF_OSC_MODE_2PIN_CRYSTAL;
  opt.startup = AVR32_SCIF_OSCCTRL32_STARTUP_0_RCOSC;

  // Start OSC_32KHZ
  scif_start_osc32(&opt,true);

  // Initialize the AST
  if (!ast_init_calendar(&AVR32_AST, AST_OSC_32KHZ, AST_PSEL_32KHZ_1HZ, ast_calendar))
  {
    print_dbg("Error initializing the AST\r\n");
    while(1);
  }

  ast_set_periodic0_value(&AVR32_AST,pir);

  ast_enable_periodic0(&AVR32_AST);

  // Clear All Interrupt
  AVR32_AST.scr=0xFFFFFFFF;

  // Enable the AST
  ast_enable(&AVR32_AST);
}

/*! \brief Initializes the MCU system clocks.
*/
static void init_sys_clocks(void)
{

  /*! \name System Clock Frequencies
   */
  //! @{
  static pcl_freq_param_t pcl_freq_param =
  {
    .cpu_f        = FCPU_HZ,
    .pba_f        = FPBA_HZ,
    .osc0_f       = FOSC0,
    .osc0_startup = OSC0_STARTUP
  };
  //! @}

  // Configure system clocks.
  if (pcl_configure_clocks(&pcl_freq_param) != PASS) {
    while(1);
  }
}

/*! \brief This example show a DMA transfer to USART controlled by the AST
    periodic alarm using the PEVC.
 */
int main(void)
{
  int i;

  // Init the string with a simple recognizable pattern.
  for(i=0;i<sizeof(aDataTransfered);i++)
    aDataTransfered[i] = '0' + (i%36);

  init_sys_clocks();

  init_usart();

  gpio_clr_gpio_pin(LED0_GPIO);

  init_pevc();

  init_ast();

  init_pdca();

  while(1)
  {
    gpio_tgl_gpio_pin(LED1_GPIO);
    delay_ms(500); //Wait 500ms
  }
}
Ejemplo n.º 8
0
void aic23b_codec_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_codec_stop();

  gpio_enable_module(AIC23B_SSC_CODEC_GPIO_MAP,
                     sizeof(AIC23B_SSC_CODEC_GPIO_MAP) / sizeof(AIC23B_SSC_CODEC_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   = 0;
#if (AIC23B_INPUT==AIC23B_INPUT_LINE)
  pdc.mic   = 1;
  pdc.line  = 0;
#elif (AIC23B_INPUT==AIC23B_INPUT_MIC)
  pdc.mic   = 0;
  pdc.line  = 1;
#else
  #error No Input defined in file 'conf_tlv320aic23b.h'
#endif
  aic23b_set_power_down_state(pdc);

  aic23b_codec_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);
#if (AIC23B_INPUT==AIC23B_INPUT_LINE)
  aapc.ste   = 0;
  aapc.dac   = 1;
  aapc.byp   = 0;
  aapc.insel = 0;
  aapc.micm  = 0;
  aapc.micb  = 1;
#elif (AIC23B_INPUT==AIC23B_INPUT_MIC)
  aapc.ste   = 0;
  aapc.dac   = 1;
  aapc.sta   = 4;
  aapc.byp   = 0;
  aapc.insel = 1;
  aapc.micm  = 0;
  aapc.micb  = 1;
#else
  #error No Input defined in file 'conf_tlv320aic23b.h'
#endif
  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  = 0;
  aic23b_set_digital_audio_path(dapc);


  aic23b_llicvc_t llivc;
  llivc.data  = AIC23B_DEFAULT(AIC23B_LLICVC);
  llivc.liv   = 20;
  llivc.lim   = 0;
  llivc.lrs   = 1;
  aic23b_write_reg(AIC23B_LLICVC, llivc.data);

  aic23b_rlicvc_t rlivc;
  rlivc.data  = AIC23B_DEFAULT(AIC23B_RLICVC);
  rlivc.riv   = 20;
  rlivc.rim   = 0;
  rlivc.rls   = 1;
  aic23b_write_reg(AIC23B_RLICVC, rlivc.data);

  INTC_register_interrupt(&aic23b_ssc_rx_pdca_int_handler,
                          AIC23B_SSC_RX_PDCA_IRQ,
                          AIC23B_SSC_RX_PDCA_INT_LEVEL);

  // 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_codec_setup(uint32_t sample_rate_hz,
                      uint8_t num_channels,
                      uint8_t bits_per_sample,
                      bool swap_channels,
                      void (*callback)(uint32_t opt),
                      uint32_t callback_opt,
                      uint32_t pba_hz)
{
  uint32_t master_clock = AIC23B_MCLK_HZ; // default configuration

  // Change the CPU frequency
  //
  //Disable_global_interrupt();

  // Switch to OSC0 during OSC1 transition
  //pm_switch_to_osc0(&AVR32_PM, FOSC0, OSC0_STARTUP);

  // Switch to PLL0 as the master clock
  //pm_switch_to_clock(&AVR32_PM, AVR32_PM_MCCTRL_MCSEL_PLL0);

  if (sample_rate_hz < (8000 + 8021) / 2)
  { // 8000 Hz
  }
  else if (sample_rate_hz < (8021 + 32000) / 2)
  { // 8021 Hz
  }
  else if (sample_rate_hz < (32000 + 44100) / 2)
  { // 32000 Hz
    master_clock = usb_stream_resync_frequency = 8192000;
    cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, FOSC0));
    pba_hz = FCPU_HZ = FHSB_HZ = FPBA_HZ = FPBB_HZ = FMCK_HZ(8192000);
  }
  else if (sample_rate_hz < (44100 + 48000) / 2)
  { // 44100 Hz
    master_clock = usb_stream_resync_frequency = 11289600;
    cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, FOSC0));
    pba_hz = FCPU_HZ = FHSB_HZ = FPBA_HZ = FPBB_HZ = FMCK_HZ(11289600);
  }
  else if (sample_rate_hz < (48000 + 88200) / 2)
  { // 48000 Hz
    master_clock = usb_stream_resync_frequency = 12288000;
    cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, FOSC0));
    pba_hz = FCPU_HZ = FHSB_HZ = FPBA_HZ = FPBB_HZ = FMCK_HZ(12288000);
  }
  else if (sample_rate_hz < (88200 + 96000) / 2)
  { // 88200 Hz
  }
  else
  { // 96000 Hz
  }

  //Enable_global_interrupt();

  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_STEREO_IN,
               pba_hz);

  pdca_channel_options_t aic23b_ssc_pdca_options_rx =
  {
    .addr           = NULL,
    .size           = 0,
    .r_addr         = NULL,
    .r_size         = 0,
    .pid            = AIC23B_SSC_RX_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_RX_PDCA_CHANNEL, &aic23b_ssc_pdca_options_rx);
  pdca_enable(AIC23B_SSC_RX_PDCA_CHANNEL);

  pdca_channel_options_t aic23b_ssc_pdca_options_tx =
  {
    .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_tx);
  pdca_enable(AIC23B_SSC_TX_PDCA_CHANNEL);

  // Set codec frequency
  aic23b_configure_freq(master_clock, sample_rate_hz);

  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;
}

void aic23b_codec_flush(void)
{
  pdca_disable_interrupt_transfer_complete(AIC23B_SSC_RX_PDCA_CHANNEL);
  while (!(pdca_get_transfer_status(AIC23B_SSC_RX_PDCA_CHANNEL) &
           PDCA_TRANSFER_COMPLETE));
  pdca_disable_interrupt_transfer_complete(AIC23B_SSC_TX_PDCA_CHANNEL);
  while (!(pdca_get_transfer_status(AIC23B_SSC_TX_PDCA_CHANNEL) &
           PDCA_TRANSFER_COMPLETE));
}

void aic23b_codec_stop(void)
{
  aic23b_codec_flush();

  aic23b_reset();

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

  pdca_disable(AIC23B_SSC_RX_PDCA_CHANNEL);
  pdca_disable(AIC23B_SSC_TX_PDCA_CHANNEL);

  ssc_i2s_reset(AIC23B_SSC);

  gpio_enable_gpio(AIC23B_SSC_CODEC_GPIO_MAP,
                   sizeof(AIC23B_SSC_CODEC_GPIO_MAP) / sizeof(AIC23B_SSC_CODEC_GPIO_MAP[0]));

  aic23b_output_params.num_channels             = 0;
  aic23b_output_params.callback                 = NULL;
  aic23b_output_params.callback_opt             = 0;
}
Ejemplo n.º 9
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);
  }
}
Ejemplo n.º 10
0
Archivo: ms3.c Proyecto: 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;
}
Ejemplo n.º 11
0
// initialize application timer
extern void init_tc (volatile avr32_tc_t *tc) {
  // waveform options
  static const tc_waveform_opt_t waveform_opt = {
    .channel  = APP_TC_CHANNEL,  // channel
    .bswtrg   = TC_EVT_EFFECT_NOOP, // software trigger action on TIOB
    .beevt    = TC_EVT_EFFECT_NOOP, // external event action
    .bcpc     = TC_EVT_EFFECT_NOOP, // rc compare action
    .bcpb     = TC_EVT_EFFECT_NOOP, // rb compare
    .aswtrg   = TC_EVT_EFFECT_NOOP, // soft trig on TIOA
    .aeevt    = TC_EVT_EFFECT_NOOP, // etc
    .acpc     = TC_EVT_EFFECT_NOOP,
    .acpa     = TC_EVT_EFFECT_NOOP,
    // Waveform selection: Up mode with automatic trigger(reset) on RC compare.
    .wavsel   = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER,
    .enetrg   = false,             // external event trig
    .eevt     = 0,                 // extern event select
    .eevtedg  = TC_SEL_NO_EDGE,    // extern event edge
    .cpcdis   = false,             // counter disable when rc compare
    .cpcstop  = false,            // counter stopped when rc compare
    .burst    = false,
    .clki     = false,
    // Internal source clock 5, connected to fPBA / 128.
    .tcclks   = TC_CLOCK_SOURCE_TC5
  };

  // Options for enabling TC interrupts
  static const tc_interrupt_t tc_interrupt = {
    .etrgs = 0,
    .ldrbs = 0,
    .ldras = 0,
    .cpcs  = 1, // Enable interrupt on RC compare alone
    .cpbs  = 0,
    .cpas  = 0,
    .lovrs = 0,
    .covfs = 0
  };
  // Initialize the timer/counter.
  tc_init_waveform(tc, &waveform_opt);

  // set timer compare trigger.
  // we want it to overflow and generate an interrupt every 1 ms
  // so (1 / fPBA / 128) * RC = 0.001
  // so RC = fPBA / 128 / 1000
  tc_write_rc(tc, APP_TC_CHANNEL, (FPBA_HZ / 128 / 1000));
  // configure the timer interrupt
  tc_configure_interrupts(tc, APP_TC_CHANNEL, &tc_interrupt);
  // Start the timer/counter.
  tc_start(tc, APP_TC_CHANNEL);
}


// initialize usb USARTy
void init_ftdi_usart (void) {
  // GPIO map for USART.
  static const gpio_map_t FTDI_USART_GPIO_MAP = {
    { FTDI_USART_RX_PIN, FTDI_USART_RX_FUNCTION },
    { FTDI_USART_TX_PIN, FTDI_USART_TX_FUNCTION }
  };
  
  // Options for USART.
  static const usart_options_t FTDI_USART_OPTIONS = {
    .baudrate = FTDI_USART_BAUDRATE,
    .charlength = 8,
    .paritytype = USART_NO_PARITY,
    .stopbits = USART_1_STOPBIT,
    .channelmode = USART_NORMAL_CHMODE
  };

  // Set up GPIO for FTDI_USART
  gpio_enable_module(FTDI_USART_GPIO_MAP,
                     sizeof(FTDI_USART_GPIO_MAP) / sizeof(FTDI_USART_GPIO_MAP[0]));

  // Initialize in RS232 mode.
  usart_init_rs232(FTDI_USART, &FTDI_USART_OPTIONS, FPBA_HZ);
}

// initialize spi1: OLED, ADC, SD/MMC
extern void init_spi1 (void) {
  
  static const gpio_map_t OLED_SPI_GPIO_MAP = {
    {OLED_SPI_SCK_PIN,  OLED_SPI_SCK_FUNCTION },
    {OLED_SPI_MISO_PIN, OLED_SPI_MISO_FUNCTION},
    {OLED_SPI_MOSI_PIN, OLED_SPI_MOSI_FUNCTION},
    {OLED_SPI_NPCS0_PIN,  OLED_SPI_NPCS0_FUNCTION },
    {OLED_SPI_NPCS1_PIN,  OLED_SPI_NPCS1_FUNCTION },
    {OLED_SPI_NPCS2_PIN,  OLED_SPI_NPCS2_FUNCTION },
  };

  // SPI options for OLED
  spi_options_t spiOptions = {
    .reg = OLED_SPI_NPCS,
    .baudrate     = 40000000,
    .bits = 8,
    .trans_delay = 0,
    .spck_delay = 0,
    .stay_act = 1,
    .spi_mode = 3,
    .modfdis = 1
  };

  // Assign GPIO to SPI.
  gpio_enable_module(OLED_SPI_GPIO_MAP,
		     sizeof(OLED_SPI_GPIO_MAP) / sizeof(OLED_SPI_GPIO_MAP[0]));
  // Initialize as master.
  spi_initMaster(OLED_SPI, &spiOptions);
  // Set SPI selection mode: variable_ps, pcs_decode, delay.
  spi_selectionMode(OLED_SPI, 0, 0, 0);
  // Enable SPI module.
  spi_enable(OLED_SPI);

  // setup chip register for OLED
  spi_setupChipReg( OLED_SPI, &spiOptions, FPBA_HZ );

  // add ADC chip register
  spiOptions.reg          = ADC_SPI_NPCS;
  spiOptions.baudrate     = 20000000;
  spiOptions.bits         = 16;
  spiOptions.spi_mode     = 2;
  spiOptions.spck_delay   = 0;
  spiOptions.trans_delay  = 5;
  spiOptions.stay_act     = 0;
  spiOptions.modfdis      = 0;

  spi_setupChipReg( ADC_SPI, &spiOptions, FPBA_HZ );

  // add SD/MMC chip register
  spiOptions.reg         = SD_MMC_SPI_NPCS;
  spiOptions.baudrate    = SD_MMC_SPI_MASTER_SPEED; // Defined in conf_sd_mmc_spi.h;
  spiOptions.bits        = SD_MMC_SPI_BITS; // Defined in conf_sd_mmc_spi.h;
  spiOptions.spck_delay  = 0;
  spiOptions.trans_delay = 0;
  spiOptions.stay_act    = 1;
  spiOptions.spi_mode    = 0;
  spiOptions.modfdis     = 1;

  // Initialize SD/MMC driver with SPI clock (PBA).
  sd_mmc_spi_init(spiOptions, FPBA_HZ);
}


// init PDCA (Peripheral DMA Controller A) resources for the SPI transfer and start a dummy transfer
void init_local_pdca(void)
{
  // PDCA channel for SPI RX
  pdca_channel_options_t pdca_options_SPI_RX ={ // pdca channel options
    .addr = (void *)&pdcaRxBuf,
    .size = FS_BUF_SIZE,                      // transfer size
    .r_addr = NULL,                           // next memory address after 1st transfer complete
    .r_size = 0,                              // next transfer counter not used here
    .pid = AVR32_PDCA_CHANNEL_USED_RX,        // select peripheral ID - SPI1 RX
    .transfer_size = PDCA_TRANSFER_SIZE_BYTE  // select size of the transfer: 8,16,32 bits
  };

  // PDCA channel for SPI TX
  pdca_channel_options_t pdca_options_SPI_TX ={ // pdca channel options
    .addr = (void *)&pdcaTxBuf,               // memory address.
    .size = FS_BUF_SIZE,                      // transfer size
    .r_addr = NULL,                           // next memory address after 1st transfer complete
    .r_size = 0,                              // next transfer counter not used here
    .pid = AVR32_PDCA_CHANNEL_USED_TX,        // select peripheral ID - SPI1 TX
    .transfer_size = PDCA_TRANSFER_SIZE_BYTE  // select size of the transfer: 8,16,32 bits
  };

  // Init PDCA transmission channel
  pdca_init_channel(AVR32_PDCA_CHANNEL_SPI_TX, &pdca_options_SPI_TX);

  // Init PDCA Reception channel
  pdca_init_channel(AVR32_PDCA_CHANNEL_SPI_RX, &pdca_options_SPI_RX);
}

// intialize resources for bf533 communication: SPI, GPIO
void init_bfin_resources(void) {
  static const gpio_map_t BFIN_SPI_GPIO_MAP = {
    { BFIN_SPI_SCK_PIN, BFIN_SPI_SCK_FUNCTION },
    { BFIN_SPI_MISO_PIN, BFIN_SPI_MISO_FUNCTION },
    { BFIN_SPI_MOSI_PIN, BFIN_SPI_MOSI_FUNCTION },
    { BFIN_SPI_NPCS0_PIN, BFIN_SPI_NPCS0_FUNCTION },
  };
  
  spi_options_t spiOptions = {
    .reg          = BFIN_SPI_NPCS,
    //// FIXME: 
    //// would prefer fast baudrate / lower trans delay during boot,
    //// but need multiple registers for boot (fast) and run (slow)
    //// investigate if this is possible...
    //   .baudrate     = 20000000,
    //     .baudrate     = 10000000,
    //     .baudrate     = 5000000,
     .baudrate     = 20000000,
    .bits         = 8,
    .spck_delay   = 0,
    //    .trans_delay  = 0,
    .trans_delay = 20,
    .stay_act     = 1,
    .spi_mode     = 1,
    .modfdis      = 1
  };

  // assign pins to SPI.
  gpio_enable_module(BFIN_SPI_GPIO_MAP,
		     sizeof(BFIN_SPI_GPIO_MAP) / sizeof(BFIN_SPI_GPIO_MAP[0]));

  // intialize as master
  spi_initMaster(BFIN_SPI, &spiOptions);

  // set selection mode: variable_ps, pcs_decode, delay.
  spi_selectionMode(BFIN_SPI, 0, 0, 0);

  // enable SPI.
  spi_enable(BFIN_SPI);

  // intialize the chip register
  spi_setupChipReg(BFIN_SPI, &spiOptions, FPBA_HZ);
  // enable pulldown on bfin HWAIT line
  //// shit! not implemented... 
  // gpio_enable_pin_pull_down(BFIN_HWAIT_PIN);
  
  // enable pullup on bfin RESET line
  gpio_enable_pin_pull_up(BFIN_RESET_PIN);
}

// intialize two-wire interface
void init_twi(void) {
  // TWI/I2C GPIO map
  static const gpio_map_t TWI_GPIO_MAP = {
    { TWI_DATA_PIN, TWI_DATA_FUNCTION },
    { TWI_CLOCK_PIN, TWI_CLOCK_FUNCTION }
  };
  gpio_enable_module(TWI_GPIO_MAP, sizeof(TWI_GPIO_MAP) / sizeof(TWI_GPIO_MAP[0]));
}


// initialize USB host stack
void init_usb_host (void) {
  //  pm_configure_usb_clock();
  uhc_start();
}
Ejemplo n.º 12
0
/******************************************************************************
    rn42_init
*//**
    @brief Initializes RN42 driver.

    @brief usart    Pointer to the USART hardware structure the RN42 is on.
    @brief irq      IRQ number to process interrupts on.
    @brief gpio_pin Pin connected to the RN42's status output.
******************************************************************************/
void
rn42_init(
    volatile avr32_usart_t *usart,
    uint32_t irq,
    uint32_t gpio_pin)
{ 
    static usart_options_t usart_options =
    {
        .baudrate     = 115200,
        .charlength   = 8,
        .paritytype   = USART_NO_PARITY,
        .stopbits     = USART_1_STOPBIT,
        .channelmode  = USART_NORMAL_CHMODE
    };

    static pdca_channel_options_t pdca_rx_options =
    {
        .pid = AVR32_PDCA_PID_USART3_RX,
        .addr = NULL,
        .size = 0,
        .r_addr = NULL,
        .r_size = 0,
        .transfer_size = PDCA_TRANSFER_SIZE_BYTE
    };

    static pdca_channel_options_t pdca_tx_options =
    {
        .pid = AVR32_PDCA_PID_USART3_TX,
        .addr = NULL,
        .size = 0,
        .r_addr = NULL,
        .r_size = 0,
        .transfer_size = PDCA_TRANSFER_SIZE_BYTE
    };

    /* Initialize the USART to use hardware handshaking. Without the
       handshaking, the RN42 has trouble keeping up when continuosly sending
       fairly small amounts of data. Note that when hardware handshaking is
       enabled, the PDCA must be used for receiving data.
     */
    rn42_usart = usart;
    usart_serial_init(rn42_usart, &usart_options);
    rn42_usart->mr = (rn42_usart->mr & ~0xf) | 0x02;

    /* Register the ISR for USART's DMA completion IRQs. */
    pdca_init_channel(PDCA_CHANNEL_RX, &pdca_rx_options);
    pdca_init_channel(PDCA_CHANNEL_TX, &pdca_tx_options);
    irq_register_handler(usart_isr, PDCA_IRQ, 0);

    setup_usart_rx_dma(bt_buf, sizeof(command_t));
    usart_irq_enable();
    pdca_enable(PDCA_CHANNEL_RX);
    pdca_enable(PDCA_CHANNEL_TX);

    /* Configure RN42 status GPIO. */
    gpio_configure_pin(gpio_pin, GPIO_DIR_INPUT | GPIO_PULL_DOWN);
    gpio_disable_pin_pull_up(gpio_pin);

    rn42_status_pin = gpio_pin;
}


/******************************************************************************
    rn42_connected
*//**
    @brief Returns whether the RN42 is connected by examining the status GPIO.

    The RN42's status line appears to bounce, so this function takes care of
    debouncing it.
******************************************************************************/
static bool
rn42_connected(void)
{
    bool connected1;
    bool connected2;

    do {
        connected1 = gpio_pin_is_high(rn42_status_pin);
        delay_ms(50);
        connected2 = gpio_pin_is_high(rn42_status_pin);
    } while (connected1 != connected2);

    return connected1 & connected2;
}


/******************************************************************************
    rn42_send_data
*//**
    @brief Transmits data to a Bluetooth peer over the RN42 module.

    @param[in] buf  Pointer to the data that should be sent.
    @param[in] size Number of bytes to send.
******************************************************************************/
void
rn42_send_data(uint8_t *buf, uint32_t size)
{
    uint32_t status;

    setup_usart_tx_dma(buf, size);

    while (true)
    {
        status = pdca_get_transfer_status(PDCA_CHANNEL_TX);

        if (status & PDCA_TRANSFER_COMPLETE)
        {
            break;
        }
    }
}


/******************************************************************************
    send_response
*//**
    @brief Sends a response packet to the host.

    @param[in] cmd_id       The command ID we're responding to.
    @param[in] status       The status code.
    @param[in] data         Pointer to data to send to the PC.
    @param[in] data_length  Number of bytes to send.
******************************************************************************/
static void
send_response(
    uint8_t cmd_id,
    uint8_t status,
    uint8_t *data,
    uint32_t data_length)
{
    response_t response = {
        {'C', 'C', 'M', 'D'},
        cmd_id,
        status,
    };
    storeBigU32(&response.data_length, data_length);

    rn42_send_data((uint8_t*) &response, sizeof(response));
    rn42_send_data(data, data_length);
}
Ejemplo n.º 13
0
int8_t  i2c_driver_trigger_request(uint8_t  i2c_device, uint8_t  schedule_slot) 
{
	// initiate transfer of given request
	// set up DMA channel
	volatile avr32_twim_t *twim;
	
	i2c_packet_conf_t* conf = &schedule[i2c_device][schedule_slot].config;
	static  pdca_channel_options_t PDCA_OPTIONS =
			{
				.addr = 0,                                // memory address
				.pid = AVR32_TWIM0_PDCA_ID_TX,            // select peripheral 
				.size = 4,	                              // transfer counter
				.r_addr = NULL,                           // next memory address
				.r_size = 0,                              // next transfer counter
				.transfer_size = PDCA_TRANSFER_SIZE_BYTE  // select size of the transfer
			};
	switch (i2c_device) 
	{
	case 0: 
		twim = &AVR32_TWIM0;
		twim->cr = AVR32_TWIM_CR_MEN_MASK;
		twim->cr = AVR32_TWIM_CR_SWRST_MASK;
		twim->cr = AVR32_TWIM_CR_MDIS_MASK;
		
		switch (conf->direction)  
		{
		case I2C_WRITE1_THEN_READ:
		case I2C_READ:
			PDCA_OPTIONS.pid = AVR32_TWIM0_PDCA_ID_RX;
			PDCA_OPTIONS.addr = (void *)conf->read_data;
			PDCA_OPTIONS.size=conf->read_count;
			// Init PDCA channel with the pdca_options.
			pdca_init_channel(TWI0_DMA_CH, &PDCA_OPTIONS); // init PDCA channel with options.
			break;
			
		case I2C_WRITE:
			PDCA_OPTIONS.pid = AVR32_TWIM0_PDCA_ID_TX;
			PDCA_OPTIONS.addr = (void *)conf->write_data;
			PDCA_OPTIONS.size=conf->write_count;
			
			// Init PDCA channel with the pdca_options.
			pdca_init_channel(TWI0_DMA_CH, &PDCA_OPTIONS); // init PDCA channel with options.
			pdca_load_channel(TWI0_DMA_CH, (void *)conf->write_data, conf->write_count);
			break;
		}
		
		//pdca_load_channel(TWI0_DMA_CH, (void *)schedule[i2c_device][schedule_slot].config.write_data, schedule[i2c_device][schedule_slot].config.write_count);
		// Enable pdca interrupt each time the reload counter reaches zero, i.e. each time
		// the whole block was received
		pdca_enable_interrupt_transfer_complete(TWI0_DMA_CH);
		pdca_enable_interrupt_transfer_error(TWI0_DMA_CH);
	break;
		
	case 1:
		twim = &AVR32_TWIM1;
	break;
	
	default: // invalid device ID
		return -1;
	}		

	// set up I2C speed and mode
	//twim_set_speed(twim, 100000, sysclk_get_pba_hz());
    
	switch (conf->direction)  
	{
		case I2C_READ:
			twim->cmdr = (conf->slave_address << AVR32_TWIM_CMDR_SADR_OFFSET)
						| (conf->read_count << AVR32_TWIM_CMDR_NBYTES_OFFSET)
						| (AVR32_TWIM_CMDR_VALID_MASK)
						| (AVR32_TWIM_CMDR_START_MASK)
						| (0 << AVR32_TWIM_CMDR_STOP_OFFSET)
						| (0 << AVR32_TWIM_CMDR_READ_OFFSET);
		break;
		
		case I2C_WRITE1_THEN_READ:
			print_util_dbg_print( "wr");
			
			// set up next command register for the burst read transfer
			// set up command register to initiate the write transfer. The DMA will take care of the reading once this is done.
			twim->cmdr = (conf->slave_address << AVR32_TWIM_CMDR_SADR_OFFSET)
						| (1 << AVR32_TWIM_CMDR_NBYTES_OFFSET)
						| (AVR32_TWIM_CMDR_VALID_MASK)
						| (AVR32_TWIM_CMDR_START_MASK)
						| (0 << AVR32_TWIM_CMDR_STOP_OFFSET)
						;
			
			twim->ncmdr = (conf->slave_address << AVR32_TWIM_CMDR_SADR_OFFSET)
						| ((conf->read_count) << AVR32_TWIM_CMDR_NBYTES_OFFSET)
						| (AVR32_TWIM_CMDR_VALID_MASK)
						| (AVR32_TWIM_CMDR_START_MASK)
						| (0 << AVR32_TWIM_CMDR_STOP_OFFSET)
						| (0 << AVR32_TWIM_CMDR_READ_OFFSET);
			// set up writing of one byte (usually a slave register index)
			//twim->cr = AVR32_TWIM_CR_MEN_MASK;
			twim->thr = conf->write_then_read_preamble;
			twim->cr = AVR32_TWIM_CR_MEN_MASK;
		break;	
			
		case I2C_WRITE:
			print_util_dbg_print( "w");
			twim->cmdr = (conf->slave_address << AVR32_TWIM_CMDR_SADR_OFFSET)
						| ((conf->write_count) << AVR32_TWIM_CMDR_NBYTES_OFFSET)
						| (AVR32_TWIM_CMDR_VALID_MASK)
						| (AVR32_TWIM_CMDR_START_MASK)
						| (0 << AVR32_TWIM_CMDR_STOP_OFFSET)
						;
			twim->ncmdr = (conf->slave_address << AVR32_TWIM_CMDR_SADR_OFFSET)
						| ((conf->write_count) << AVR32_TWIM_CMDR_NBYTES_OFFSET)
						//| (AVR32_TWIM_CMDR_VALID_MASK)
						| (AVR32_TWIM_CMDR_START_MASK)
						| (0 << AVR32_TWIM_CMDR_STOP_OFFSET)
						;	
			
		break;	
	}		
	// start transfer

	current_schedule_slot[i2c_device] = schedule_slot;
	schedule[i2c_device][schedule_slot].transfer_in_progress = 1;
	twim->cr = AVR32_TWIM_CR_MEN_MASK;
	pdca_enable(TWI0_DMA_CH);
	return 0;
}

int8_t  i2c_driver_pause_request(uint8_t  i2c_device, uint8_t  schedule_slot)
{
	// pause scheduler
	// if this request currently active, wait for current transfer to finish
	// deactivate request
	// resume scheduler
}

int8_t  i2c_driver_enable_request(uint8_t  i2c_device, uint8_t  schedule_slot){
	return 0;
}

int8_t  i2c_driver_remove_request(uint8_t  i2c_device, uint8_t  schedule_slot){
	return 0;
}