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;