audio.c 2.84 KB
Newer Older
1
2
3
4
5
6
7
8
#include <stdint.h>

#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_dac.h"

#include "nlr.h"
#include "misc.h"
9
#include "mpconfig.h"
10
#include "parse.h"
11
#include "obj.h"
12
13
#include "runtime.h"

14
15
#include "audio.h"

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#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
47
48
49
mp_obj_t pyb_audio_dac(mp_obj_t val) {
    DAC_SetChannel2Data(DAC_Align_8b_R, mp_obj_get_int(val));
    return mp_const_none;
50
51
}

52
mp_obj_t pyb_audio_is_full(void) {
53
    if (audio_is_full()) {
54
        return mp_const_true;
55
    } else {
56
        return mp_const_false;
57
58
59
    }
}

60
61
62
mp_obj_t pyb_audio_fill(mp_obj_t val) {
    audio_fill(mp_obj_get_int(val));
    return mp_const_none;
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
}

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
93
    mp_obj_t m = mp_obj_new_module(qstr_from_str_static("audio"));
94
95
96
    rt_store_attr(m, qstr_from_str_static("dac"), rt_make_function_n(1, pyb_audio_dac));
    rt_store_attr(m, qstr_from_str_static("is_full"), rt_make_function_n(0, pyb_audio_is_full));
    rt_store_attr(m, qstr_from_str_static("fill"), rt_make_function_n(1, pyb_audio_fill));
97
98
    rt_store_name(qstr_from_str_static("audio"), m);
}