circuitpython/stm/audio.c
Damien d99b05282d Change object representation from 1 big union to individual structs.
A big change.  Micro Python objects are allocated as individual structs
with the first element being a pointer to the type information (which
is itself an object).  This scheme follows CPython.  Much more flexible,
not necessarily slower, uses same heap memory, and can allocate objects
statically.

Also change name prefix, from py_ to mp_ (mp for Micro Python).
2013-12-21 18:17:45 +00:00

100 lines
2.8 KiB
C

#include <stdint.h>
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_dac.h"
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "parse.h"
#include "compile.h"
#include "obj.h"
#include "runtime.h"
#include "audio.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
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;
}
mp_obj_t pyb_audio_is_full(void) {
if (audio_is_full()) {
return mp_const_true;
} else {
return mp_const_false;
}
}
mp_obj_t pyb_audio_fill(mp_obj_t val) {
audio_fill(mp_obj_get_int(val));
return mp_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
mp_obj_t m = mp_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);
}