/*
 * 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) {
    valid_params_if(ADC, input < NUM_ADC_CHANNELS);
    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 (uint16_t) 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,
                   (bool_to_bit(en) << ADC_FCS_EN_LSB) |
                   (bool_to_bit(dreq_en) << ADC_FCS_DREQ_EN_LSB) |
                   (((uint)dreq_thresh) << ADC_FCS_THRESH_LSB) |
                   (bool_to_bit(err_in_fifo) << ADC_FCS_ERR_LSB) |
                   (bool_to_bit(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 (uint16_t)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 (uint16_t)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
