diff --git a/Makefile b/Makefile index 35d4790ad421501f0fe53f1cc125cfdb4af6d78c..826ec6ba8c9578d1d1a41e7d75cf0a67bf46e8cf 100644 --- a/Makefile +++ b/Makefile @@ -25,10 +25,10 @@ clean: rm -f $(TARGET).elf *.o *.hex %.o: %.c - $(GCC_BIN) -c $(C_FLAGS) $< -o $@ + $(GCC_BIN) -c $(C_FLAGS) *.c $(TARGET).elf: $(TARGET).o - $(GCC_BIN) $(LD_FLAGS) $(TARGET).o -o $(TARGET).elf + $(GCC_BIN) $(LD_FLAGS) *.o -o $(TARGET).elf $(TARGET).hex: $(TARGET).elf $(OBJCOPY_BIN) $(OBJCOPY_FLAGS) $(TARGET).elf $(TARGET).hex diff --git a/ads8698.c b/ads8698.c new file mode 100644 index 0000000000000000000000000000000000000000..0591f2ce367844dc605165ce2b2eaf8401e75324 --- /dev/null +++ b/ads8698.c @@ -0,0 +1,75 @@ +/** + * This file includes functions for interacting with an ADC + * + * Written for: TI ADS8698 8-channel ADC + * + * Connections: + * Function | ADC Pin | AVR Port | Pin # on DIP Atmega328P + * ----------+-------------+------------+------------------------- + * Data In | 1 (SDI) | PB3 (MOSI) | 17 + * Reset | 2 (RST) | PC0 | 23 + * Data Out | 36 (SDO) | PB4 (MISO) | 18 + * Clock | 37 (SCLK) | PB5 (SCK) | 19 + * Chip Sel.| 38 (CS) | PC1 | 24 + */ + +#include <avr/io.h> +#include <util/delay.h> + +#include "include/spi.h" +#include "include/ads8698.h" + +/* Initialize the ADC. */ +void ADS8698_init(void) { + + // Start SPI. + SPI_init(); + + // Set RST and CS as outputs. + DDRC |= (1<<DDC0) | (1<<DDC1); + + // Pull RST and CS high. + PORTC |= _BV(PORTC0); + PORTC |= _BV(PORTC1); + + // Reset the ADC. + ADS8698_reset(); + + // Start measurements + ADS8698_send_command(ADS8698_RESET); + SPI_transmit('H'); + SPI_transmit('e'); + SPI_transmit('l'); + SPI_transmit('l'); + SPI_transmit('o'); + SPI_transmit('!'); +} + +/* Set the input range on the ADC. */ +void ADS8698_set_range(ADS8698_range range) { + // TODO + return; +} + +/* Write to a register on the ADC. */ +void ADS8698_write_register(uint8_t address, uint8_t data) { + // TODO + return; +} + +/* Send a command to the ADC. */ +void ADS8698_send_command(ADS8698_command command) { + // TODO + return; +} + +/* Reset the ADC. + * + * Pull RST low for 70ns (instructions: 40-100ns). + * See datasheet section 8.4.1.1.6. + */ +void ADS8698_reset(void) { + PORTC &= ~_BV(PORTC0); + _delay_us(0.47); + PORTC |= _BV(PORTC0); +} diff --git a/blink.c b/blink.c deleted file mode 100644 index a1c46b21deaddc45243fbae2387215ce66951b66..0000000000000000000000000000000000000000 --- a/blink.c +++ /dev/null @@ -1,38 +0,0 @@ -#include <avr/io.h> -#include <util/delay.h> - -#define STROBE_DURATION_MS 20 - -/* This file is just placeholder stuff. It has nothing to do with testing. */ - -void delay(int duration) { - duration = duration / 10; - while (duration--) { - _delay_ms(10); - } -} - -void blink_once(int duration) { - /* Output High */ - PORTB |= _BV(PORTB5); - - /* Wait */ - delay(duration); - - /* Output Low */ - PORTB &= ~_BV(PORTB5); -} - -void strobe_pulse() { - /* Blinking pattern. Looks neat. */ - for (int j = 5; j < 10; j++) { - for (int i = 1; i < j; i++) { - blink_once(STROBE_DURATION_MS * i); - delay(STROBE_DURATION_MS * i); - } - for (int i = j; i > 0; i--) { - blink_once(STROBE_DURATION_MS * i); - delay(STROBE_DURATION_MS * i); - } - } -} diff --git a/include/ads8698.h b/include/ads8698.h new file mode 100644 index 0000000000000000000000000000000000000000..293a92d16b5ea2e96eaf337b314669c199bb17ab --- /dev/null +++ b/include/ads8698.h @@ -0,0 +1,62 @@ +/** + * This file includes functions for interacting with an ADC + * + * Written for: TI ADS8698 8-channel ADC + * + * Connections: + * Function | ADC Pin | AVR Port | Pin # on DIP Atmega328P + * ----------+-------------+------------+------------------------- + * Data In | 1 (SDI) | PB3 (MOSI) | 17 + * Reset | 2 (RST) | PC0 | 23 + * Data Out | 36 (SDO) | PB4 (MISO) | 18 + * Clock | 37 (SCLK) | PB5 (SCK) | 19 + * Chip Sel.| 38 (CS) | PC1 | 24 + */ + + +/* ADC Commands. + * + * See datasheet section 8.5.1. + */ +typedef enum { + ADS8698_NO_OP = 0x00, // Continue operating in previous mode. + ADS8698_STANDBY = 0x82, // Enter standby mode. + ADS8698_POWER_DOWN = 0x83, // Power down. + ADS8698_RESET = 0x85, // Reset. + ADS8698_AUTO_RESET = 0xA0, // Reset and enter auto-scan mode. + ADS8698_MANUAL_CH0 = 0xC0, // Select channel 0 input. + ADS8698_MANUAL_CH1 = 0xC4, // Select channel 1 input. + ADS8698_MANUAL_CH2 = 0xC8, // Select channel 2 input. + ADS8698_MANUAL_CH3 = 0xCC, // Select channel 3 input. + ADS8698_MANUAL_CH4 = 0xD0, // Select channel 4 input. + ADS8698_MANUAL_CH5 = 0xD4, // Select channel 5 input. + ADS8698_MANUAL_CH6 = 0xD8, // Select channel 6 input. + ADS8698_MANUAL_CH7 = 0xDC, // Select channel 7 input. + ADS8698_MANUAL_AUX = 0xE0, // Select aux input. +} ADS8698_command; + + +/* ADC Input Ranges. + * + * See datasheet section 8.5.2.3.3. + */ +typedef enum { + ADS8698_RANGE_BIPOLAR_2_5X = 0x00, // 0 +/- 2.5 x Vref + ADS8698_RANGE_BIPOLAR_1_25X = 0x01, // 0 +/- 1.25 x Vref + ADS8698_RANGE_BIPOLAR_0_625X = 0x02, // 0 +/- 0.625 x Vref + ADS8698_RANGE_UNIPOLAR_2_5X = 0x05, // 0 + 2.5 x Vref + ADS8698_RANGE_UNIPOLAR_1_25X = 0x0 // 0 + 1.25 x Vref +} ADS8698_range; + + +/* Initialize the ADC. */ +void ADS8698_init(void); + +/* Set the input range on the ADC. */ +void ADS8698_set_range(ADS8698_range range); + +/* Send a command to the ADC. */ +void ADS8698_send_command(ADS8698_command command); + +/* Reset the ADC. */ +void ADS8698_reset(void); diff --git a/include/measure.h b/include/measure.h new file mode 100644 index 0000000000000000000000000000000000000000..c3af59e94b60763f4959b8bb196ceb7a5296f9f2 --- /dev/null +++ b/include/measure.h @@ -0,0 +1,16 @@ +/** + * This file includes functions for measuring electrical resistance. + */ + +typedef struct Measurements Measurements; + +struct Measurements { + double value1, value2, value3, value4, value5, value6, value7, value8; +}; + + +/* Prepare for measuring resistance. */ +void Measure_init(void); + +/* Acquire resistance measurements. */ +struct Measurements measure(void); diff --git a/include/spi.h b/include/spi.h new file mode 100644 index 0000000000000000000000000000000000000000..5bf901f56b55f64895cf477a87980c250c7d1f81 --- /dev/null +++ b/include/spi.h @@ -0,0 +1,12 @@ +/** + * Logic for using SPI to communicate between the AVR and other devices. + */ + +/* Initialize the microcontroller's SPI interface. */ +void SPI_init(void); + +/* Send a byte over the SPI interface. */ +void SPI_transmit(char data); + +/* Receive a byte from the SPI interface. */ +char SPI_receive(void); diff --git a/main.c b/main.c index 5efeeb9abe3d85dff8666d7cb36d0c89fa625c05..70d39b1b0e3469f8daea65800d50716e5ab096cb 100644 --- a/main.c +++ b/main.c @@ -1,13 +1,22 @@ -#include "blink.c" +#include "include/measure.h" +/* Start-up procedure */ void init() { - /* Make Pin 5 of PORTB an output. */ - DDRB |= _BV(DDB5); + /* Activate display. */ + // TODO + + /* Prepare ADC for measurements. */ + Measure_init(); } +/* Main code; will repeat forever */ void loop() { - /* Strobe forever */ - strobe_pulse(); + /* Measure resistance. */ + // TODO + Measure_init(); + + /* Update display. */ + // TODO } int main(void) { diff --git a/measure.c b/measure.c new file mode 100644 index 0000000000000000000000000000000000000000..c14a95b748807cf6e112f4ed9eae902a8fa8bcfb --- /dev/null +++ b/measure.c @@ -0,0 +1,28 @@ +/** + * This file includes functions for measuring electrical resistance. + */ + +#include <avr/io.h> +#include <util/delay.h> + +#include "include/spi.h" +#include "include/ads8698.h" +#include "include/measure.h" + + + +/* Acquire resistance measurements. */ +struct Measurements measure() { + /* Do the stuff. */ + // TODO + return (Measurements) {1, 1, 1, 1, 1, 1, 1, 1}; +} + + +/* Prepare for measuring resistance. */ +void Measure_init(void) { + ADS8698_init(); + _delay_us(100); + // int sample_count = 2048; // TODO: what is this + // ADS8698_config(&sample_buffer, sample_count, ADS8698_CHANNEL_0, INPUT_RANGE_UNIPOLAR_1_25X_VREF); +} diff --git a/spi.c b/spi.c new file mode 100644 index 0000000000000000000000000000000000000000..e20d0c6a8cf562365c676f31e84404b0867a36ca --- /dev/null +++ b/spi.c @@ -0,0 +1,36 @@ +/** + * Logic for using SPI to communicate between the AVR and other devices. + */ + +#include <avr/io.h> + +#include "include/spi.h" + +/* Initialize the microcontroller's SPI interface. */ +void SPI_init(void) { + // Set MOSI, SCK, and SS as outputs + DDRB = (1<<DDB3) | (1<<DDB5) | (1<<DDB2); + + // Enable SPI, become master, set clock rate to CPU clock / 16. + SPCR = (1<<SPE) | (1<<MSTR); +} + +/* Send a byte over the SPI interface. */ +void SPI_transmit(char data) { + // Put the data in the SPI Data Register. + SPDR = data; + + // Wait for transmission to complete. + while(!(SPSR & (1<<SPIF))) + ; +} + +/* Receive a byte from the SPI interface. */ +char SPI_receive(void) { + // Wait for reception to complete. + while (!(SPSR & (1<<SPIF))) + ; + + // Return received value from data register. + return SPDR; +}