Example #1
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;
}
Example #2
0
int media_read(unsigned long sector, unsigned char *buffer, unsigned long sector_count) {
#if 1
#else
  unsigned long i;

  for (i=0;i<sector_count;i++) {
    pdca_load_channel( AVR32_PDCA_CHANNEL_SPI_RX,
		       &pdcaRxBuf,
		       FS_BUF_SIZE);
    
    pdca_load_channel( AVR32_PDCA_CHANNEL_SPI_TX,
		       (void *)&pdcaTxBuf,
		       FS_BUF_SIZE); //send dummy to activate the clock
    
    fsEndTransfer = false;
    
    if(sd_mmc_spi_read_open_PDCA (sector)) {

      spi_write(SD_MMC_SPI,0xFF); // dummy byte synchronizes transfer

      pdca_enable_interrupt_transfer_complete(AVR32_PDCA_CHANNEL_SPI_RX);
      pdcaRxChan =(volatile avr32_pdca_channel_t*) pdca_get_handler(AVR32_PDCA_CHANNEL_SPI_RX);
      pdcaTxChan =(volatile avr32_pdca_channel_t*) pdca_get_handler(AVR32_PDCA_CHANNEL_SPI_TX);
      pdcaRxChan->cr = AVR32_PDCA_TEN_MASK; // Enable RX PDCA transfer first
      pdcaTxChan->cr = AVR32_PDCA_TEN_MASK; // and TX PDCA transfer
      // wait for signal from ISR
      while(!fsEndTransfer) { ;; }
      // copy FIXME: could optimize away
      for(i=0; i<FS_BUF_SIZE; i++) {
	buffer[i] = pdcaRxBuf[i];
      }
    } else {
      print_dbg("\r\n error opening PDCA at sector "); 
      print_dbg_ulong(sector);
    }
    sector ++;
    buffer += FS_BUF_SIZE;
  }
  return 1;
#endif
}
Example #3
0
__interrupt
#endif
static void int_usart_handler(void)
{
  unsigned char c;


  if( USART->csr & AVR32_USART_RXRDY_MASK )
  {
      c = (USART->rhr & AVR32_USART_RHR_RXCHR_MASK) >> AVR32_USART_RHR_RXCHR_OFFSET;
      if(MessageReady == true) {
      //Do not update message will old message has not been read
        return;
      }

    SERIAL_RX_Buffer[SERIAL_RX_index++]=c;
    // resynchronize until we get MESSAGE_START
    if(SERIAL_RX_Buffer[0]!=MESSAGE_START) {
      SERIAL_RX_index=0;
    }

    if(SERIAL_RX_index == 3u) {
    	rx_size = ((SERIAL_RX_Buffer[1]<<8) | SERIAL_RX_Buffer[2]);
    }

    // If SERIAL_RX_index==3 run PDCA to received rest of the message
    if(SERIAL_RX_index == 3u) {
      // Disable RXRDY interrupt before switch to PDCA MODE
      USART->idr = AVR32_USART_IDR_RXRDY_MASK;
      rx_size = ((SERIAL_RX_Buffer[1]<<8) | SERIAL_RX_Buffer[2]);
      pdca_load_channel(PDCA_CHANNEL_RX_USART, (void *)&(SERIAL_RX_Buffer[3]),rx_size-2 );
      pdca_enable(PDCA_CHANNEL_RX_USART);
      pdca_enable_interrupt_transfer_complete(PDCA_CHANNEL_RX_USART);
    }

    if(SERIAL_RX_index > 3) {
      // Must not occurred, require a sync
      SERIAL_RX_index=0;
    }
  }
Example #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;
}
/*! \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);
}
Example #6
0
File: lin.c Project: 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

}
Example #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
  }
}
Example #8
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);
  }
}
Example #9
0
File: ms3.c Project: 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;
}
Example #10
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;
}