diff --git a/stm/Makefile b/stm/Makefile
index 9e5ba14fadeac28039edd9df479f2cfa27136846..6203e9f4af176822fa201cd111cb198d2f6189e2 100644
--- a/stm/Makefile
+++ b/stm/Makefile
@@ -26,6 +26,7 @@ SRC_C = \
 	usart.c \
 	usb.c \
 	sdio.c \
+	audio.c \
 	lexerstm.c \
 
 SRC_S = \
@@ -70,6 +71,7 @@ SRC_STM = \
 	stm32f4xx_rtc.c \
 	stm32f4xx_usart.c \
 	stm32f4xx_spi.c \
+	stm32f4xx_dac.c \
 	stm_misc.c \
 	usb_core.c \
 	usb_dcd.c \
diff --git a/stm/audio.c b/stm/audio.c
new file mode 100644
index 0000000000000000000000000000000000000000..2df4e079410fc8d25f1a2446d57f6ca4a0e6c14a
--- /dev/null
+++ b/stm/audio.c
@@ -0,0 +1,98 @@
+#include <stdint.h>
+
+#include "stm32f4xx_rcc.h"
+#include "stm32f4xx_gpio.h"
+#include "stm32f4xx_dac.h"
+
+#include "nlr.h"
+#include "misc.h"
+//#include "lexer.h"
+//#include "lexerstm.h"
+#include "mpyconfig.h"
+#include "parse.h"
+#include "compile.h"
+#include "runtime.h"
+
+#define SAMPLE_BUF_SIZE (32)
+
+// sample_buf_in is always the same or ahead of sample_buf_out
+// when they are the same, there are no more samples left to process
+// in this scheme, there is always 1 unusable byte in the buffer, just before sample_buf_out
+int sample_buf_in;
+int sample_buf_out;
+byte sample_buf[SAMPLE_BUF_SIZE];
+
+bool audio_is_full(void) {
+    return ((sample_buf_in + 1) % SAMPLE_BUF_SIZE) == sample_buf_out;
+}
+
+void audio_fill(byte sample) {
+    sample_buf[sample_buf_in] = sample;
+    sample_buf_in = (sample_buf_in + 1) % SAMPLE_BUF_SIZE;
+    // enable interrupt
+}
+
+void audio_drain(void) {
+    if (sample_buf_in == sample_buf_out) {
+        // buffer is empty; disable interrupt
+    } else {
+        // buffer has a sample; output it
+        byte sample = sample_buf[sample_buf_out];
+        DAC_SetChannel2Data(DAC_Align_8b_R, sample);
+        sample_buf_out = (sample_buf_out + 1) % SAMPLE_BUF_SIZE;
+    }
+}
+
+// direct access to DAC
+py_obj_t pyb_audio_dac(py_obj_t val) {
+    DAC_SetChannel2Data(DAC_Align_8b_R, py_obj_get_int(val));
+    return py_const_none;
+}
+
+py_obj_t pyb_audio_is_full(void) {
+    if (audio_is_full()) {
+        return py_const_true;
+    } else {
+        return py_const_false;
+    }
+}
+
+py_obj_t pyb_audio_fill(py_obj_t val) {
+    audio_fill(py_obj_get_int(val));
+    return py_const_none;
+}
+
+void audio_init(void) {
+    // DAC peripheral clock
+    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
+
+    // DAC channel 2 (DAC_OUT2 = PA.5) configuration
+    GPIO_InitTypeDef GPIO_InitStructure;
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
+    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+    GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+    // DAC channel2 Configuration
+    DAC_InitTypeDef DAC_InitStructure;
+    DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
+    DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
+    DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
+    DAC_Init(DAC_Channel_2, &DAC_InitStructure);
+
+    // Enable DAC Channel2
+    DAC_Cmd(DAC_Channel_2, ENABLE);
+
+    // from now on use DAC_SetChannel2Data to trigger a conversion
+
+    sample_buf_in = 0;
+    sample_buf_out = 0;
+    // enable interrupt
+
+    // Python interface
+    py_obj_t m = py_module_new();
+    rt_store_attr(m, qstr_from_str_static("dac"), rt_make_function_1(pyb_audio_dac));
+    rt_store_attr(m, qstr_from_str_static("is_full"), rt_make_function_0(pyb_audio_is_full));
+    rt_store_attr(m, qstr_from_str_static("fill"), rt_make_function_1(pyb_audio_fill));
+    rt_store_name(qstr_from_str_static("audio"), m);
+}
diff --git a/stm/audio.h b/stm/audio.h
new file mode 100644
index 0000000000000000000000000000000000000000..be5f4815575ec907418e217b52568e43c472c5a3
--- /dev/null
+++ b/stm/audio.h
@@ -0,0 +1 @@
+void audio_init(void);
diff --git a/stm/lib/stm32f4xx_dac.c b/stm/lib/stm32f4xx_dac.c
new file mode 100644
index 0000000000000000000000000000000000000000..bc19fb3b3355d546eb06928beed77001ad04c177
--- /dev/null
+++ b/stm/lib/stm32f4xx_dac.c
@@ -0,0 +1,715 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4xx_dac.c
+  * @author  MCD Application Team
+  * @version V1.1.0
+  * @date    11-January-2013
+   * @brief   This file provides firmware functions to manage the following 
+  *          functionalities of the Digital-to-Analog Converter (DAC) peripheral: 
+  *           + DAC channels configuration: trigger, output buffer, data format
+  *           + DMA management      
+  *           + Interrupts and flags management
+  *
+ @verbatim      
+ ===============================================================================
+                      ##### DAC Peripheral features #####
+ ===============================================================================
+    [..]        
+      *** DAC Channels ***
+      ====================  
+    [..]  
+    The device integrates two 12-bit Digital Analog Converters that can 
+    be used independently or simultaneously (dual mode):
+      (#) DAC channel1 with DAC_OUT1 (PA4) as output
+      (#) DAC channel2 with DAC_OUT2 (PA5) as output
+  
+      *** DAC Triggers ***
+      ====================
+    [..]
+    Digital to Analog conversion can be non-triggered using DAC_Trigger_None
+    and DAC_OUT1/DAC_OUT2 is available once writing to DHRx register 
+    using DAC_SetChannel1Data() / DAC_SetChannel2Data() functions.
+    [..] 
+    Digital to Analog conversion can be triggered by:
+      (#) External event: EXTI Line 9 (any GPIOx_Pin9) using DAC_Trigger_Ext_IT9.
+          The used pin (GPIOx_Pin9) must be configured in input mode.
+  
+      (#) Timers TRGO: TIM2, TIM4, TIM5, TIM6, TIM7 and TIM8 
+          (DAC_Trigger_T2_TRGO, DAC_Trigger_T4_TRGO...)
+          The timer TRGO event should be selected using TIM_SelectOutputTrigger()
+  
+      (#) Software using DAC_Trigger_Software
+  
+      *** DAC Buffer mode feature ***
+      =============================== 
+      [..] 
+      Each DAC channel integrates an output buffer that can be used to 
+      reduce the output impedance, and to drive external loads directly
+      without having to add an external operational amplifier.
+      To enable, the output buffer use  
+      DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
+      [..]           
+      (@) Refer to the device datasheet for more details about output 
+          impedance value with and without output buffer.
+            
+       *** DAC wave generation feature ***
+       =================================== 
+       [..]     
+       Both DAC channels can be used to generate
+         (#) Noise wave using DAC_WaveGeneration_Noise
+         (#) Triangle wave using DAC_WaveGeneration_Triangle
+          
+          -@-  Wave generation can be disabled using DAC_WaveGeneration_None
+  
+       *** DAC data format ***
+       =======================
+       [..]   
+       The DAC data format can be:
+         (#) 8-bit right alignment using DAC_Align_8b_R
+         (#) 12-bit left alignment using DAC_Align_12b_L
+         (#) 12-bit right alignment using DAC_Align_12b_R
+  
+       *** DAC data value to voltage correspondence ***  
+       ================================================ 
+       [..] 
+       The analog output voltage on each DAC channel pin is determined
+       by the following equation: 
+       DAC_OUTx = VREF+ * DOR / 4095
+       with  DOR is the Data Output Register
+          VEF+ is the input voltage reference (refer to the device datasheet)
+        e.g. To set DAC_OUT1 to 0.7V, use
+          DAC_SetChannel1Data(DAC_Align_12b_R, 868);
+          Assuming that VREF+ = 3.3V, DAC_OUT1 = (3.3 * 868) / 4095 = 0.7V
+  
+       *** DMA requests  ***
+       =====================
+       [..]    
+       A DMA1 request can be generated when an external trigger (but not
+       a software trigger) occurs if DMA1 requests are enabled using
+       DAC_DMACmd()
+       [..]
+       DMA1 requests are mapped as following:
+         (#) DAC channel1 : mapped on DMA1 Stream5 channel7 which must be 
+             already configured
+         (#) DAC channel2 : mapped on DMA1 Stream6 channel7 which must be 
+             already configured
+  
+      
+                      ##### How to use this driver #####
+ ===============================================================================
+    [..]          
+      (+) DAC APB clock must be enabled to get write access to DAC
+          registers using
+          RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE)
+      (+) Configure DAC_OUTx (DAC_OUT1: PA4, DAC_OUT2: PA5) in analog mode.
+      (+) Configure the DAC channel using DAC_Init() function
+      (+) Enable the DAC channel using DAC_Cmd() function
+   
+ @endverbatim    
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
+  *
+  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+  * You may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
+  *
+  *        http://www.st.com/software_license_agreement_liberty_v2
+  *
+  * Unless required by applicable law or agreed to in writing, software 
+  * distributed under the License is distributed on an "AS IS" BASIS, 
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  *
+  ******************************************************************************  
+  */ 
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_conf.h"
+#include "stm32f4xx_dac.h"
+#include "stm32f4xx_rcc.h"
+
+/** @addtogroup STM32F4xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @defgroup DAC 
+  * @brief DAC driver modules
+  * @{
+  */ 
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+
+/* CR register Mask */
+#define CR_CLEAR_MASK              ((uint32_t)0x00000FFE)
+
+/* DAC Dual Channels SWTRIG masks */
+#define DUAL_SWTRIG_SET            ((uint32_t)0x00000003)
+#define DUAL_SWTRIG_RESET          ((uint32_t)0xFFFFFFFC)
+
+/* DHR registers offsets */
+#define DHR12R1_OFFSET             ((uint32_t)0x00000008)
+#define DHR12R2_OFFSET             ((uint32_t)0x00000014)
+#define DHR12RD_OFFSET             ((uint32_t)0x00000020)
+
+/* DOR register offset */
+#define DOR_OFFSET                 ((uint32_t)0x0000002C)
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/** @defgroup DAC_Private_Functions
+  * @{
+  */
+
+/** @defgroup DAC_Group1 DAC channels configuration
+ *  @brief   DAC channels configuration: trigger, output buffer, data format 
+ *
+@verbatim   
+ ===============================================================================
+   ##### DAC channels configuration: trigger, output buffer, data format #####
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Deinitializes the DAC peripheral registers to their default reset values.
+  * @param  None
+  * @retval None
+  */
+void DAC_DeInit(void)
+{
+  /* Enable DAC reset state */
+  RCC_APB1PeriphResetCmd(RCC_APB1Periph_DAC, ENABLE);
+  /* Release DAC from reset state */
+  RCC_APB1PeriphResetCmd(RCC_APB1Periph_DAC, DISABLE);
+}
+
+/**
+  * @brief  Initializes the DAC peripheral according to the specified parameters
+  *         in the DAC_InitStruct.
+  * @param  DAC_Channel: the selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  DAC_InitStruct: pointer to a DAC_InitTypeDef structure that contains
+  *         the configuration information for the  specified DAC channel.
+  * @retval None
+  */
+void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct)
+{
+  uint32_t tmpreg1 = 0, tmpreg2 = 0;
+
+  /* Check the DAC parameters */
+  assert_param(IS_DAC_TRIGGER(DAC_InitStruct->DAC_Trigger));
+  assert_param(IS_DAC_GENERATE_WAVE(DAC_InitStruct->DAC_WaveGeneration));
+  assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude));
+  assert_param(IS_DAC_OUTPUT_BUFFER_STATE(DAC_InitStruct->DAC_OutputBuffer));
+
+/*---------------------------- DAC CR Configuration --------------------------*/
+  /* Get the DAC CR value */
+  tmpreg1 = DAC->CR;
+  /* Clear BOFFx, TENx, TSELx, WAVEx and MAMPx bits */
+  tmpreg1 &= ~(CR_CLEAR_MASK << DAC_Channel);
+  /* Configure for the selected DAC channel: buffer output, trigger, 
+     wave generation, mask/amplitude for wave generation */
+  /* Set TSELx and TENx bits according to DAC_Trigger value */
+  /* Set WAVEx bits according to DAC_WaveGeneration value */
+  /* Set MAMPx bits according to DAC_LFSRUnmask_TriangleAmplitude value */ 
+  /* Set BOFFx bit according to DAC_OutputBuffer value */   
+  tmpreg2 = (DAC_InitStruct->DAC_Trigger | DAC_InitStruct->DAC_WaveGeneration |
+             DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude | \
+             DAC_InitStruct->DAC_OutputBuffer);
+  /* Calculate CR register value depending on DAC_Channel */
+  tmpreg1 |= tmpreg2 << DAC_Channel;
+  /* Write to DAC CR */
+  DAC->CR = tmpreg1;
+}
+
+/**
+  * @brief  Fills each DAC_InitStruct member with its default value.
+  * @param  DAC_InitStruct: pointer to a DAC_InitTypeDef structure which will 
+  *         be initialized.
+  * @retval None
+  */
+void DAC_StructInit(DAC_InitTypeDef* DAC_InitStruct)
+{
+/*--------------- Reset DAC init structure parameters values -----------------*/
+  /* Initialize the DAC_Trigger member */
+  DAC_InitStruct->DAC_Trigger = DAC_Trigger_None;
+  /* Initialize the DAC_WaveGeneration member */
+  DAC_InitStruct->DAC_WaveGeneration = DAC_WaveGeneration_None;
+  /* Initialize the DAC_LFSRUnmask_TriangleAmplitude member */
+  DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
+  /* Initialize the DAC_OutputBuffer member */
+  DAC_InitStruct->DAC_OutputBuffer = DAC_OutputBuffer_Enable;
+}
+
+/**
+  * @brief  Enables or disables the specified DAC channel.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  NewState: new state of the DAC channel. 
+  *          This parameter can be: ENABLE or DISABLE.
+  * @note   When the DAC channel is enabled the trigger source can no more be modified.
+  * @retval None
+  */
+void DAC_Cmd(uint32_t DAC_Channel, FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    /* Enable the selected DAC channel */
+    DAC->CR |= (DAC_CR_EN1 << DAC_Channel);
+  }
+  else
+  {
+    /* Disable the selected DAC channel */
+    DAC->CR &= (~(DAC_CR_EN1 << DAC_Channel));
+  }
+}
+
+/**
+  * @brief  Enables or disables the selected DAC channel software trigger.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  NewState: new state of the selected DAC channel software trigger.
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void DAC_SoftwareTriggerCmd(uint32_t DAC_Channel, FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    /* Enable software trigger for the selected DAC channel */
+    DAC->SWTRIGR |= (uint32_t)DAC_SWTRIGR_SWTRIG1 << (DAC_Channel >> 4);
+  }
+  else
+  {
+    /* Disable software trigger for the selected DAC channel */
+    DAC->SWTRIGR &= ~((uint32_t)DAC_SWTRIGR_SWTRIG1 << (DAC_Channel >> 4));
+  }
+}
+
+/**
+  * @brief  Enables or disables simultaneously the two DAC channels software triggers.
+  * @param  NewState: new state of the DAC channels software triggers.
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */
+void DAC_DualSoftwareTriggerCmd(FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    /* Enable software trigger for both DAC channels */
+    DAC->SWTRIGR |= DUAL_SWTRIG_SET;
+  }
+  else
+  {
+    /* Disable software trigger for both DAC channels */
+    DAC->SWTRIGR &= DUAL_SWTRIG_RESET;
+  }
+}
+
+/**
+  * @brief  Enables or disables the selected DAC channel wave generation.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  DAC_Wave: specifies the wave type to enable or disable.
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Wave_Noise: noise wave generation
+  *            @arg DAC_Wave_Triangle: triangle wave generation
+  * @param  NewState: new state of the selected DAC channel wave generation.
+  *          This parameter can be: ENABLE or DISABLE.  
+  * @retval None
+  */
+void DAC_WaveGenerationCmd(uint32_t DAC_Channel, uint32_t DAC_Wave, FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  assert_param(IS_DAC_WAVE(DAC_Wave)); 
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    /* Enable the selected wave generation for the selected DAC channel */
+    DAC->CR |= DAC_Wave << DAC_Channel;
+  }
+  else
+  {
+    /* Disable the selected wave generation for the selected DAC channel */
+    DAC->CR &= ~(DAC_Wave << DAC_Channel);
+  }
+}
+
+/**
+  * @brief  Set the specified data holding register value for DAC channel1.
+  * @param  DAC_Align: Specifies the data alignment for DAC channel1.
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Align_8b_R: 8bit right data alignment selected
+  *            @arg DAC_Align_12b_L: 12bit left data alignment selected
+  *            @arg DAC_Align_12b_R: 12bit right data alignment selected
+  * @param  Data: Data to be loaded in the selected data holding register.
+  * @retval None
+  */
+void DAC_SetChannel1Data(uint32_t DAC_Align, uint16_t Data)
+{  
+  __IO uint32_t tmp = 0;
+  
+  /* Check the parameters */
+  assert_param(IS_DAC_ALIGN(DAC_Align));
+  assert_param(IS_DAC_DATA(Data));
+  
+  tmp = (uint32_t)DAC_BASE; 
+  tmp += DHR12R1_OFFSET + DAC_Align;
+
+  /* Set the DAC channel1 selected data holding register */
+  *(__IO uint32_t *) tmp = Data;
+}
+
+/**
+  * @brief  Set the specified data holding register value for DAC channel2.
+  * @param  DAC_Align: Specifies the data alignment for DAC channel2.
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Align_8b_R: 8bit right data alignment selected
+  *            @arg DAC_Align_12b_L: 12bit left data alignment selected
+  *            @arg DAC_Align_12b_R: 12bit right data alignment selected
+  * @param  Data: Data to be loaded in the selected data holding register.
+  * @retval None
+  */
+void DAC_SetChannel2Data(uint32_t DAC_Align, uint16_t Data)
+{
+  __IO uint32_t tmp = 0;
+
+  /* Check the parameters */
+  assert_param(IS_DAC_ALIGN(DAC_Align));
+  assert_param(IS_DAC_DATA(Data));
+  
+  tmp = (uint32_t)DAC_BASE;
+  tmp += DHR12R2_OFFSET + DAC_Align;
+
+  /* Set the DAC channel2 selected data holding register */
+  *(__IO uint32_t *)tmp = Data;
+}
+
+/**
+  * @brief  Set the specified data holding register value for dual channel DAC.
+  * @param  DAC_Align: Specifies the data alignment for dual channel DAC.
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Align_8b_R: 8bit right data alignment selected
+  *            @arg DAC_Align_12b_L: 12bit left data alignment selected
+  *            @arg DAC_Align_12b_R: 12bit right data alignment selected
+  * @param  Data2: Data for DAC Channel2 to be loaded in the selected data holding register.
+  * @param  Data1: Data for DAC Channel1 to be loaded in the selected data  holding register.
+  * @note   In dual mode, a unique register access is required to write in both
+  *          DAC channels at the same time.
+  * @retval None
+  */
+void DAC_SetDualChannelData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1)
+{
+  uint32_t data = 0, tmp = 0;
+  
+  /* Check the parameters */
+  assert_param(IS_DAC_ALIGN(DAC_Align));
+  assert_param(IS_DAC_DATA(Data1));
+  assert_param(IS_DAC_DATA(Data2));
+  
+  /* Calculate and set dual DAC data holding register value */
+  if (DAC_Align == DAC_Align_8b_R)
+  {
+    data = ((uint32_t)Data2 << 8) | Data1; 
+  }
+  else
+  {
+    data = ((uint32_t)Data2 << 16) | Data1;
+  }
+  
+  tmp = (uint32_t)DAC_BASE;
+  tmp += DHR12RD_OFFSET + DAC_Align;
+
+  /* Set the dual DAC selected data holding register */
+  *(__IO uint32_t *)tmp = data;
+}
+
+/**
+  * @brief  Returns the last data output value of the selected DAC channel.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @retval The selected DAC channel data output value.
+  */
+uint16_t DAC_GetDataOutputValue(uint32_t DAC_Channel)
+{
+  __IO uint32_t tmp = 0;
+  
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  
+  tmp = (uint32_t) DAC_BASE ;
+  tmp += DOR_OFFSET + ((uint32_t)DAC_Channel >> 2);
+  
+  /* Returns the DAC channel data output register value */
+  return (uint16_t) (*(__IO uint32_t*) tmp);
+}
+/**
+  * @}
+  */
+
+/** @defgroup DAC_Group2 DMA management functions
+ *  @brief   DMA management functions
+ *
+@verbatim   
+ ===============================================================================
+                       ##### DMA management functions #####
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Enables or disables the specified DAC channel DMA request.
+  * @note   When enabled DMA1 is generated when an external trigger (EXTI Line9,
+  *         TIM2, TIM4, TIM5, TIM6, TIM7 or TIM8  but not a software trigger) occurs.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  NewState: new state of the selected DAC channel DMA request.
+  *          This parameter can be: ENABLE or DISABLE.
+  * @note   The DAC channel1 is mapped on DMA1 Stream 5 channel7 which must be
+  *          already configured.
+  * @note   The DAC channel2 is mapped on DMA1 Stream 6 channel7 which must be
+  *          already configured.    
+  * @retval None
+  */
+void DAC_DMACmd(uint32_t DAC_Channel, FunctionalState NewState)
+{
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+
+  if (NewState != DISABLE)
+  {
+    /* Enable the selected DAC channel DMA request */
+    DAC->CR |= (DAC_CR_DMAEN1 << DAC_Channel);
+  }
+  else
+  {
+    /* Disable the selected DAC channel DMA request */
+    DAC->CR &= (~(DAC_CR_DMAEN1 << DAC_Channel));
+  }
+}
+/**
+  * @}
+  */
+
+/** @defgroup DAC_Group3 Interrupts and flags management functions
+ *  @brief   Interrupts and flags management functions
+ *
+@verbatim   
+ ===============================================================================
+             ##### Interrupts and flags management functions #####
+ ===============================================================================  
+
+@endverbatim
+  * @{
+  */
+
+/**
+  * @brief  Enables or disables the specified DAC interrupts.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  DAC_IT: specifies the DAC interrupt sources to be enabled or disabled. 
+  *          This parameter can be the following values:
+  *            @arg DAC_IT_DMAUDR: DMA underrun interrupt mask
+  * @note   The DMA underrun occurs when a second external trigger arrives before the 
+  *         acknowledgement for the first external trigger is received (first request).
+  * @param  NewState: new state of the specified DAC interrupts.
+  *          This parameter can be: ENABLE or DISABLE.
+  * @retval None
+  */ 
+void DAC_ITConfig(uint32_t DAC_Channel, uint32_t DAC_IT, FunctionalState NewState)  
+{
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  assert_param(IS_FUNCTIONAL_STATE(NewState));
+  assert_param(IS_DAC_IT(DAC_IT)); 
+
+  if (NewState != DISABLE)
+  {
+    /* Enable the selected DAC interrupts */
+    DAC->CR |=  (DAC_IT << DAC_Channel);
+  }
+  else
+  {
+    /* Disable the selected DAC interrupts */
+    DAC->CR &= (~(uint32_t)(DAC_IT << DAC_Channel));
+  }
+}
+
+/**
+  * @brief  Checks whether the specified DAC flag is set or not.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  DAC_FLAG: specifies the flag to check. 
+  *          This parameter can be only of the following value:
+  *            @arg DAC_FLAG_DMAUDR: DMA underrun flag
+  * @note   The DMA underrun occurs when a second external trigger arrives before the 
+  *         acknowledgement for the first external trigger is received (first request).
+  * @retval The new state of DAC_FLAG (SET or RESET).
+  */
+FlagStatus DAC_GetFlagStatus(uint32_t DAC_Channel, uint32_t DAC_FLAG)
+{
+  FlagStatus bitstatus = RESET;
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  assert_param(IS_DAC_FLAG(DAC_FLAG));
+
+  /* Check the status of the specified DAC flag */
+  if ((DAC->SR & (DAC_FLAG << DAC_Channel)) != (uint8_t)RESET)
+  {
+    /* DAC_FLAG is set */
+    bitstatus = SET;
+  }
+  else
+  {
+    /* DAC_FLAG is reset */
+    bitstatus = RESET;
+  }
+  /* Return the DAC_FLAG status */
+  return  bitstatus;
+}
+
+/**
+  * @brief  Clears the DAC channel's pending flags.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  DAC_FLAG: specifies the flag to clear. 
+  *          This parameter can be of the following value:
+  *            @arg DAC_FLAG_DMAUDR: DMA underrun flag 
+  * @note   The DMA underrun occurs when a second external trigger arrives before the 
+  *         acknowledgement for the first external trigger is received (first request).                           
+  * @retval None
+  */
+void DAC_ClearFlag(uint32_t DAC_Channel, uint32_t DAC_FLAG)
+{
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  assert_param(IS_DAC_FLAG(DAC_FLAG));
+
+  /* Clear the selected DAC flags */
+  DAC->SR = (DAC_FLAG << DAC_Channel);
+}
+
+/**
+  * @brief  Checks whether the specified DAC interrupt has occurred or not.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  DAC_IT: specifies the DAC interrupt source to check. 
+  *          This parameter can be the following values:
+  *            @arg DAC_IT_DMAUDR: DMA underrun interrupt mask
+  * @note   The DMA underrun occurs when a second external trigger arrives before the 
+  *         acknowledgement for the first external trigger is received (first request).
+  * @retval The new state of DAC_IT (SET or RESET).
+  */
+ITStatus DAC_GetITStatus(uint32_t DAC_Channel, uint32_t DAC_IT)
+{
+  ITStatus bitstatus = RESET;
+  uint32_t enablestatus = 0;
+  
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  assert_param(IS_DAC_IT(DAC_IT));
+
+  /* Get the DAC_IT enable bit status */
+  enablestatus = (DAC->CR & (DAC_IT << DAC_Channel)) ;
+  
+  /* Check the status of the specified DAC interrupt */
+  if (((DAC->SR & (DAC_IT << DAC_Channel)) != (uint32_t)RESET) && enablestatus)
+  {
+    /* DAC_IT is set */
+    bitstatus = SET;
+  }
+  else
+  {
+    /* DAC_IT is reset */
+    bitstatus = RESET;
+  }
+  /* Return the DAC_IT status */
+  return  bitstatus;
+}
+
+/**
+  * @brief  Clears the DAC channel's interrupt pending bits.
+  * @param  DAC_Channel: The selected DAC channel. 
+  *          This parameter can be one of the following values:
+  *            @arg DAC_Channel_1: DAC Channel1 selected
+  *            @arg DAC_Channel_2: DAC Channel2 selected
+  * @param  DAC_IT: specifies the DAC interrupt pending bit to clear.
+  *          This parameter can be the following values:
+  *            @arg DAC_IT_DMAUDR: DMA underrun interrupt mask                         
+  * @note   The DMA underrun occurs when a second external trigger arrives before the 
+  *         acknowledgement for the first external trigger is received (first request).                           
+  * @retval None
+  */
+void DAC_ClearITPendingBit(uint32_t DAC_Channel, uint32_t DAC_IT)
+{
+  /* Check the parameters */
+  assert_param(IS_DAC_CHANNEL(DAC_Channel));
+  assert_param(IS_DAC_IT(DAC_IT)); 
+
+  /* Clear the selected DAC interrupt pending bits */
+  DAC->SR = (DAC_IT << DAC_Channel);
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stm/lib/stm32f4xx_dac.h b/stm/lib/stm32f4xx_dac.h
new file mode 100644
index 0000000000000000000000000000000000000000..62c0c872882b32a90aa0d45f0d4853628b1c3bb9
--- /dev/null
+++ b/stm/lib/stm32f4xx_dac.h
@@ -0,0 +1,304 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4xx_dac.h
+  * @author  MCD Application Team
+  * @version V1.1.0
+  * @date    11-January-2013
+  * @brief   This file contains all the functions prototypes for the DAC firmware 
+  *          library.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
+  *
+  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+  * You may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at:
+  *
+  *        http://www.st.com/software_license_agreement_liberty_v2
+  *
+  * Unless required by applicable law or agreed to in writing, software 
+  * distributed under the License is distributed on an "AS IS" BASIS, 
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F4xx_DAC_H
+#define __STM32F4xx_DAC_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx.h"
+
+/** @addtogroup STM32F4xx_StdPeriph_Driver
+  * @{
+  */
+
+/** @addtogroup DAC
+  * @{
+  */
+
+/* Exported types ------------------------------------------------------------*/
+
+/** 
+  * @brief  DAC Init structure definition
+  */
+
+typedef struct
+{
+  uint32_t DAC_Trigger;                      /*!< Specifies the external trigger for the selected DAC channel.
+                                                  This parameter can be a value of @ref DAC_trigger_selection */
+
+  uint32_t DAC_WaveGeneration;               /*!< Specifies whether DAC channel noise waves or triangle waves
+                                                  are generated, or whether no wave is generated.
+                                                  This parameter can be a value of @ref DAC_wave_generation */
+
+  uint32_t DAC_LFSRUnmask_TriangleAmplitude; /*!< Specifies the LFSR mask for noise wave generation or
+                                                  the maximum amplitude triangle generation for the DAC channel. 
+                                                  This parameter can be a value of @ref DAC_lfsrunmask_triangleamplitude */
+
+  uint32_t DAC_OutputBuffer;                 /*!< Specifies whether the DAC channel output buffer is enabled or disabled.
+                                                  This parameter can be a value of @ref DAC_output_buffer */
+}DAC_InitTypeDef;
+
+/* Exported constants --------------------------------------------------------*/
+
+/** @defgroup DAC_Exported_Constants
+  * @{
+  */
+
+/** @defgroup DAC_trigger_selection 
+  * @{
+  */
+
+#define DAC_Trigger_None                   ((uint32_t)0x00000000) /*!< Conversion is automatic once the DAC1_DHRxxxx register 
+                                                                       has been loaded, and not by external trigger */
+#define DAC_Trigger_T2_TRGO                ((uint32_t)0x00000024) /*!< TIM2 TRGO selected as external conversion trigger for DAC channel */
+#define DAC_Trigger_T4_TRGO                ((uint32_t)0x0000002C) /*!< TIM4 TRGO selected as external conversion trigger for DAC channel */
+#define DAC_Trigger_T5_TRGO                ((uint32_t)0x0000001C) /*!< TIM5 TRGO selected as external conversion trigger for DAC channel */
+#define DAC_Trigger_T6_TRGO                ((uint32_t)0x00000004) /*!< TIM6 TRGO selected as external conversion trigger for DAC channel */
+#define DAC_Trigger_T7_TRGO                ((uint32_t)0x00000014) /*!< TIM7 TRGO selected as external conversion trigger for DAC channel */
+#define DAC_Trigger_T8_TRGO                ((uint32_t)0x0000000C) /*!< TIM8 TRGO selected as external conversion trigger for DAC channel */                                                                       
+
+#define DAC_Trigger_Ext_IT9                ((uint32_t)0x00000034) /*!< EXTI Line9 event selected as external conversion trigger for DAC channel */
+#define DAC_Trigger_Software               ((uint32_t)0x0000003C) /*!< Conversion started by software trigger for DAC channel */
+
+#define IS_DAC_TRIGGER(TRIGGER) (((TRIGGER) == DAC_Trigger_None) || \
+                                 ((TRIGGER) == DAC_Trigger_T6_TRGO) || \
+                                 ((TRIGGER) == DAC_Trigger_T8_TRGO) || \
+                                 ((TRIGGER) == DAC_Trigger_T7_TRGO) || \
+                                 ((TRIGGER) == DAC_Trigger_T5_TRGO) || \
+                                 ((TRIGGER) == DAC_Trigger_T2_TRGO) || \
+                                 ((TRIGGER) == DAC_Trigger_T4_TRGO) || \
+                                 ((TRIGGER) == DAC_Trigger_Ext_IT9) || \
+                                 ((TRIGGER) == DAC_Trigger_Software))
+
+/**
+  * @}
+  */
+
+/** @defgroup DAC_wave_generation 
+  * @{
+  */
+
+#define DAC_WaveGeneration_None            ((uint32_t)0x00000000)
+#define DAC_WaveGeneration_Noise           ((uint32_t)0x00000040)
+#define DAC_WaveGeneration_Triangle        ((uint32_t)0x00000080)
+#define IS_DAC_GENERATE_WAVE(WAVE) (((WAVE) == DAC_WaveGeneration_None) || \
+                                    ((WAVE) == DAC_WaveGeneration_Noise) || \
+                                    ((WAVE) == DAC_WaveGeneration_Triangle))
+/**
+  * @}
+  */
+
+/** @defgroup DAC_lfsrunmask_triangleamplitude
+  * @{
+  */
+
+#define DAC_LFSRUnmask_Bit0                ((uint32_t)0x00000000) /*!< Unmask DAC channel LFSR bit0 for noise wave generation */
+#define DAC_LFSRUnmask_Bits1_0             ((uint32_t)0x00000100) /*!< Unmask DAC channel LFSR bit[1:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits2_0             ((uint32_t)0x00000200) /*!< Unmask DAC channel LFSR bit[2:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits3_0             ((uint32_t)0x00000300) /*!< Unmask DAC channel LFSR bit[3:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits4_0             ((uint32_t)0x00000400) /*!< Unmask DAC channel LFSR bit[4:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits5_0             ((uint32_t)0x00000500) /*!< Unmask DAC channel LFSR bit[5:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits6_0             ((uint32_t)0x00000600) /*!< Unmask DAC channel LFSR bit[6:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits7_0             ((uint32_t)0x00000700) /*!< Unmask DAC channel LFSR bit[7:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits8_0             ((uint32_t)0x00000800) /*!< Unmask DAC channel LFSR bit[8:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits9_0             ((uint32_t)0x00000900) /*!< Unmask DAC channel LFSR bit[9:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits10_0            ((uint32_t)0x00000A00) /*!< Unmask DAC channel LFSR bit[10:0] for noise wave generation */
+#define DAC_LFSRUnmask_Bits11_0            ((uint32_t)0x00000B00) /*!< Unmask DAC channel LFSR bit[11:0] for noise wave generation */
+#define DAC_TriangleAmplitude_1            ((uint32_t)0x00000000) /*!< Select max triangle amplitude of 1 */
+#define DAC_TriangleAmplitude_3            ((uint32_t)0x00000100) /*!< Select max triangle amplitude of 3 */
+#define DAC_TriangleAmplitude_7            ((uint32_t)0x00000200) /*!< Select max triangle amplitude of 7 */
+#define DAC_TriangleAmplitude_15           ((uint32_t)0x00000300) /*!< Select max triangle amplitude of 15 */
+#define DAC_TriangleAmplitude_31           ((uint32_t)0x00000400) /*!< Select max triangle amplitude of 31 */
+#define DAC_TriangleAmplitude_63           ((uint32_t)0x00000500) /*!< Select max triangle amplitude of 63 */
+#define DAC_TriangleAmplitude_127          ((uint32_t)0x00000600) /*!< Select max triangle amplitude of 127 */
+#define DAC_TriangleAmplitude_255          ((uint32_t)0x00000700) /*!< Select max triangle amplitude of 255 */
+#define DAC_TriangleAmplitude_511          ((uint32_t)0x00000800) /*!< Select max triangle amplitude of 511 */
+#define DAC_TriangleAmplitude_1023         ((uint32_t)0x00000900) /*!< Select max triangle amplitude of 1023 */
+#define DAC_TriangleAmplitude_2047         ((uint32_t)0x00000A00) /*!< Select max triangle amplitude of 2047 */
+#define DAC_TriangleAmplitude_4095         ((uint32_t)0x00000B00) /*!< Select max triangle amplitude of 4095 */
+
+#define IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(VALUE) (((VALUE) == DAC_LFSRUnmask_Bit0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits1_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits2_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits3_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits4_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits5_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits6_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits7_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits8_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits9_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits10_0) || \
+                                                      ((VALUE) == DAC_LFSRUnmask_Bits11_0) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_1) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_3) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_7) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_15) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_31) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_63) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_127) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_255) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_511) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_1023) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_2047) || \
+                                                      ((VALUE) == DAC_TriangleAmplitude_4095))
+/**
+  * @}
+  */
+
+/** @defgroup DAC_output_buffer 
+  * @{
+  */
+
+#define DAC_OutputBuffer_Enable            ((uint32_t)0x00000000)
+#define DAC_OutputBuffer_Disable           ((uint32_t)0x00000002)
+#define IS_DAC_OUTPUT_BUFFER_STATE(STATE) (((STATE) == DAC_OutputBuffer_Enable) || \
+                                           ((STATE) == DAC_OutputBuffer_Disable))
+/**
+  * @}
+  */
+
+/** @defgroup DAC_Channel_selection 
+  * @{
+  */
+
+#define DAC_Channel_1                      ((uint32_t)0x00000000)
+#define DAC_Channel_2                      ((uint32_t)0x00000010)
+#define IS_DAC_CHANNEL(CHANNEL) (((CHANNEL) == DAC_Channel_1) || \
+                                 ((CHANNEL) == DAC_Channel_2))
+/**
+  * @}
+  */
+
+/** @defgroup DAC_data_alignement 
+  * @{
+  */
+
+#define DAC_Align_12b_R                    ((uint32_t)0x00000000)
+#define DAC_Align_12b_L                    ((uint32_t)0x00000004)
+#define DAC_Align_8b_R                     ((uint32_t)0x00000008)
+#define IS_DAC_ALIGN(ALIGN) (((ALIGN) == DAC_Align_12b_R) || \
+                             ((ALIGN) == DAC_Align_12b_L) || \
+                             ((ALIGN) == DAC_Align_8b_R))
+/**
+  * @}
+  */
+
+/** @defgroup DAC_wave_generation 
+  * @{
+  */
+
+#define DAC_Wave_Noise                     ((uint32_t)0x00000040)
+#define DAC_Wave_Triangle                  ((uint32_t)0x00000080)
+#define IS_DAC_WAVE(WAVE) (((WAVE) == DAC_Wave_Noise) || \
+                           ((WAVE) == DAC_Wave_Triangle))
+/**
+  * @}
+  */
+
+/** @defgroup DAC_data 
+  * @{
+  */
+
+#define IS_DAC_DATA(DATA) ((DATA) <= 0xFFF0) 
+/**
+  * @}
+  */
+  
+/** @defgroup DAC_interrupts_definition 
+  * @{
+  */   
+#define DAC_IT_DMAUDR                      ((uint32_t)0x00002000)  
+#define IS_DAC_IT(IT) (((IT) == DAC_IT_DMAUDR)) 
+
+/**
+  * @}
+  */ 
+
+/** @defgroup DAC_flags_definition 
+  * @{
+  */ 
+  
+#define DAC_FLAG_DMAUDR                    ((uint32_t)0x00002000)  
+#define IS_DAC_FLAG(FLAG) (((FLAG) == DAC_FLAG_DMAUDR))  
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions --------------------------------------------------------*/  
+
+/*  Function used to set the DAC configuration to the default reset state *****/  
+void DAC_DeInit(void);
+
+/*  DAC channels configuration: trigger, output buffer, data format functions */
+void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct);
+void DAC_StructInit(DAC_InitTypeDef* DAC_InitStruct);
+void DAC_Cmd(uint32_t DAC_Channel, FunctionalState NewState);
+void DAC_SoftwareTriggerCmd(uint32_t DAC_Channel, FunctionalState NewState);
+void DAC_DualSoftwareTriggerCmd(FunctionalState NewState);
+void DAC_WaveGenerationCmd(uint32_t DAC_Channel, uint32_t DAC_Wave, FunctionalState NewState);
+void DAC_SetChannel1Data(uint32_t DAC_Align, uint16_t Data);
+void DAC_SetChannel2Data(uint32_t DAC_Align, uint16_t Data);
+void DAC_SetDualChannelData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1);
+uint16_t DAC_GetDataOutputValue(uint32_t DAC_Channel);
+
+/* DMA management functions ***************************************************/
+void DAC_DMACmd(uint32_t DAC_Channel, FunctionalState NewState);
+
+/* Interrupts and flags management functions **********************************/
+void DAC_ITConfig(uint32_t DAC_Channel, uint32_t DAC_IT, FunctionalState NewState);
+FlagStatus DAC_GetFlagStatus(uint32_t DAC_Channel, uint32_t DAC_FLAG);
+void DAC_ClearFlag(uint32_t DAC_Channel, uint32_t DAC_FLAG);
+ITStatus DAC_GetITStatus(uint32_t DAC_Channel, uint32_t DAC_IT);
+void DAC_ClearITPendingBit(uint32_t DAC_Channel, uint32_t DAC_IT);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__STM32F4xx_DAC_H */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stm/main.c b/stm/main.c
index f8f1105c1cdf51fce5194f7d9929660e56f39ed7..996684cb894e776b2199750f16baae13f36e739f 100644
--- a/stm/main.c
+++ b/stm/main.c
@@ -20,6 +20,7 @@
 #include "usart.h"
 #include "usb.h"
 #include "ff.h"
+#include "audio.h"
 
 static FATFS fatfs0;
 
@@ -745,6 +746,9 @@ soft_reset:
     // servo
     servo_init();
 
+    // audio
+    audio_init();
+
     // add some functions to the python namespace
     {
         py_obj_t m = py_module_new();
diff --git a/stm/systick.c b/stm/systick.c
index c9d37a2df0b5d4c0e163040419e9cff8af3eddb7..1979ea7e0f3fe821046779c2f5ffeb6bc7f5d64d 100644
--- a/stm/systick.c
+++ b/stm/systick.c
@@ -14,6 +14,9 @@ void sys_tick_init(void) {
 // called on SysTick interrupt
 void SysTick_Handler(void) {
     sys_tick_counter++;
+    // hack!
+    void audio_drain(void);
+    audio_drain();
 }
 
 void sys_tick_delay_ms(uint32_t delay_ms) {