Skip to content

Commit ef6baee

Browse files
committed
[example] STM32F4-Disco: CS43L22 I2S DAC example
1 parent 3bb021d commit ef6baee

File tree

2 files changed

+148
-0
lines changed

2 files changed

+148
-0
lines changed
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* Copyright (c) 2021, Raphael Lehmann
3+
* Copyright (c) 2021, Christopher Durand
4+
*
5+
* This file is part of the modm project.
6+
*
7+
* This Source Code Form is subject to the terms of the Mozilla Public
8+
* License, v. 2.0. If a copy of the MPL was not distributed with this
9+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
10+
*/
11+
// ----------------------------------------------------------------------------
12+
13+
#include <array>
14+
#include <cmath>
15+
#include <limits>
16+
#include <modm/board.hpp>
17+
#include <modm/debug/logger.hpp>
18+
#include <modm/driver/dac/cs43l22.hpp>
19+
#include <modm/io/iostream.hpp>
20+
#include <modm/processing/timer.hpp>
21+
#include <numbers>
22+
23+
#include <arm_math.h>
24+
25+
// Set the log level
26+
#undef MODM_LOG_LEVEL
27+
#define MODM_LOG_LEVEL modm::log::DEBUG
28+
29+
// Create an IODeviceWrapper around the Uart Peripheral we want to use
30+
modm::IODeviceWrapper< Usart2, modm::IOBuffer::BlockIfFull > loggerDevice;
31+
32+
// Set all four logger streams to use the UART
33+
modm::log::Logger modm::log::debug(loggerDevice);
34+
modm::log::Logger modm::log::info(loggerDevice);
35+
modm::log::Logger modm::log::warning(loggerDevice);
36+
modm::log::Logger modm::log::error(loggerDevice);
37+
38+
using namespace Board;
39+
40+
template<typename T, std::size_t length>
41+
constexpr auto computeSinTable(uint8_t cycles=1)
42+
{
43+
std::array<T, length> data{};
44+
constexpr auto HalfOutput = std::numeric_limits<T>::max() / 2; // 16 bit full scale
45+
for (size_t i = 0; i < data.size(); ++i) {
46+
constexpr auto pi = std::numbers::pi_v<float>;
47+
data[i] = HalfOutput * (1 + arm_sin_f32(i * (2*pi / data.size() * cycles)));
48+
}
49+
return data;
50+
}
51+
52+
constexpr std::size_t bufferSize = 960; // 480
53+
auto bufferA = computeSinTable<uint16_t, bufferSize>(1);
54+
auto bufferB = computeSinTable<uint16_t, bufferSize>(2);
55+
volatile bool bufferA_ready{true};
56+
volatile bool bufferB_ready{true};
57+
58+
void
59+
transferCompleteIrqHandler()
60+
{
61+
LedGreen::reset();
62+
63+
if (bufferA_ready) {
64+
cs43::I2sMaster::setTxBufferAddress(uintptr_t(bufferA.data()), bufferSize);
65+
bufferA_ready = false;
66+
}
67+
else if (bufferB_ready) {
68+
cs43::I2sMaster::setTxBufferAddress(uintptr_t(bufferB.data()), bufferSize);
69+
bufferB_ready = false;
70+
}
71+
else {
72+
LedRed::toggle();
73+
//MODM_LOG_ERROR << "No buffer ready for DMA :(" << modm::endl;
74+
}
75+
cs43::I2sMaster::startDma();
76+
77+
LedGreen::set();
78+
}
79+
80+
int
81+
main()
82+
{
83+
Board::initialize();
84+
85+
// initialize Uart2 for MODM_LOG_*
86+
Usart2::connect<GpioOutputA2::Tx>();
87+
Usart2::initialize<Board::SystemClock, 115200_Bd>();
88+
89+
MODM_LOG_INFO << "Audio demo using CS43L22 I2S DAC on STM32F4-DSICOVERY" << modm::endl;
90+
91+
Dma1::enable();
92+
Dma2::enable();
93+
94+
Board::initializeCs43</*samplerate=*/48_kHz, /*tolerance=*/0.02_pct>();
95+
96+
modm::Cs43l22<cs43::I2cMaster> audioDac{cs43::I2CAddress};
97+
if (!RF_CALL_BLOCKING(audioDac.initialize())) {
98+
MODM_LOG_ERROR << "Unable to initialize CS43L22 audio DAC" << modm::endl;
99+
}
100+
if (!RF_CALL_BLOCKING(audioDac.setMasterVolume(-600))) {
101+
MODM_LOG_ERROR << "Unable to set master volume of CS43L22 audio DAC" << modm::endl;
102+
}
103+
104+
cs43::I2sMaster::setTransferCompleteIrqHandler(transferCompleteIrqHandler);
105+
cs43::I2sMaster::setTxBufferAddress(uintptr_t(bufferA.data()), bufferSize);
106+
cs43::I2sMaster::start();
107+
108+
modm::PeriodicTimer tmr{500ms};
109+
uint8_t counter{3};
110+
111+
while (true)
112+
{
113+
if (!bufferA_ready) {
114+
bufferA = computeSinTable<uint16_t, bufferSize>(counter++);
115+
bufferA_ready = true;
116+
}
117+
if (!bufferB_ready) {
118+
bufferB = computeSinTable<uint16_t, bufferSize>(counter++);
119+
bufferB_ready = true;
120+
}
121+
if (counter > 100) {
122+
counter = 3;
123+
}
124+
125+
if (tmr.execute()) {
126+
LedBlue::toggle();
127+
}
128+
129+
if (cs43::I2sMaster::hasDmaError()) {
130+
MODM_LOG_ERROR << "I2S DMA Error :(" << modm::endl;
131+
}
132+
}
133+
134+
return 0;
135+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<library>
2+
<extends>modm:disco-f407vg</extends>
3+
<options>
4+
<option name="modm:build:build.path">../../../build/stm32f4_discovery/audio_i2s</option>
5+
</options>
6+
<modules>
7+
<module>modm:debug</module>
8+
<module>modm:build:scons</module>
9+
<module>modm:platform:uart:2</module>
10+
<module>modm:processing:timer</module>
11+
<module>modm:cmsis:dsp:fast_math</module>
12+
</modules>
13+
</library>

0 commit comments

Comments
 (0)