blob: d9ac176fc945a1f9e645638a7dbee49a4995e2e0 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef __ADC_H__
#define __ADC_H__
#include "os/mynewt.h"
#ifdef __cplusplus
extern "C" {
#endif
struct adc_dev;
/**
* Types of ADC events passed to the ADC driver.
*/
typedef enum {
/* This event represents the result of an ADC run. */
ADC_EVENT_RESULT = 0,
ADC_EVENT_CALIBRATED
} adc_event_type_t;
/**
* Event handler for ADC events that are processed in asynchronous mode.
*
* @param The ADC device being processed
* @param The argument data passed to adc_set_result_handler()
* @param The event type
* @param The buffer containing event data
* @param The size in bytes of that buffer.
*
* @return 0 on success, non-zero error code on failure
*/
typedef int (*adc_event_handler_func_t)(struct adc_dev *, void *,
adc_event_type_t, void *, int);
/**
* Configure an ADC channel for this ADC device. This is implemented
* by the HW specific drivers.
*
* @param The ADC device to configure
* @param The channel number to configure
* @param An opaque blob containing HW specific configuration.
*
* @return 0 on success, non-zero error code on failure.
*/
typedef int (*adc_configure_channel_func_t)(struct adc_dev *dev, uint8_t,
void *);
/**
* Trigger a sample on the ADC device asynchronously. This is implemented
* by the HW specific drivers.
*
* @param The ADC device to sample
*
* @return 0 on success, non-zero error code on failure
*/
typedef int (*adc_sample_func_t)(struct adc_dev *);
/**
* Blocking read of an ADC channel. This is implemented by the HW specific
* drivers.
*
* @param The ADC device to perform the blocking read on
* @param The channel to read
* @param The result to put the ADC reading into
*
* @return 0 on success, non-zero error code on failure
*/
typedef int (*adc_read_channel_func_t)(struct adc_dev *, uint8_t, int *);
/**
* Set the buffer(s) to read ADC results into for non-blocking reads. This
* is implemented by the HW specific drivers.
*
* @param The ADC device to read results into
* @param The primary buffer to read results into
* @param The secondary buffer to read results into (for cases where
* DMA'ing occurs, and secondary buffer can be used while primary
* is being processed.)
* @param The length of both buffers in number of bytes
*
* @return 0 on success, non-zero error code on failure.
*/
typedef int (*adc_buf_set_func_t)(struct adc_dev *, void *, void *, int);
/**
* Release a buffer for an ADC device, allowing the driver to re-use it for
* DMA'ing data.
*
* @param The ADC device to release the buffer to
* @param A pointer to the buffer to release
* @param The length of the buffer being released.
*
* @return 0 on success, non-zero error code on failure.
*/
typedef int (*adc_buf_release_func_t)(struct adc_dev *, void *, int);
/**
* Read the next entry from an ADC buffer as a integer
*
* @param The ADC device to read the entry from
* @param The buffer to read the entry from
* @param The total length of the buffer
* @param The entry number to read from the buffer
* @param The result to put the entry into
*
* @return 0 on success, non-zero error code on failure.
*/
typedef int (*adc_buf_read_func_t)(struct adc_dev *, void *, int, int, int *);
/**
* Get the size of a buffer
*
* @param The ADC device to get the buffer size from
* @param The number of channels in the buffer
* @param The number of samples in the buffer
*
* @return The size of the buffer
*/
typedef int (*adc_buf_size_func_t)(struct adc_dev *, int, int);
struct adc_driver_funcs {
adc_configure_channel_func_t af_configure_channel;
adc_sample_func_t af_sample;
adc_read_channel_func_t af_read_channel;
adc_buf_set_func_t af_set_buffer;
adc_buf_release_func_t af_release_buffer;
adc_buf_read_func_t af_read_buffer;
adc_buf_size_func_t af_size_buffer;
};
struct adc_chan_config {
uint16_t c_refmv;
uint8_t c_res;
uint8_t c_configured;
uint8_t c_cnum;
};
struct adc_dev {
struct os_dev ad_dev;
struct os_mutex ad_lock;
const struct adc_driver_funcs *ad_funcs;
struct adc_chan_config *ad_chans;
int ad_chan_count;
/* Open reference count */
uint8_t ad_ref_cnt;
adc_event_handler_func_t ad_event_handler_func;
void *ad_event_handler_arg;
};
int adc_chan_config(struct adc_dev *, uint8_t, void *);
int adc_chan_read(struct adc_dev *, uint8_t, int *);
int adc_event_handler_set(struct adc_dev *, adc_event_handler_func_t,
void *);
/**
* Sample the device specified by dev. This is used in non-blocking mode
* to generate samples into the event buffer.
*
* @param dev The device to sample
*
* @return 0 on success, non-zero on failure
*/
static inline int
adc_sample(struct adc_dev *dev)
{
return (dev->ad_funcs->af_sample(dev));
}
/**
* Blocking read of an ADC channel. This is implemented by the HW specific
* drivers.
*
* @param The ADC device to perform the blocking read on
* @param The channel to read
* @param The result to put the ADC reading into
*
* @return 0 on success, non-zero error code on failure
*/
static inline int
adc_read_channel(struct adc_dev *dev, uint8_t ch, int *result)
{
return (dev->ad_funcs->af_read_channel(dev, ch, result));
}
/**
* Set a result buffer to store data into. Optionally, provide a
* second buffer to continue writing data into as the first buffer
* fills up. Both buffers must be the same size.
*
* @param dev The ADC device to set the buffer for
* @param buf1 The first buffer to spool data into
* @param buf2 The second buffer to spool data into, while the first
* buffer is being processed. If NULL is provided, it's
* unused.
* @param buf_len The length of both buffers, in bytes.
*
* @return 0 on success, non-zero on failure.
*/
static inline int
adc_buf_set(struct adc_dev *dev, void *buf1, void *buf2,
int buf_len)
{
return (dev->ad_funcs->af_set_buffer(dev, buf1, buf2, buf_len));
}
/**
* Release a result buffer on the ADC device, and allow for it to be
* re-used for DMA'ing results.
*
* @param dev The device to release the buffer for
* @param buf The buffer to release
* @param buf_len The length of the buffer being released.
*
* @return 0 on success, non-zero error code on failure.
*/
static inline int
adc_buf_release(struct adc_dev *dev, void *buf, int buf_len)
{
return (dev->ad_funcs->af_release_buffer(dev, buf, buf_len));
}
/**
* Read an entry from an ADC buffer
*
* @param dev The device that the entry is being read from
* @param buf The buffer that we're reading the entry from
* @param buf_len The length of the buffer we're reading the entry from
* @param off The entry number to read from the buffer
* @param result A pointer to the result to store the data in
*
* @return 0 on success, non-zero error code on failure
*/
static inline int
adc_buf_read(struct adc_dev *dev, void *buf, int buf_len, int entry,
int *result)
{
return (dev->ad_funcs->af_read_buffer(dev, buf, buf_len, entry, result));
}
/**
* Return the size of an ADC buffer
*
* @param dev The ADC device to return the buffer size from
* @param channels The number of channels for these samples
* @param samples The number of SAMPLES on this ADC device
*
* @return The size of the resulting buffer
*/
static inline int
adc_buf_size(struct adc_dev *dev, int chans, int samples)
{
return (dev->ad_funcs->af_size_buffer(dev, chans, samples));
}
/**
* Take an ADC result and convert it to millivolts.
*
* @param dev The ADC dev to convert the result on
* @param cnum The channel number to convert the result from
* @param val The ADC value to convert to millivolts
*
* @return The convert value in millivolts
*/
static inline int
adc_result_mv(struct adc_dev *dev, uint8_t cnum, int val)
{
int res;
int refmv;
int ret;
refmv = (int) dev->ad_chans[cnum].c_refmv;
res = (int) dev->ad_chans[cnum].c_res;
ret = val * refmv;
ret += (1 << (res - 2));
ret = ret >> res;
return (ret);
}
#ifdef __cplusplus
}
#endif
#endif /* __ADC_H__ */