diff --git a/firmware/mcp_adc.c b/firmware/mcp_adc.c new file mode 100644 index 0000000..0e8a58a --- /dev/null +++ b/firmware/mcp_adc.c @@ -0,0 +1,66 @@ +#include + +/* 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_BITS_MASK 0x0c + +#define ADC_ADDR 0xD0 /* or 0x68 */ + +void mcpadc_init(uint8_t mode) +{ + i2c_write(ADC_ADDR, 1, &mode)) +} + +uint8_t mcpadc_has_new_data() +{ + uint8_t r[4]; + i2c_read(ADC_ADDR, 4, r)/* 4 bytes are only needed in 18 bit mode */ + return r[3] & ADC_NEW_SAMPLE; +} + +#if ADC_ENABLE_18_BIT_MODE +int32_t mcpadc_get_data() +{ + uint8_t r[4] = 0; + int32_t value = 0; + i2c_read(ADC_ADDR, 4, r);/* reading 4 bytes guarantees us one config byte */ + if(r[0] & 0x80) {value = 0xffff;} + value = (value << 16) | (r[0] << 8) | r[1];/*endianess ???*/ + if((uint8_t) r[3] & ADC_BITS_MASK == ADC_BITS_18) + { + value = (value << 8) | r[3]; + } + return value; +} +#else +int16_t mcpadc_get_data() +{ + uint8_t r[2] = 0; + i2c_read(ADC_ADDR, 2, r);/* this will NOT work in 18 bit mode */ + int16_t value = (r[0] << 8) | r[1];/*endianess ???*/ + return r; +} +#endif + +void mcpadc_start_conv() +{ + uint8_t r[4]; + i2c_read(ADC_ADDR, 4, r); + r[3] |= ADC_NEW_SAMPLE; + i2c_write(ADC_ADDR, 1, &(r[3])); +} diff --git a/firmware/mcp_adc.h b/firmware/mcp_adc.h new file mode 100644 index 0000000..5ff341a --- /dev/null +++ b/firmware/mcp_adc.h @@ -0,0 +1,54 @@ +#ifndef MCPADC_H +#define MCPADC_H + +/* + +used i2c functions: + +i2c_read(uint8_t address, uint length, uint8_t *buf); +i2c_write(uint8_t address, uint length, uint8_t *buf); + +*/ + +#define ADC_ENABLE_18_BIT_MODE 0 + +#define ADC_GAIN_1 0x00 +#define ADC_GAIN_2 0x01 +#define ADC_GAIN_4 0x02 +#define ADC_GAIN_8 0x03 + +#define ADC_BITS_12 0x00 +#define ADC_BITS_14 0x04 +#define ADC_BITS_16 0x08 +#if ADC_ENABLE_18_BIT_MODE +# define ADC_BITS_18 0x0c +#endif + +#define ADC_CONV_SINGLE 0x00 +#define ADC_CONV_CONT 0x10 + +/* sets the mcp adc to the specified mode + * valid modes are obtained by oring one of each group (ADC_GAIN_*, ADC_BITS_* and ADC_CONV_*) together + */ +void mcpadc_init(uint8_t const mode); + +/* tests if the adc has a new sample + * returns nonzero if new data is aviable, 0 otherwise + */ +uint8_t mcpadc_has_new_data(); + +/* returns the most recent sample result of the adc + * !! return type depends on defines + */ +#if ADC_ENABLE_18_BIT_MODE +int32_t mcpadc_get_data(); +#else +int16_t mcpadc_get_data(); +#endif + +/* instructs the adc to take a new sample now + * has no effect if the current mode includes ADC_CONV_CONT + */ +void mcpadc_start_conv(); + +#endif