audio.c 2.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdint.h>

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

#include "nlr.h"
#include "misc.h"
#include "mpyconfig.h"
#include "parse.h"
#include "compile.h"
#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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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
93
94
95
96
97
98
#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);
}