8 Appendix

Generating Constant Analog Signal Code

/* 4 MHz (needed for delay function) */
#define F_CPU                    (4000000UL)

#include <avr/io.h>
#include <util/delay.h>

/* DAC Value */
#define DAC_EXAMPLE_VALUE        (0x258)
/* VREF start-up time */
#define VREF_STARTUP_TIME        (50)
/* Mask needed to get the 2 LSb for DAC Data Register */
#define LSB_MASK                 (0x03)

static void VREF_init(void);
static void DAC0_init(void);
static void DAC0_setVal(uint16_t value);

static void VREF_init(void)
{
    VREF.DAC0REF = VREF_REFSEL_2V048_gc /* Select the 2.048V Internal Voltage Reference for DAC */
                 | VREF_ALWAYSON_bm;    /* Set the Voltage Reference in Always On mode */
    /* Wait VREF start-up time */
    _delay_us(VREF_STARTUP_TIME);
}

static void DAC0_init(void)
{
    /* Disable digital input buffer */
    PORTD.PIN6CTRL &= ~PORT_ISC_gm;
    PORTD.PIN6CTRL |= PORT_ISC_INPUT_DISABLE_gc;
    /* Disable pull-up resistor */
    PORTD.PIN6CTRL &= ~PORT_PULLUPEN_bm;   
    DAC0.CTRLA = DAC_ENABLE_bm          /* Enable DAC */
               | DAC_OUTEN_bm           /* Enable output buffer */
               | DAC_RUNSTDBY_bm;       /* Enable Run in Standby mode */
}

static void DAC0_setVal(uint16_t value)
{
    /* Store the two LSbs in DAC0.DATAL */
    DAC0.DATAL = (value & LSB_MASK) << 6;
    /* Store the eight MSbs in DAC0.DATAH */
    DAC0.DATAH = value >> 2;
}

int main(void)
{
    VREF_init();
    DAC0_init();
    
    DAC0_setVal(DAC_EXAMPLE_VALUE);
    
    while (1)
    {
        ;
    }
}

Generating Sine Wave Signal Code

/* 4 MHz (needed for delay function) */
#define F_CPU                   (4000000UL)

#include <avr/io.h>
#include <util/delay.h>
#include <math.h>

/* VREF start-up time */
#define VREF_STARTUP_TIME       (50)
/* Mask needed to get the 2 LSb for DAC Data Register */
#define LSB_MASK                (0x03)
/* Number of samples for a sine wave period */
#define SINE_PERIOD_STEPS       (100)
/* Sine wave amplitude */
#define SINE_AMPLITUDE          (511)
/* Sine wave DC offset */
#define SINE_DC_OFFSET          (512)
/* Frequency of the sine wave */
#define SINE_FREQ               (100)
/* Step delay for the loop */
#define STEP_DELAY_TIME         ((1000000 / SINE_FREQ) / SINE_PERIOD_STEPS)

static void sineWaveInit(void);
static void VREF_init(void);
static void DAC0_init(void);
static void DAC0_setVal(uint16_t value);

/* Buffer to store the sine wave samples */
uint16_t sineWave[SINE_PERIOD_STEPS];

static void sineWaveInit(void)
{
    uint8_t i;
    for(i = 0; i < SINE_PERIOD_STEPS; i++)
    {
        sineWave[i] = SINE_DC_OFFSET + SINE_AMPLITUDE * sin(2 * M_PI * i / SINE_PERIOD_STEPS);
    }
}

static void VREF_init(void)
{
    VREF.DAC0REF = VREF_REFSEL_2V048_gc /* Select the 2.048V Internal Voltage Reference for DAC */
                 | VREF_ALWAYSON_bm;    /* Set the Voltage Reference in Always On mode */
    /* Wait VREF start-up time */
    _delay_us(VREF_STARTUP_TIME);
}

static void DAC0_init(void)
{
    /* Disable digital input buffer */
    PORTD.PIN6CTRL &= ~PORT_ISC_gm;
    PORTD.PIN6CTRL |= PORT_ISC_INPUT_DISABLE_gc;
    /* Disable pull-up resistor */
    PORTD.PIN6CTRL &= ~PORT_PULLUPEN_bm;
    DAC0.CTRLA = DAC_ENABLE_bm          /* Enable DAC */
               | DAC_OUTEN_bm           /* Enable output buffer */
               | DAC_RUNSTDBY_bm;       /* Enable Run in Standby mode */
}

static void DAC0_setVal(uint16_t value)
{
    /* Store the two LSbs in DAC0.DATAL */
    DAC0.DATAL = (value & LSB_MASK) << 6;
    /* Store the eight MSbs in DAC0.DATAH */
    DAC0.DATAH = value >> 2;
}

int main(void)
{
    uint8_t sineIndex = 0;
    
    VREF_init();
    DAC0_init();
    
    sineWaveInit();
    
    while (1)
    {
        DAC0_setVal(sineWave[sineIndex++]);
        if(sineIndex == SINE_PERIOD_STEPS)
            sineIndex = 0;
        _delay_us(STEP_DELAY_TIME);
    }
}

Reading the DAC Internally with the ADC Code

/* 4 MHz (needed for delay function) */
#define F_CPU                   (4000000UL)

#include <avr/io.h>
#include <util/delay.h>

/* VREF start-up time */
#define VREF_STARTUP_TIME       (50)
/* Mask needed to get the 2 LSb for DAC Data Register */
#define LSB_MASK                (0x03)

static void VREF_init(void);
static void DAC0_init(void);
static void DAC0_setVal(uint16_t val);
static void ADC0_init(void);
static uint16_t ADC0_read(void);

static void VREF_init(void)
{
    VREF.DAC0REF = VREF_REFSEL_2V048_gc /* Select the 2.048V Internal Voltage Reference for DAC */
                 | VREF_ALWAYSON_bm;    /* Set the Voltage Reference in Always On mode */   
    VREF.ADC0REF = VREF_REFSEL_2V048_gc /* Select the 2.048V Internal Voltage Reference for ADC */
                 | VREF_ALWAYSON_bm;    /* Set the Voltage Reference in Always On mode */
    /* Wait VREF start-up time */
    _delay_us(VREF_STARTUP_TIME);
}

static void DAC0_init(void)
{
    /* Enable DAC */
    DAC0.CTRLA = DAC_ENABLE_bm;
}

static void DAC0_setVal(uint16_t value)
{
    /* Store the two LSbs in DAC0.DATAL */
    DAC0.DATAL = (value & LSB_MASK) << 6;
    /* Store the eight MSbs in DAC0.DATAH */
    DAC0.DATAH = value >> 2;
}

static void ADC0_init(void)
{
    /* CLK_PER divided by 2 */
    ADC0.CTRLC = ADC_PRESC_DIV2_gc;
    ADC0.CTRLA = ADC_ENABLE_bm          /* Enable ADC */
               | ADC_RESSEL_12BIT_gc;   /* Use 12-bit resolution */
    /* Select ADC channel */
    ADC0.MUXPOS = ADC_MUXPOS_DAC0_gc
}

static uint16_t ADC0_read(void)
{
    /* Start conversion */
    ADC0.COMMAND = ADC_STCONV_bm;
    /* Wait until ADC conversion is done */
    while(!(ADC0.INTFLAGS & ADC_RESRDY_bm))
    {
        ;
    }
    /* The interrupt flag is cleared when the conversion result is accessed */
    return ADC0.RES;
}


int main(void)
{
    uint16_t dacVal = 0;
    volatile uint16_t adcVal = 0;
    
    VREF_init();
    DAC0_init();
    ADC0_init();
    
    while (1)
    {
        adcVal = ADC0_read();
        
        /* do something with adcVal */
        
        dacVal++;
        DAC0_setVal(dacVal);
    }
}

Generating Amplitude Modulation Signal Code

/* 4 MHz (needed for delay function) */
#define F_CPU                   (4000000UL)

#include <avr/io.h>
#include <util/delay.h>
#include <math.h>

/* VREF start-up time */
#define VREF_STARTUP_TIME       (50)
/* Mask needed to get the 2 LSb for DAC Data Register */
#define LSB_MASK                (0x03)
/* Number of samples for a sine wave period */
#define SINE_PERIOD_STEPS       (100)
/* Sine wave amplitude */
#define SINE_AMPLITUDE          (511)
/* Sine wave DC offset */
#define SINE_DC_OFFSET          (512)
/* Frequency of the sine wave */
#define SINE_FREQ               (50)
/* Step delay for the loop */
#define STEP_DELAY_TIME         ((1000000 / SINE_FREQ) / SINE_PERIOD_STEPS)

static void PORT_init (void);
static void sineWaveInit(void);
static void VREF_init(void);
static void DAC0_init(void);
static void DAC0_setVal(uint16_t val);

/* Buffer to store the sine wave samples */
uint16_t sineWave[SINE_PERIOD_STEPS];

static void PORT_init (void)
{
    /* Set the VREFA pin (PD7) as input */
    PORTD.DIRCLR |= PIN7_bm;
}

static void sineWaveInit(void)
{
    uint8_t i;
    for(i = 0; i < SINE_PERIOD_STEPS; i++)
    {
        sineWave[i] = SINE_DC_OFFSET + SINE_AMPLITUDE * sin(2 * M_PI * i / SINE_PERIOD_STEPS);
    }
}

static void VREF_init(void)
{
    VREF.DAC0REF = VREF_REFSEL_VREFA_gc /* Select the External Reference from VREFA pin */
                 | VREF_ALWAYSON_bm;    /* Set the Voltage Reference in Always On mode */
    /* Wait VREF start-up time */
    _delay_us(VREF_STARTUP_TIME);
}

static void DAC0_init(void)
{
    /* Disable digital input buffer */
    PORTD.PIN6CTRL &= ~PORT_ISC_gm;
    PORTD.PIN6CTRL |= PORT_ISC_INPUT_DISABLE_gc;
    /* Disable pull-up resistor */
    PORTD.PIN6CTRL &= ~PORT_PULLUPEN_bm;
    DAC0.CTRLA = DAC_ENABLE_bm          /* Enable DAC */
               | DAC_OUTEN_bm           /* Enable output buffer */
               | DAC_RUNSTDBY_bm;       /* Enable Run in Standby mode */
}

static void DAC0_setVal(uint16_t value)
{
    /* Store the two LSbs in DAC0.DATAL */
    DAC0.DATAL = (value & LSB_MASK) << 6;
    /* Store the eight MSbs in DAC0.DATAH */
    DAC0.DATAH = value >> 2;
}

int main(void)
{
    uint8_t sineIndex = 0;
    
    PORT_init();
    VREF_init();
    DAC0_init();
    
    sineWaveInit();
    
    while (1)
    {
        DAC0_setVal(sineWave[sineIndex++]);
        if(sineIndex == SINE_PERIOD_STEPS)
            sineIndex = 0;
        _delay_us(STEP_DELAY_TIME);
    }
}