-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathI2SOutput.cpp
More file actions
79 lines (73 loc) · 2.91 KB
/
I2SOutput.cpp
File metadata and controls
79 lines (73 loc) · 2.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
#include <Arduino.h>
#include "driver/i2s.h"
#include <math.h>
#include <SPIFFS.h>
#include <FS.h>
#include "SampleSource.h"
#include "I2SOutput.h"
// number of frames to try and send at once (a frame is a left and right sample)
#define NUM_FRAMES_TO_SEND 128
void i2sWriterTask(void *param)
{
I2SOutput *output = (I2SOutput *)param;
int availableBytes = 0;
int buffer_position = 0;
Frame_t frames[NUM_FRAMES_TO_SEND];
while (true)
{
// wait for some data to be requested
i2s_event_t evt;
if (xQueueReceive(output->m_i2sQueue, &evt, portMAX_DELAY) == pdPASS)
{
if (evt.type == I2S_EVENT_TX_DONE)
{
size_t bytesWritten = 0;
do
{
if (availableBytes == 0)
{
// get some frames from the wave file - a frame consists of a 16 bit left and right sample
output->m_sample_generator->getFrames(frames, NUM_FRAMES_TO_SEND);
// how maby bytes do we now have to send
availableBytes = NUM_FRAMES_TO_SEND * sizeof(uint32_t);
// reset the buffer position back to the start
buffer_position = 0;
}
// do we have something to write?
if (availableBytes > 0)
{
// write data to the i2s peripheral
i2s_write(output->m_i2sPort, buffer_position + (uint8_t *)frames,
availableBytes, &bytesWritten, portMAX_DELAY);
availableBytes -= bytesWritten;
buffer_position += bytesWritten;
}
} while (bytesWritten > 0);
}
}
}
}
void I2SOutput::start(i2s_port_t i2sPort, i2s_pin_config_t &i2sPins, SampleSource *sample_generator)
{
m_sample_generator = sample_generator;
// i2s config for writing both channels of I2S
i2s_config_t i2sConfig = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = m_sample_generator->getSampleRate(),
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S),
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 4,
.dma_buf_len = NUM_FRAMES_TO_SEND/2};
m_i2sPort = i2sPort;
//install and start i2s driver
i2s_driver_install(m_i2sPort, &i2sConfig, 4, &m_i2sQueue);
// set up the i2s pins
i2s_set_pin(m_i2sPort, &i2sPins);
// clear the DMA buffers
i2s_zero_dma_buffer(m_i2sPort);
// start a task to write samples to the i2s peripheral
TaskHandle_t writerTaskHandle;
xTaskCreatePinnedToCore(i2sWriterTask, "i2s Writer Task", 4096, this, 0, &writerTaskHandle,0);
}