/*
 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef _HARDWARE_ADC_H_
#define _HARDWARE_ADC_H_

#include "pico.h"
#include "hardware/structs/adc.h"
#include "hardware/gpio.h"

/** \file hardware/adc.h
 *  \defgroup hardware_adc hardware_adc
 *
 * Analog to Digital Converter (ADC) API
 *
 * The RP2040 has an internal analogue-digital converter (ADC) with the following features:
 * - SAR ADC
 * - 500 kS/s (Using an independent 48MHz clock)
 * - 12 bit (9.5 ENOB)
 * - 5 input mux:
 *  - 4 inputs that are available on package pins shared with GPIO[29:26]
 *  - 1 input is dedicated to the internal temperature sensor
 * - 4 element receive sample FIFO
 * - Interrupt generation
 * - DMA interface
 *
 * Although there is only one ADC you can specify the input to it using the adc_select_input() function.
 * In round robin mode (adc_rrobin()) will use that input and move to the next one after a read.
 *
 * User ADC inputs are on 0-3 (GPIO 26-29), the temperature sensor is on input 4.
 *
 * Temperature sensor values can be approximated in centigrade as:
 *
 * T = 27 - (ADC_Voltage - 0.706)/0.001721
 *
 * The FIFO, if used, can contain up to 4 entries.
 *
 * \subsection adc_example Example
 * \addtogroup hardware_adc
 *
 * \include hello_adc.c
 */

// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_ADC, Enable/disable assertions in the ADC module, type=bool, default=0, group=hardware_adc
#ifndef PARAM_ASSERTIONS_ENABLED_ADC
#define PARAM_ASSERTIONS_ENABLED_ADC 0
#endif

#ifdef __cplusplus
extern "C" {
#endif

/*! \brief  Initialise the ADC HW
 *  \ingroup hardware_adc
 *
 */
void adc_init(void);

/*! \brief  Initialise the gpio for use as an ADC pin
 *  \ingroup hardware_adc
 *
 * Prepare a GPIO for use with ADC, by disabling all digital functions.
 *
 * \param gpio The GPIO number to use. Allowable GPIO numbers are 26 to 29 inclusive.
 */
static inline void adc_gpio_init(uint gpio) {
    invalid_params_if(ADC, gpio < 26 || gpio > 29);
    // Select NULL function to make output driver hi-Z
    gpio_set_function(gpio, GPIO_FUNC_NULL);
    // Also disable digital pulls and digital receiver
    gpio_disable_pulls(gpio);
    gpio_set_input_enabled(gpio, false);
}

/*! \brief  ADC input select
 *  \ingroup hardware_adc
 *
 * Select an ADC input. 0...3 are GPIOs 26...29 respectively.
 * Input 4 is the onboard temperature sensor.
 *
 * \param input Input to select.
 */
static inline void adc_select_input(uint input) {
    invalid_params_if(ADC, input > 4);
    hw_write_masked(&adc_hw->cs, input << ADC_CS_AINSEL_LSB, ADC_CS_AINSEL_BITS);
}

/*! \brief  Round Robin sampling selector
 *  \ingroup hardware_adc
 *
 * This function sets which inputs are to be run through in round robin mode.
 * Value between 0 and 0x1f (bit 0 to bit 4 for GPIO 26 to 29 and temperature sensor input respectively)
 *
 * \param input_mask A bit pattern indicating which of the 5 inputs are to be sampled. Write a value of 0 to disable round robin sampling.
 */
static inline void adc_set_round_robin(uint input_mask) {
    invalid_params_if(ADC, input_mask & ~ADC_CS_RROBIN_BITS);
    hw_write_masked(&adc_hw->cs, input_mask << ADC_CS_RROBIN_LSB, ADC_CS_RROBIN_BITS);
}

/*! \brief Enable the onboard temperature sensor
 *  \ingroup hardware_adc
 *
 * \param enable Set true to power on the onboard temperature sensor, false to power off.
 *
 */
static inline void adc_set_temp_sensor_enabled(bool enable) {
    if (enable)
        hw_set_bits(&adc_hw->cs, ADC_CS_TS_EN_BITS);
    else
        hw_clear_bits(&adc_hw->cs, ADC_CS_TS_EN_BITS);
}

/*! \brief Perform a single conversion
 *  \ingroup hardware_adc
 *
 *  Performs an ADC conversion, waits for the result, and then returns it.
 *
 * \return Result of the conversion.
 */
static inline uint16_t adc_read(void) {
    hw_set_bits(&adc_hw->cs, ADC_CS_START_ONCE_BITS);

    while (!(adc_hw->cs & ADC_CS_READY_BITS))
        tight_loop_contents();

    return adc_hw->result;
}

/*! \brief Enable or disable free-running sampling mode
 *  \ingroup hardware_adc
 *
 * \param run false to disable, true to enable free running conversion mode.
 */
static inline void adc_run(bool run) {
    if (run)
        hw_set_bits(&adc_hw->cs, ADC_CS_START_MANY_BITS);
    else
        hw_clear_bits(&adc_hw->cs, ADC_CS_START_MANY_BITS);
}

/*! \brief Set the ADC Clock divisor
 *  \ingroup hardware_adc
 *
 * Period of samples will be (1 + div) cycles on average. Note it takes 96 cycles to perform a conversion,
 * so any period less than that will be clamped to 96.
 *
 * \param clkdiv If non-zero, conversion will be started at intervals rather than back to back.
 */
static inline void adc_set_clkdiv(float clkdiv) {
    invalid_params_if(ADC, clkdiv >= 1 << (ADC_DIV_INT_MSB - ADC_DIV_INT_LSB + 1));
    adc_hw->div = (uint32_t)(clkdiv * (float) (1 << ADC_DIV_INT_LSB));
}

/*! \brief Setup the ADC FIFO
 *  \ingroup hardware_adc
 *
 * FIFO is 4 samples long, if a conversion is completed and the FIFO is full the result is dropped.
 *
 * \param en Enables write each conversion result to the FIFO
 * \param dreq_en Enable DMA requests when FIFO contains data
 * \param dreq_thresh Threshold for DMA requests/FIFO IRQ if enabled.
 * \param err_in_fifo If enabled, bit 15 of the FIFO contains error flag for each sample
 * \param byte_shift Shift FIFO contents to be one byte in size (for byte DMA) - enables DMA to byte buffers.
 */
static inline void adc_fifo_setup(bool en, bool dreq_en, uint16_t dreq_thresh, bool err_in_fifo, bool byte_shift) {
    hw_write_masked(&adc_hw->fcs,
                   (!!en << ADC_FCS_EN_LSB) |
                   (!!dreq_en << ADC_FCS_DREQ_EN_LSB) |
                   (dreq_thresh << ADC_FCS_THRESH_LSB) |
                   (!!err_in_fifo << ADC_FCS_ERR_LSB) |
                   (!!byte_shift << ADC_FCS_SHIFT_LSB),
                   ADC_FCS_EN_BITS |
                   ADC_FCS_DREQ_EN_BITS |
                   ADC_FCS_THRESH_BITS |
                   ADC_FCS_ERR_BITS |
                   ADC_FCS_SHIFT_BITS
    );
}

/*! \brief Check FIFO empty state
 *  \ingroup hardware_adc
 *
 * \return Returns true if the fifo is empty
 */
static inline bool adc_fifo_is_empty(void) {
    return !!(adc_hw->fcs & ADC_FCS_EMPTY_BITS);
}

/*! \brief Get number of entries in the ADC FIFO
 *  \ingroup hardware_adc
 *
 * The ADC FIFO is 4 entries long. This function will return how many samples are currently present.
 */
static inline uint8_t adc_fifo_get_level(void) {
    return (adc_hw->fcs & ADC_FCS_LEVEL_BITS) >> ADC_FCS_LEVEL_LSB;
}

/*! \brief Get ADC result from FIFO
 *  \ingroup hardware_adc
 *
 * Pops the latest result from the ADC FIFO.
 */
static inline uint16_t adc_fifo_get(void) {
    return adc_hw->fifo;
}

/*! \brief Wait for the ADC FIFO to have data.
 *  \ingroup hardware_adc
 *
 * Blocks until data is present in the FIFO
 */
static inline uint16_t adc_fifo_get_blocking(void) {
    while (adc_fifo_is_empty())
        tight_loop_contents();
    return adc_hw->fifo;
}

/*! \brief Drain the ADC FIFO
 *  \ingroup hardware_adc
 *
 * Will wait for any conversion to complete then drain the FIFO discarding any results.
 */
static inline void adc_fifo_drain(void) {
    // Potentially there is still a conversion in progress -- wait for this to complete before draining
    while (!(adc_hw->cs & ADC_CS_READY_BITS))
        tight_loop_contents();
    while (!adc_fifo_is_empty())
        (void) adc_fifo_get();
}

/*! \brief Enable/Disable ADC interrupts.
 *  \ingroup hardware_adc
 *
 * \param enabled Set to true to enable the ADC interrupts, false to disable
 */
static inline void adc_irq_set_enabled(bool enabled) {
    adc_hw->inte = !!enabled;
}

#ifdef __cplusplus
}
#endif

#endif
