int main( void )
{   
    KEY_PORT.DIR = 0x00; // Set direction as input.
    LED_PORT.DIR = 0xFF;

    PORTCFG.MPCMASK = 0xFF;
    LED_PORT.PIN0CTRL |= (LED_PORT.PIN0CTRL ) | PORT_INVEN_bm;
               
    // Configure all keys to be active when pressed (inverted).
    PORTCFG.MPCMASK = 0xFF;
    KEY_PORT.PIN0CTRL |= (KEY_PORT.PIN0CTRL ) | PORT_INVEN_bm;

    // Enable overflow interrupt
    TCC0.INTCTRLA = ( TCC0.INTCTRLA & TC0_OVFINTLVL_gm ) | TC_OVFINTLVL_MED_gc; 

    DMA_Setup(DMA_CHANNEL_0, SineWaveHighRes, (void *) &DACB.CH0DATA, SINE_WAVE_HIGH_RES * 2, DMA_REPEAT_FOREVER);

    DMA_Setup(DMA_CHANNEL_1, SineWaveLowRes,  (void *) &DACB.CH1DATA, SINE_WAVE_LOW_RES  * 2, DMA_REPEAT_FOREVER);
 
    DAC_DualChannel_Enable(  &DACB,
	                         DAC_REFSEL_AVCC_gc,
	                         false, // Right adjusted
 	                         DAC_CONINTVAL_4CLK_gc,
	                         DAC_REFRESH_32CLK_gc 
                          );

    DMA_EnableChannel( DMA_CHANNEL_0 );
    DMA_EnableChannel( DMA_CHANNEL_1 );
    
    // Enable medium interrupt level in PMIC and enable global interrupts.
	PMIC.CTRL |= PMIC_MEDLVLEN_bm;
    sei();

	while (1) 
    {
        if(KEY_PORT.IN == 0x00)
        {
            // No Timer to trigger DMA: No Signal
             TCC0.CTRLA = ( TCC0.CTRLA & ~TC0_CLKSEL_gm ) | TC_CLKSEL_OFF_gc;
        }
        else
        {
            // Enable Timer C0, prescaler div1 means Main Clock (2MHz).
            TCC0.CTRLA = ( TCC0.CTRLA & ~TC0_CLKSEL_gm ) | TC_CLKSEL_DIV1_gc;

    	    if(KEY_PORT.IN & 0x01)
            {
                TCC0.PER = TIMER_C0_PERIOD;

                while(KEY_PORT.IN & 0x01)
                {                    
                    LED_PORT.OUTSET = 0x01;                  
                }
            }            
            LED_PORT.OUT = 0x00;
        }
    }
}
Esempio n. 2
0
//------------------------------------------------------------------------------
/// Starts buffer transfer on the given channel
/// \param channel Particular channel number.
/// \param size Total transfer size in byte.
/// \param callback Optional callback function.
/// \param polling Polling channel status enable.
//------------------------------------------------------------------------------
unsigned char DMAD_BufferTransfer(unsigned char channel, 
                                  unsigned int size, 
                                  DmaCallback callback, 
                                  unsigned char polling)
{
    DmaTransfer *pTransfer = &(dmad.transfers[channel]);
    // Check that no transfer is pending on the channel
    if (pTransfer-> transferSize > 0 ) {
        TRACE_ERROR("DAM transfer is already pending\n\r");
        return DMAD_ERROR_BUSY;
    }
    pTransfer->status = DMAD_ERROR_BUSY; 
    pTransfer->transferSize = size;
    pTransfer->callback = callback; 
    
    if(!polling){
        DMA_EnableIt(DMA_BTC << channel);
    }
    // Enable the channel.
    DMA_EnableChannel(channel);
    
    if(polling){
        while ((DMA_GetChannelStatus() & (DMA_ENA << channel)) == (DMA_ENA << channel));
        pTransfer->callback();
        DMA_DisableChannel(channel);
    }
    return 0;
}
Esempio n. 3
0
//------------------------------------------------------------------------------
/// Starts buffer transfer on the given channel
/// \param channel Particular channel number.
/// \param size Total transfer size in byte.
/// \param callback Optional callback function.
/// \param polling Polling channel status enable.
//------------------------------------------------------------------------------
U8 DMAD_BufferTransfer(U8 channel, U32 size, DmaCallback callback, U8 polling)
{
	DmaTransfer *pTransfer = &(dmad.transfers[channel]);
	
	if (pTransfer-> transferSize > 0 ) // Check that no transfer is pending on the channel
	{
		DEBUG_MSG("DAM transfer is already pending");
		return DMAD_ERROR_BUSY;
	}
	pTransfer->status = DMAD_ERROR_BUSY; 
	pTransfer->transferSize = size;
	pTransfer->callback = callback; 

	if(!polling)
	{
		DMA_EnableIt(0x1 << channel);
	}
	DMA_EnableChannel(channel); // Enable the channel.
	if(polling)
	{
		while ((DMA_GetChannelStatus() & (0x1 << channel)) == (0x1 << channel));
		if (pTransfer->callback)
		{
			pTransfer->callback();
		}
		pTransfer->transferSize = 0;
		DMA_DisableChannel(channel);
	}
	return 0;
}
Esempio n. 4
0
void dma_init(uint32_t dmaNdx, uint32_t chnNdx){
	assert(dmaNdx == 0);
	uint32_t bmOldChnEn;

	HAL_ENTER_CRITICAL();
		bmOldChnEn = dma_idle.bmChnEn[dmaNdx];
		dma_idle.bmChnEn[dmaNdx] = bmOldChnEn | 1 << chnNdx;
		if (0 == bmOldChnEn)
			DMA_Init(DMA0);
		HAL_NVIC_SetPriority(DMA0_IRQn, IRQ_PRI_DMA, IRQ_SUBPRI_DMA);
	HAL_LEAVE_CRITICAL();
	
	DMA_EnableChannel(DMA0, chnNdx);
}
Esempio n. 5
0
/*  AsyncMemCopy
 *
 *  Block size 0 = 64k. Enable the DMA channel to use first. 
 *  Then setup channel for copying data, increasing addresses, 
 *  no address pointer reload, with 8-byte bursts.
 *
 * \note This function is asynchronous and DOES NOT wait for 
 *       completion.This must be handled by the program 
 *       calling this function. 
 *       In this example, an interrupt.
 *
 */
void AsyncMemCopy( const void * src,
                   void * dest,
                   uint16_t blockSize,
                   DMA_CH_t * dmaChannel )
{
	DMA_EnableChannel( dmaChannel );

	DMA_SetupBlock( dmaChannel,
	                src,
	                DMA_CH_SRCRELOAD_NONE_gc,
	                DMA_CH_SRCDIR_INC_gc,
	                dest,
	                DMA_CH_DESTRELOAD_NONE_gc,
	                DMA_CH_DESTDIR_INC_gc,
	                blockSize,
	                DMA_CH_BURSTLEN_8BYTE_gc,
	                0,
	                false );

	DMA_StartTransfer( dmaChannel );
}
Esempio n. 6
0
//------------------------------------------------------------------------------
/// Starts buffer transfer on the given dwChannel
/// \param dwChannel Particular dwChannel number.
/// \param size Total transfer size in byte.
/// \param callback Optional callback function.
/// \param polling Polling dwChannel status enable.
//------------------------------------------------------------------------------
extern uint32_t DMAD_BufferTransfer( uint32_t dwChannel, uint32_t dwSize,
                                     DmaCallback callback, uint32_t dwPolling )
{
    DmaTransfer *pTransfer = &(dmad.transfers[dwChannel]) ;

    // Check that no transfer is pending on the dwChannel
    if ( pTransfer-> transferSize > 0 )
    {
        TRACE_ERROR( "DAM transfer is already pending\n\r" ) ;

        return DMAD_ERROR_BUSY ;
    }

    pTransfer->status = DMAD_ERROR_BUSY ;
    pTransfer->transferSize = dwSize ;
    pTransfer->callback = callback ;

    if ( dwPolling == 0 )
    {
        DMA_EnableIt( DMAC, DMA_BTC << dwChannel ) ;
    }

    // Enable the dwChannel.
    DMA_EnableChannel( DMAC, dwChannel ) ;

    if ( dwPolling != 0 )
    {
        while ( (DMA_GetChannelStatus( DMAC ) & (DMAC_CHSR_ENA0 << dwChannel)) == (DMAC_CHSR_ENA0 << dwChannel)) ;

        if ( pTransfer->callback )
        {
            pTransfer->callback() ;
        }
        pTransfer->transferSize = 0 ;
        DMA_DisableChannel( DMAC, dwChannel ) ;
    }

    return 0 ;
}
Esempio n. 7
0
bool MemCopy( const void * src, void * dest, uint16_t blockSize,
                          DMA_CH_t * dmaChannel )
{
    uint8_t flags = 0;

	DMA_EnableChannel( dmaChannel );
	DMA_SetupBlock( dmaChannel,
	                src,
	                DMA_CH_SRCRELOAD_NONE_gc,
	                DMA_CH_SRCDIR_INC_gc,
	                dest,
	                DMA_CH_DESTRELOAD_NONE_gc,
	                DMA_CH_DESTDIR_INC_gc,
	                blockSize,
	                DMA_CH_BURSTLEN_8BYTE_gc,
	                0, 
	                false ); // no repeat

	DMA_StartTransfer( dmaChannel );

    // Wait until the completion or error flag is set. The flags
	// must be cleared manually.
    do {
        flags = DMA_ReturnStatus_non_blocking( dmaChannel );
    } while ( flags == 0 );

	// Clear flags
    DMA.CH0.CTRLB |= ( flags );

    // Check if error flag is set
    if ( ( flags & DMA_CH_ERRIF_bm ) != 0x00 ) 
    {
        return true;
    } else 
    {
        return false;
    }
}
Esempio n. 8
0
/*! \brief Example of a repeated block memory copy operation.
 *
 *  Block size 0 = 64k. Enable the DMA channel to use first and the channel
 *  will be disabled automatically. A parameter check to avoid illegal values.
 *  Setup channel for copying data, increasing addresses, no address pointer
 *  reload, with 8-byte bursts.
 *
 * \note This function wait until the transfer is complete and use a blocking
 *       function which also makes this function blocking, hence the function
 *       will dead-lock if the completion or error flag never get set.
 *
 * \retval true   if success.
 * \retval false  if failure.
 */
bool MultiBlockMemCopy( const void * src, void * dest, uint16_t blockSize,
                          uint8_t repeatCount, volatile DMA_CH_t * dmaChannel )
{
	uint8_t flags;

	DMA_EnableChannel( dmaChannel );
	DMA_SetupBlock( dmaChannel,
	                src,
	                DMA_CH_SRCRELOAD_NONE_gc,
	                DMA_CH_SRCDIR_INC_gc,
	                dest,
	                DMA_CH_DESTRELOAD_NONE_gc,
	                DMA_CH_DESTDIR_INC_gc,
	                blockSize,
	                DMA_CH_BURSTLEN_8BYTE_gc,
	                repeatCount,
	                true );

	DMA_StartTransfer( dmaChannel );

	/* Wait until the completion or error flag is set. The flags
	 * must be cleared manually.
	 */
	do {
		flags = DMA_ReturnStatus_non_blocking( dmaChannel );
	} while ( flags == 0);

	dmaChannel->CTRLB |= ( flags );

	/* Check if error flag is set. */
	if ( ( flags & DMA_CH_ERRIF_bm ) != 0x00 ) {
		return false;
	} else {
		return true;
	}
}
int main(void)
{
	facilitatePowersaving();

	// Configure switches
	PORTCFG.MPCMASK = 0xff; // Configure several PINxCTRL registers at the same time
	SWITCHPORT.PIN0CTRL = (SWITCHPORT.PIN0CTRL & ~PORT_OPC_gm) | PORT_OPC_PULLUP_gc; //Enable pull-up to get a defined level on the switches

	SWITCHPORT.DIRCLR = 0xff; // Set port as input

	// Configure LEDs
	PORTCFG.MPCMASK = 0xff; // Configure several PINxCTRL registers at the same time
	LEDPORT.PIN0CTRL = PORT_INVEN_bm; // Invert input to turn the leds on when port output value is 1

	LEDPORT.DIRSET = 0xff; 	// Set port as output
	LEDPORT.OUT = 0x00;  // Set initial value


	// Set up ADCB0 on PB0 to read temp sensor. More of this can be achieved by using driver from appnote AVR1300
	PORTQ.PIN2CTRL = (PORTQ.PIN2CTRL & ~PORT_OPC_gm) | PORT_OPC_PULLDOWN_gc;	// This pin must be grounded to "enable" NTC-resistor
	PORTB.DIRCLR = PIN0;
	PORTB.PIN0CTRL = (PORTB.PIN0CTRL & ~PORT_OPC_gm);

	ADC_CalibrationValues_Load(&ADCB);  // Load factory calibration data for ADC
	ADCB.CH0.CTRL = (ADCB.CH0.CTRL & ~ADC_CH_INPUTMODE_gm) | ADC_CH_INPUTMODE_SINGLEENDED_gc; // Single ended input
	ADCB.CH0.MUXCTRL = (ADCB.CH0.MUXCTRL & ~ADC_CH_MUXPOS_gm) | ADC_CH_MUXPOS_PIN0_gc; // Pin 0 is input	
	ADCB.REFCTRL = (ADCB.REFCTRL & ~ADC_REFSEL_gm) | ADC_REFSEL_VCC_gc;	// Internal AVCC/1.6 as reference

	ADCB.CTRLB |= ADC_FREERUN_bm; // Free running mode
	ADCB.PRESCALER = (ADCB.PRESCALER & ~ADC_PRESCALER_gm) | ADC_PRESCALER_DIV512_gc; // Divide clock by 1024.
	ADCB.CTRLB = (ADCB.CTRLB & ~ADC_RESOLUTION_gm) | ADC_RESOLUTION_8BIT_gc; // Set 8 bit resolution
	ADCB.CTRLA |= ADC_ENABLE_bm; // Enable ADC
	

	// Set up DMA CH0 to transfer from ADC to LEDS. We only read low byte.
	DMA_Enable();
	DMA_SetupBlock( 
                    &DMA.CH0,
			        (void const *) &(ADCB.CH0RES), 
                    DMA_CH_SRCRELOAD_NONE_gc, 
                    DMA_CH_SRCDIR_FIXED_gc,
			        (void const *) &(LEDPORT.OUT), 
                    DMA_CH_DESTRELOAD_NONE_gc, 
                    DMA_CH_DESTDIR_FIXED_gc,
			        1, 
                    DMA_CH_BURSTLEN_1BYTE_gc, 
                    0,
                    true
                );
    DMA_EnableSingleShot( &DMA.CH0 );
	DMA_SetTriggerSource( &DMA.CH0, DMA_CH_TRIGSRC_ADCB_CH0_gc ); // ADC Channel 0 is trigger source.
	


	// Set up interrupt on button 0, or else we can't come back from IDLE
	SWITCHPORT.INTCTRL = (SWITCHPORT.INTCTRL & ~PORT_INT0LVL_gm) | PORT_INT0LVL_LO_gc;
	SWITCHPORT.INT0MASK = SWITCHMASK_ACTIVE;
	SWITCHPORT.PIN0CTRL = (SWITCHPORT.PIN0CTRL & ~PORT_ISC_gm) | PORT_ISC_FALLING_gc;


	// Enable low interrupt level in PMIC and enable global interrupts.
	PMIC.CTRL |= PMIC_LOLVLEN_bm;
	sei();

	// Main loop.
	while (1) {

		if ((SWITCHPORT.IN & SWITCHMASK_ACTIVE) == 0x00)
		{
		// Button 0 pressed. Enter ACTIVE mode again.
			DMA_DisableChannel( &DMA.CH0 );

			SLEEP.CTRL &= ~SLEEP_SEN_bm;	// Disable sleep. sleep() is now ineffective.

		} else if ((SWITCHPORT.IN & SWITCHMASK_IDLE) == 0x00)	
	    {	
		// Button 1 pressed. Enter Idle mode
			DMA_EnableChannel( &DMA.CH0 );			

			// Set and enable sleep.
			SLEEP.CTRL = (SLEEP.CTRL & ~SLEEP_SMODE_gm) | SLEEP_SMODE_IDLE_gc;
			SLEEP.CTRL |= SLEEP_SEN_bm; // Enable sleep.

		} else if (SLEEP.CTRL & SLEEP_SEN_bm) {
			 	// We are in wanting-to-sleep mode, but were awake.
				sleep();
	
		} else { 
			// Do active sampling and transfer of ADC data.
			LEDPORT.OUT = ADCB.CH0RES & 0xFF;
		}

	}
	
}