#ifndef _chip_conv_h__
#define _chip_conv_h__

/** chip_conv **
 *
 * Functions that convert chip raw data to quantities.
 * 
 */

#include "chip.h"
#include "quantity.h"

#ifdef __cplusplus
extern "C" {
#endif


/*
 * This file provides a recipe for declaring functions that convert raw chip data
 * into a Quantity. Each sensor chip must declare its own conversion function(s).
 */


/**
 * Arguments to a conversion function:
 * 
 * - result   : Store results into the given Quantity, passed by reference
 * - raw_data : Array of raw data bytes to convert (length assumed by implementation)
 * - cal_data : Array of calibration data bytes (ignored by most chips)
 * - cal_len  : Length of calibration data array (ignored by most chips)
 */
#define _CHIP_CONV_RAW_ARGS \
    Quantity *result, uint8_t *raw_data, uint8_t raw_len, uint8_t *cal_data, uint8_t cal_len

/**
 * Macro to declare a conversion function. For uniformity, each sensor chip should
 * declare its conversion function(s) using this macro.
 * 
 * If the argument name is "foo", the declared function is named "foo_conv_raw", and
 * it returns 0 on success, or an int error code as defined in chip.h.
 */
#define _CHIP_CONV_RAW(name) int name ## _conv_raw(_CHIP_CONV_RAW_ARGS)

/**
 * Type definition for a pointer to a conversion function.
 */
typedef int (*chip_conv_raw_fn_t)(_CHIP_CONV_RAW_ARGS);

/*
 * Declarations of conversion functions FOR ALL SUPPORTED SENSOR CHIPS.
 * Enable the required implementations by defining the appropriate compile-time variable.
 * 
 * For example, to enable the conversion function for chip id "USBTENKI_CHIP_SHT31_T", define the
 * variable "ENABLE_CHIP_SHT31_T". This is easily achieved by adding the following argument
 * to your CFLAGS: -DENABLE_CHIP_SHT31_T
 * 
 * In a non-firmware setting, where space isn't a constraint, all functions can be enabled by
 * setting a single variable "ENABLE_ALL_CHIPS".
 */

_CHIP_CONV_RAW(unknown_chip);
_CHIP_CONV_RAW(sht31_t);
_CHIP_CONV_RAW(sht31_rh);
_CHIP_CONV_RAW(mcp9800);
_CHIP_CONV_RAW(cc2_t);
_CHIP_CONV_RAW(cc2_rh);
_CHIP_CONV_RAW(ccs811_tvoc);
_CHIP_CONV_RAW(ccs811_eco2);
_CHIP_CONV_RAW(ms5611_p);
_CHIP_CONV_RAW(ms5611_t);
_CHIP_CONV_RAW(scd30_t);
_CHIP_CONV_RAW(scd30_rh);
_CHIP_CONV_RAW(scd30_co2);
_CHIP_CONV_RAW(sps30_mc);
_CHIP_CONV_RAW(sps30_nc);
_CHIP_CONV_RAW(sps30_part_size);
_CHIP_CONV_RAW(thc);
_CHIP_CONV_RAW(pt100_rtd);
_CHIP_CONV_RAW(rtd300_pt100_3w);
_CHIP_CONV_RAW(rtd300_pt100_2w);
_CHIP_CONV_RAW(rtd300_pt1000_3w);
_CHIP_CONV_RAW(tmc200_type_k);
_CHIP_CONV_RAW(tmc200_type_n);
_CHIP_CONV_RAW(tmc200_type_t);
_CHIP_CONV_RAW(tmc200_type_e);
_CHIP_CONV_RAW(tmc200_type_j);
_CHIP_CONV_RAW(tmc200_cold);
_CHIP_CONV_RAW(apds9250);
_CHIP_CONV_RAW(veml6030_als);
_CHIP_CONV_RAW(veml6030_white);
_CHIP_CONV_RAW(veml6075_uva);
_CHIP_CONV_RAW(veml6075_uvb);
_CHIP_CONV_RAW(co2_dxc200);
_CHIP_CONV_RAW(co2_dxc300);
_CHIP_CONV_RAW(p_comp_dxc300);
_CHIP_CONV_RAW(t_comp_dxc300);
_CHIP_CONV_RAW(rh_comp_dxc300);
_CHIP_CONV_RAW(tsl2561);
_CHIP_CONV_RAW(tsl2568);


/**
 * Return the appropriate conversion function for the given chip ID.
 * Callable only when ENABLE_ALL_CHIPS is defined; otherwise you'll get a linker error.
 */
chip_conv_raw_fn_t chip_conv_raw_fn(uint16_t chip_id);


#ifdef __cplusplus
}
#endif

#endif
