diff --git a/Makefile b/Makefile index e645e9ccd9cf01833100addc7211f31301f39bcd..be633e02cc58d8e68501a532e6f4e2c107b7f029 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ PROJECT=bioloid_exp ######################################################## # afegir tots els fitxers que s'han de compilar aquà ######################################################## -SOURCES=src/main.c src/dyn_slave_se.c src/dyn_slave_diff.c src/mem.c src/dyn_common.c src/ports.c src/adc.c src/pwm.c +SOURCES=src/main.c src/dyn_slave_se.c src/dyn_slave_diff.c src/mem.c src/dyn_common.c src/ports.c src/adc.c src/pwm.c src/dac.c OBJS=$(SOURCES:.c=.o) SRC_DIR=./src/ INCLUDE_DIR=./include/ diff --git a/include/dac.h b/include/dac.h new file mode 100644 index 0000000000000000000000000000000000000000..3c6de961852e36bcd0d50d18da55e9485ef6e95d --- /dev/null +++ b/include/dac.h @@ -0,0 +1,16 @@ +#ifndef _DAC_H +#define _DAC_H + +#include <avr/io.h> +#include <avr/interrupt.h> + +typedef enum {dac0,dac1} dac_ch_t; + +void dac_init(void); +void dac_start(void); +void dac_stop(void); +void dac_enable_channel(dac_ch_t ch); +void dac_disable_channel(dac_ch_t ch); +void dac_set_voltage(dac_ch_t ch,uint16_t voltage); + +#endif diff --git a/include/memory_map.h b/include/memory_map.h index d6b09fcc19efdfdfd2714a69f9a859244440da9f..76c1ac66b0043a70158db7d7bd7f4d6a70bf4a3e 100644 --- a/include/memory_map.h +++ b/include/memory_map.h @@ -147,14 +147,20 @@ #define ADC_AVG_CHANNEL7_L 0x76 #define ADC_AVG_CHANNEL7_H 0x77 #define PWM_CONTROL 0x78 // bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 - // ch0_en ch1_en ch2_en | ch3_en start/top + // ch3_en ch2_en ch1_en | ch0_en start/top #define PWM_FREQ_L 0x79 #define PWM_FREQ_H 0x7A #define PWM_CH0_DUTY 0x7B #define PWM_CH1_DUTY 0x7C #define PWM_CH2_DUTY 0x7D #define PWM_CH3_DUTY 0x7E +#define DAC_CONTROL 0x7F // bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // ch1_en | ch0_en start/top +#define DAC_CH0_VOLTAGE_L 0x80 +#define DAC_CH0_VOLTAGE_H 0x81 +#define DAC_CH1_VOLTAGE_L 0x82 +#define DAC_CH1_VOLTAGE_H 0x83 -#define RAM_SIZE 127 +#define RAM_SIZE 132 #endif diff --git a/src/dac.c b/src/dac.c new file mode 100644 index 0000000000000000000000000000000000000000..4f7715f073f44a45c92927d5ae39527364de439d --- /dev/null +++ b/src/dac.c @@ -0,0 +1,92 @@ +#include "dac.h" +#include "mem.h" + +#define DAC_TOP_VALUE ((uint32_t)1600) +#define DAC_PRESCALE_MASK 1 +#define DAC_MAX_VOLTAGE ((uint32_t)40960) //5V in 3|13 fixed point format + +/* private variables */ +uint8_t dac_running; + +/* public functions */ +void dac_init(void) +{ + // configure as outputs the DA pins + DDRB|=0x60; + + /* initialize internal variables */ + dac_running=0; + OCR1AH=0x00; + OCR1AL=0x00; + OCR1BH=0x00; + OCR1BL=0x00; + /* set the top value */ + ICR1H=(DAC_TOP_VALUE>>8)&0xFF; + ICR1L=(DAC_TOP_VALUE)&0xFF; + + /* configure the timer 3 */ + TCNT1H=0x00; + TCNT1L=0x00; + /* set the timer mode */ + TCCR1A=(1<<WGM11);// all three channels in fast PWM mode, output disabled + TCCR1B=(1<<WGM13)|(1<<WGM12);// no clock source, fast PWM mode +} + +void dac_start(void) +{ + TCNT1H=0x00; + TCNT1L=0x00; + /* set the prescaler value */ + TCCR1B&=0xF8; + TCCR1B|=DAC_PRESCALE_MASK; + dac_running=0x01; +} + +void dac_stop(void) +{ + /* set the prescaler to 0 (no clock source) */ + TCCR1B&=0xF8; + dac_running=0x00; +} + +void dac_enable_channel(dac_ch_t ch) +{ + switch(ch) + { + case dac0: TCCR1A|=(1<<COMA1); + break; + case dac1: TCCR1A|=(1<<COMB1); + break; + } +} + +void dac_disable_channel(dac_ch_t ch) +{ + switch(ch) + { + case dac0: TCCR1A&=~(1<<COMA1); + break; + case dac1: TCCR1A&=~(1<<COMB1); + break; + } +} + +void dac_set_voltage(dac_ch_t ch,uint16_t voltage) +{ + uint32_t compare_value; + + if(voltage>DAC_MAX_VOLTAGE) + voltage=DAC_MAX_VOLTAGE; + compare_value=(voltage*DAC_TOP_VALUE)/DAC_MAX_VOLTAGE; + + switch(ch) + { + case dac0: OCR1AH=(compare_value>>8)&0xFF; + OCR1AL=(compare_value)&0xFF; + break; + case dac1: OCR1BH=(compare_value>>8)&0xFF; + OCR1BL=(compare_value)&0xFF; + break; + } +} + diff --git a/src/dyn_common.c b/src/dyn_common.c index 9af79de8579bd0ff9fbf31a63b52277a108a0222..03cdef68958767072914dd0b0d302088a132b323 100644 --- a/src/dyn_common.c +++ b/src/dyn_common.c @@ -4,6 +4,7 @@ #include "ports.h" #include "adc.h" #include "pwm.h" +#include "dac.h" void do_write(uint8_t address,uint8_t length,uint8_t *data) { @@ -79,7 +80,30 @@ void do_write(uint8_t address,uint8_t length,uint8_t *data) pwm_set_frequency(low_byte+data[num]*256); else if(i>=PWM_CH0_DUTY && i<=PWM_CH3_DUTY) pwm_set_duty_cycle((pwm_id_t)(i-PWM_CH0_DUTY),data[num]); - + /* dac interface */ + else if(i==DAC_CONTROL) + { + if(data[num]&0x01) + dac_start(); + else + dac_stop(); + if(data[num]&0x02) + dac_enable_channel(dac0); + else + dac_disable_channel(dac0); + if(data[num]&0x04) + dac_enable_channel(dac1); + else + dac_disable_channel(dac1); + } + else if(i==DAC_CH0_VOLTAGE_L) + low_byte=data[num]; + else if(i==DAC_CH0_VOLTAGE_H) + dac_set_voltage(dac0,low_byte+data[num]*256); + else if(i==DAC_CH1_VOLTAGE_L) + low_byte=data[num]; + else if(i==DAC_CH1_VOLTAGE_H) + dac_set_voltage(dac1,low_byte+data[num]*256); num++; } } diff --git a/src/main.c b/src/main.c index 44127e3f4ba7fccd46ffcbcd56d2e1cf8b25d323..8419ba8f06d06d0f4cef042c96500a82e521ae4c 100755 --- a/src/main.c +++ b/src/main.c @@ -7,6 +7,7 @@ #include "ports.h" #include "adc.h" #include "pwm.h" +#include "dac.h" int16_t main(void) { @@ -16,6 +17,7 @@ int16_t main(void) init_ports(); adc_init(); pwm_init(); + dac_init(); sei(); while (1) diff --git a/src/pwm.c b/src/pwm.c index a6f77e84bbc30c6f8f8d7f6be771b5880d6abe5b..0fe34c5f32b11584d6bbd0f442c3f3ff84e7e9dc 100644 --- a/src/pwm.c +++ b/src/pwm.c @@ -52,7 +52,6 @@ void pwm_start(void) ICR3H=(pwm_top_value>>8)&0xFF; ICR3L=(pwm_top_value)&0xFF; pwm_running=0x01; - ram_data[PWM_CONTROL]|=0x01; } void pwm_stop(void) @@ -60,7 +59,6 @@ void pwm_stop(void) /* set the prescaler to 0 (no clock source) */ TCCR3B&=0xF8; pwm_running=0x00; - ram_data[PWM_CONTROL]&=0xFE; } void pwm_enable_ch(pwm_id_t id) @@ -68,13 +66,10 @@ void pwm_enable_ch(pwm_id_t id) switch(id) { case pwm0: TCCR3A|=(1<<COMA1); - ram_data[PWM_CONTROL]|=0x02; break; case pwm1: TCCR3A|=(1<<COMB1); - ram_data[PWM_CONTROL]|=0x04; break; case pwm2: TCCR3A|=(1<<COMC1); - ram_data[PWM_CONTROL]|=0x08; break; case pwm3: break; } @@ -85,13 +80,10 @@ void pwm_disable_ch(pwm_id_t id) switch(id) { case pwm0: TCCR3A&=~(1<<COMA1); - ram_data[PWM_CONTROL]&=0xFD; break; case pwm1: TCCR3A&=~(1<<COMB1); - ram_data[PWM_CONTROL]&=0xFB; break; case pwm2: TCCR3A&=~(1<<COMC1); - ram_data[PWM_CONTROL]&=0xF7; break; case pwm3: break; } @@ -125,8 +117,6 @@ void pwm_set_frequency(uint16_t freq_hz) } else pwm_prescaler_mask=(i+1); - ram_data[PWM_FREQ_H]=(freq_hz>>8)&0xFF; - ram_data[PWM_FREQ_L]=(freq_hz)&0xFF; break; } } @@ -142,17 +132,14 @@ void pwm_set_duty_cycle(pwm_id_t id,uint8_t duty) { case pwm0: OCR3AH=(compare_value>>8)&0xFF; OCR3AL=(compare_value&0xFF); - ram_data[PWM_CH0_DUTY]=duty; pwm_duty_cycle[0]=duty; break; case pwm1: OCR3BH=(compare_value>>8)&0xFF; OCR3BL=(compare_value&0xFF); - ram_data[PWM_CH1_DUTY]=duty; pwm_duty_cycle[1]=duty; break; case pwm2: OCR3CH=(compare_value>>8)&0xFF; OCR3CL=(compare_value&0xFF); - ram_data[PWM_CH2_DUTY]=duty; pwm_duty_cycle[2]=duty; break; case pwm3: break;