2.8.2.1.2 Code

Add to the main application source file, outside of any functions:
struct adc_module adc_instance;
#define ADC_SAMPLES 128
uint16_t adc_result_buffer[ADC_SAMPLES];
Callback function:
volatile bool adc_read_done = false;

void adc_complete_callback(
        struct adc_module *const module)
{
    adc_read_done = true;
}
Copy-paste the following setup code to your user application:
void configure_adc(void)
{
    struct adc_config config_adc;
    adc_get_config_defaults(&config_adc);

#if (!SAML21) && (!SAML22) && (!SAMC21)
    config_adc.gain_factor     = ADC_GAIN_FACTOR_DIV2;
#endif
    config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV8;
    config_adc.reference       = ADC_REFERENCE_INTVCC1;
#if (SAMC21)
    config_adc.positive_input  = ADC_POSITIVE_INPUT_PIN5;
#else
    config_adc.positive_input  = ADC_POSITIVE_INPUT_PIN6;
#endif
    config_adc.resolution      = ADC_RESOLUTION_12BIT;

#if (SAMC21)
    adc_init(&adc_instance, ADC1, &config_adc);
#else
    adc_init(&adc_instance, ADC, &config_adc);
#endif

    adc_enable(&adc_instance);
}

void configure_adc_callbacks(void)
{
    adc_register_callback(&adc_instance,
            adc_complete_callback, ADC_CALLBACK_READ_BUFFER);
    adc_enable_callback(&adc_instance, ADC_CALLBACK_READ_BUFFER);
}
Add to user application initialization (typically the start of main()):
configure_adc();
configure_adc_callbacks();