8 Appendix

Generating Constant Analog Signal Code Example

    /* 3.33 MHz (needed for delay) */
    #define F_CPU                         (3333333UL)
    /* DAC value */
    #define DAC_EXAMPLE_VALUE             (0x20)
    /* VREF Startup time */
    #define VREF_STARTUP_MICROS           (25)

    #include <avr/io.h>
    #include <util/delay.h>
    
    void VREF_init(void);
    void DAC0_init(void);
    void DAC0_setVal(uint8_t val);

    void VREF_init(void)
    {
        /* Voltage reference at 4.34V */
        VREF.CTRLA |= VREF_DAC0REFSEL_4V34_gc;
        /* DAC0/AC0 reference enable: enabled */
        VREF.CTRLB |= VREF_DAC0REFEN_bm;
        /* Wait VREF start-up time */
        _delay_us(VREF_STARTUP_MICROS);
    }

    void DAC0_init(void)
    {
        /* Disable digital input buffer */
        PORTA.PIN6CTRL &= ~PORT_ISC_gm;
        PORTA.PIN6CTRL |= PORT_ISC_INPUT_DISABLE_gc;
        /* Disable pull-up resistor */
        PORTA.PIN6CTRL &= ~PORT_PULLUPEN_bm;

        /* Enable DAC, Output Buffer, Run in Standby */
        DAC0.CTRLA = DAC_ENABLE_bm | DAC_OUTEN_bm | DAC_RUNSTDBY_bm;
    }

    void DAC0_setVal(uint8_t val)
    {
        DAC0.DATA = val;
    }

    int main(void)
    {
        VREF_init();
        DAC0_init();

        DAC0_setVal(DAC_EXAMPLE_VALUE);

        while (1) 
        {
            ;
        }
    }

Generating Sine Wave Signal Code Example

    /* 3.33 MHz (needed for delay) */
    #define F_CPU                            (3333333UL)
    /* VREF Startup time */
    #define VREF_STARTUP_MICROS              (25)
    /* Number of steps for a sine wave period */
    #define SINE_WAVE_STEPS                  (100)
    /* Sine wave amplitude */
    #define SINE_AMPLITUDE                   (127)
    /* Sine wave DC offset */
    #define SINE_DC_OFFSET                   (128)
    /* 2*PI */
    #define M_2PI                            (2 * M_PI)
    /* Frequency of the sine wave */
    #define OUTPUT_FREQ                      (50)
    /* Step delay for the synthesis loop */
    #define STEP_DELAY_MICROS                ((1000000 / OUTPUT_FREQ) / SINE_WAVE_STEPS)

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

    /* Buffer to store the sine wave samples */
    uint8_t sineWave[SINE_WAVE_STEPS];
    
    void sineWaveInit(void);
    void VREF_init(void);
    void DAC0_init(void);
    void DAC0_setVal(uint8_t val);

    void sineWaveInit(void)
    {
        for(uint16_t i = 0; i < SINE_WAVE_STEPS; i++)
        {
            sineWave[i] = SINE_DC_OFFSET + SINE_AMPLITUDE * sin(i * M_2PI / SINE_WAVE_STEPS);
        }
    }

    void VREF_init(void)
    {
        /* Voltage reference at 4.34V */
        VREF.CTRLA |= VREF_DAC0REFSEL_4V34_gc;
        /* DAC0/AC0 reference enable: enabled */
        VREF.CTRLB |= VREF_DAC0REFEN_bm;
        /* Wait VREF start-up time */
        _delay_us(VREF_STARTUP_MICROS);
    }

    void DAC0_init(void)
    {
        /* Disable digital input buffer */
        PORTA.PIN6CTRL &= ~PORT_ISC_gm;
        PORTA.PIN6CTRL |= PORT_ISC_INPUT_DISABLE_gc;
        /* Disable pull-up resistor */
        PORTA.PIN6CTRL &= ~PORT_PULLUPEN_bm;

        /* default value */
        DAC0.DATA = SINE_DC_OFFSET;
        /* Enable DAC, Output Buffer, Run in Standby */
        DAC0.CTRLA = DAC_ENABLE_bm | DAC_OUTEN_bm | DAC_RUNSTDBY_bm;
    }

    void DAC0_setVal(uint8_t val)
    {
        DAC0.DATA = val;
    }

    int main(void)
    {
        uint16_t i = 0;

        VREF_init();
        DAC0_init();

        sineWaveInit();

        while (1)
        {
            DAC0_setVal(sineWave[i++]);    
            i = i % SINE_WAVE_STEPS;        
            _delay_us(STEP_DELAY_MICROS);
        }
    }

Reading DAC Internally With ADC Code Example

    /* 3.33 MHz (needed for delay) */
    #define F_CPU                         (3333333UL)  
    /* VREF Startup time */
    #define VREF_STARTUP_MICROS           (25)

    #include <avr/io.h>
    #include <util/delay.h>
    
    void VREF_init(void);
    void DAC0_init(void);
    void ADC0_init(void);
    uint16_t ADC0_read(void);
    void DAC0_setVal(uint8_t val);

    void VREF_init(void)
    {
        /* Voltage reference at 4.34V */
        VREF_CTRLA |= VREF_DAC0REFSEL_4V34_gc; 
        /* DAC0/AC0 reference enable: enabled */
        VREF_CTRLB |= VREF_DAC0REFEN_bm;
        /* Voltage reference at 4.34V */
        VREF_CTRLA |= VREF_ADC0REFSEL_4V34_gc; 
        /* ADC0 reference enable: enabled */
        VREF_CTRLB |= VREF_ADC0REFEN_bm;    
        /* Wait VREF start-up time */
        _delay_us(VREF_STARTUP_MICROS);
    }

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

    void ADC0_init(void)
    {
        ADC0.CTRLC = ADC_PRESC_DIV4_gc      /* CLK_PER divided by 4 */
                    | ADC_REFSEL_INTREF_gc  /* VDD reference */
                    | ADC_SAMPCAP_bm;       /* Sample Capacitance Selection: enabled */

        ADC0.CTRLA = ADC_ENABLE_bm          /* ADC Enable: enabled */
                    | ADC_RESSEL_10BIT_gc;  /* 10-bit mode */

        /* Select ADC channel */
        ADC0.MUXPOS = ADC_MUXPOS_DAC0_gc;
    }

    uint16_t ADC0_read(void)
    {
        /* Start ADC conversion */
        ADC0.COMMAND = ADC_STCONV_bm;

        /* Wait until ADC conversion done */
        while ( !(ADC0.INTFLAGS & ADC_RESRDY_bm) )
        {
            ;
        }

        /* Clear the interrupt flag by writing 1: */
        ADC0.INTFLAGS = ADC_RESRDY_bm;

        return ADC0.RES;
    }

    void DAC0_setVal(uint8_t val)
    {
        DAC0.DATA = val;
    }

    int main(void)
    {
        uint8_t dacVal = 0;
        volatile uint16_t adcVal = 0;

        VREF_init();
        DAC0_init();
        ADC0_init();

        /* Wait VREF start-up time */
        _delay_us(VREF_STARTUP_MICROS);

        DAC0_setVal(dacVal);

        while (1) 
        {
            adcVal = ADC0_read();

            /* do something with the adcVal */

            dacVal++;
            DAC0_setVal(dacVal); 
        }
    }

Using DAC as Negative Input for AC Code Example

    /* 3.33 MHz (needed for delay) */
    #define F_CPU                         (3333333UL)
    /* 1.4V output @ VREF = 1.5V */
    #define DAC_DATA_1V4                  (239)
    /* VREF Startup time */
    #define VREF_STARTUP_MICROS           (25)

    #include <avr/io.h>
    #include <util/delay.h>
    
    void VREF_init(void);
    void DAC0_setVal(uint8_t val);
    void DAC0_init(void);
    void AC0_init(void);

    void VREF_init(void)
    {
        /* Voltage reference at 1.5V */
        VREF.CTRLA |= VREF_DAC0REFSEL_1V5_gc;
        /* DAC0/AC0 reference enable: enabled */
        VREF.CTRLB |= VREF_DAC0REFEN_bm;
        /* Wait VREF start-up time */
        _delay_us(VREF_STARTUP_MICROS);
    }

    void DAC0_setVal(uint8_t val)
    {
        DAC0.DATA = val;
    }

    void DAC0_init(void)
    {
        /* Disable digital input buffer */
        PORTA.PIN6CTRL &= ~PORT_ISC_gm;
        PORTA.PIN6CTRL |= PORT_ISC_INPUT_DISABLE_gc;
        /* Disable pull-up resistor */
        PORTA.PIN6CTRL &= ~PORT_PULLUPEN_bm;

        /* Enable DAC, Output Buffer, Run in Standby */
        DAC0.CTRLA = DAC_ENABLE_bm | DAC_OUTEN_bm | DAC_RUNSTDBY_bm;
    }

    void AC0_init(void)
    {
        /* Negative input from DAC0 */
        /* Positive input from pin PA7 */
        AC0.MUXCTRLA = AC_MUXNEG_DAC_gc
                    | AC_MUXPOS_PIN0_gc;

        /* Enable, Output on PA5, Low Power mode */
        AC0.CTRLA = AC_ENABLE_bm
                    | AC_OUTEN_bm
                    | AC_RUNSTDBY_bm
                    | AC_LPMODE_bm;
    }

    int main(void)
    {
        /* Voltage divider -> VDD/2 input on PA7 */
        /* AC output on LED on PA5 */
        /* LED turns OFF when battery is below 2.8V (PA7 below 1.4V) */

        VREF_init();
        DAC0_init();
        AC0_init();

        /* 1.4V output @ VREF = 1.5V */
        DAC0_setVal(DAC_DATA_1V4);

        while (1)
        {
            ;
        }
    }