You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

108 lines
2.2 KiB

#include <stdint.h>
#include "i2c_simple.h"
#include "mcp_adc.h"
/* analog digital converter
* scratchpad
*
* address: 1101000
* read: conv data: 2 byte + config
* - ignore first 2 bits, bit 3 = MSB/sign
* - keeping reading always gets config byte
* write: config
*
* configuration register:
* - 0x15 continuos conversion, 14bit, gain x2 (page 16)
* - 0x05 single conversion, 14bit, gain x2 (page 16)
* bit 7 low -> new data, set to 1 on single conv mode to init
*
*/
#define ADC_NEW_SAMPLE 0x80
#define ADC_READ_DATA 0x40
#define ADC_BITS_MASK 0x0c
#define ADC_ADDR 0xD0 /* or 0x68 */
uint8_t r[4];
uint8_t curmode;
uint8_t unread_data_available;
void mcpadc_init(uint8_t mode)
{
int written = i2c_write(ADC_ADDR, 1, &mode);
if(written!=1){
for(;;); //TODO: error reporting
}
curmode = mode;
}
uint8_t mcpadc_has_new_data()
{
/* this assumes that the first RDY bit read after the sample data indicates the old/new state of the sample we just read */
if(unread_data_available){
// we already have new data, don't overwrite that by reading more
return unread_data_available;
}
#if ADC_ENABLE_18_BIT_MODE
if(curmode & ADC_BITS_MASK == ADC_BITS_18)
{
i2c_read(ADC_ADDR, 4, r);
curmode = r[3];
}
else
#else
{
i2c_read(ADC_ADDR, 3, r);
curmode = r[2];
}
#endif
if(!(curmode & ADC_NEW_SAMPLE)){ // if the /RDY bit reads 0, we just read a new sample
unread_data_available = 1;
}
return unread_data_available;
}
#if ADC_ENABLE_18_BIT_MODE
int32_t mcpadc_get_data()
{
if(!unread_data_available){
return 0;
}
int32_t value = 0;
if(r[0] & 0x80) {value = 0xffff;}
value = (value << 16) | (r[0] << 8) | r[1];
if((uint8_t) r[3] & ADC_BITS_MASK == ADC_BITS_18)
{
value = (value << 8) | r[2];
}
curmode |= (ADC_NEW_SAMPLE);
unread_data_available = 0;
return value;
}
#else
int16_t mcpadc_get_data()
{
if(!unread_data_available){
return 0;
}
int16_t value = (r[0] << 8) | r[1];
curmode |= (ADC_NEW_SAMPLE & ADC_READ_DATA);
unread_data_available = 0;
return value;
}
#endif
void mcpadc_start_conv(void)
{
r[3] = curmode | ADC_NEW_SAMPLE;
i2c_write(ADC_ADDR, 1, &(r[3]));
// curmode |= (ADC_NEW_SAMPLE & ADC_READ_DATA);/* you asked for a new sample - no you won't get the old one */
unread_data_available = 0;
}