Skip to content

Commit 0ed4457

Browse files
ledneczkirleh
authored andcommitted
[I2S] Fix audio DAC driver
Several fixes have been applied to the driver, like removal of blocking calls. ANother fix is applied to the volume setting. The volume can be also set by specifying relative steps.
1 parent 8090e89 commit 0ed4457

File tree

2 files changed

+84
-23
lines changed

2 files changed

+84
-23
lines changed

src/modm/driver/dac/cs43l22.hpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -277,9 +277,9 @@ struct cs43l22
277277
MasterVolumeControl_t, AnalogZcAndSrSettings_t,
278278
MiscellaneousControls_t, LimiterControl1MinMaxThresholds_t >;
279279

280-
typedef int16_t centiBels_t;
281-
static constexpr centiBels_t MaxVolume = 120;
282-
static constexpr centiBels_t MinVolume = -1020;
280+
typedef int16_t centiBel_t;
281+
static constexpr centiBel_t MaxVolume = 120;
282+
static constexpr centiBel_t MinVolume = -1020;
283283
}; // struct cs43l22
284284

285285

@@ -307,11 +307,15 @@ class CS43L22 : public cs43l22, public modm::I2cDevice<I2cMaster, 3>
307307
* and min volume by cs43l22::MinVolume
308308
*/
309309
ResumableResult<bool>
310-
setMasterVolume(centiBels_t vol);
310+
setMasterVolume(centiBel_t vol);
311+
312+
ResumableResult<bool>
313+
setMasterVolumeRelative(centiBel_t rel_vol);
311314

312315
private:
313316
uint8_t tx_buffer[2];
314317
uint8_t rx_buffer;
318+
centiBel_t volume;
315319
bool success;
316320

317321
ResumableResult<bool>
@@ -320,6 +324,12 @@ class CS43L22 : public cs43l22, public modm::I2cDevice<I2cMaster, 3>
320324
ResumableResult<bool>
321325
readRegister(Register reg);
322326

327+
ResumableResult<bool>
328+
getMasterVolume();
329+
330+
void
331+
regToCentibel(uint8_t reg);
332+
323333
};
324334

325335
} // namespace modm

src/modm/driver/dac/cs43l22_impl.hpp

Lines changed: 70 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,43 +18,46 @@ namespace modm
1818

1919
template<typename I2cMaster, typename I2sMaster>
2020
CS43L22<I2cMaster, I2sMaster>::CS43L22(uint8_t i2cAddress)
21-
: I2cDevice<I2cMaster, 3>(i2cAddress) {}
21+
: I2cDevice<I2cMaster, 3>(i2cAddress)
22+
{
23+
volume = -300;
24+
}
2225

2326
template<typename I2cMaster, typename I2sMaster>
2427
ResumableResult<bool>
2528
CS43L22<I2cMaster, I2sMaster>::initialize()
2629
{
2730
RF_BEGIN();
2831
// Verify the chip ID
29-
success = RF_CALL_BLOCKING(readRegister(Register::ChipIdRevision));
32+
success = RF_CALL(readRegister(Register::ChipIdRevision));
3033
if (!success || (ChipId_t::get(static_cast<ChipId_t>(rx_buffer)) != ChipId::CS43L22))
3134
{
3235
RF_RETURN(false);
3336
}
34-
RF_CALL_BLOCKING(writeRegister(Register::PowerControl1, Power_t(Power::Down)));
35-
RF_CALL_BLOCKING(writeRegister(Register::PowerControl2, ChannelPowerHeadphoneA_t(ChannelPower::OnAlways) |
37+
RF_CALL(writeRegister(Register::PowerControl1, Power_t(Power::Down)));
38+
RF_CALL(writeRegister(Register::PowerControl2, ChannelPowerHeadphoneA_t(ChannelPower::OnAlways) |
3639
ChannelPowerHeadphoneB_t(ChannelPower::OnAlways) |
3740
ChannelPowerSpeakerA_t(ChannelPower::OffAlways) |
3841
ChannelPowerSpeakerB_t(ChannelPower::OffAlways)));
39-
RF_CALL_BLOCKING(writeRegister(Register::ClockingControl, ClockingControl::AUTO_DETECT));
40-
RF_CALL_BLOCKING(writeRegister(Register::InterfaceControl1, DacInterfaceFormat_t(DacInterfaceFormat::I2sPhillipsStandard) |
42+
RF_CALL(writeRegister(Register::ClockingControl, ClockingControl::AUTO_DETECT));
43+
RF_CALL(writeRegister(Register::InterfaceControl1, DacInterfaceFormat_t(DacInterfaceFormat::I2sPhillipsStandard) |
4144
Role_t(Role::Slave)));
42-
RF_CALL_BLOCKING(setMasterVolume(-30));
43-
RF_CALL_BLOCKING(writeRegister(Register::PowerControl1, Power_t(Power::Up)));
45+
RF_CALL(setMasterVolume(volume));
46+
RF_CALL(writeRegister(Register::PowerControl1, Power_t(Power::Up)));
4447
/* Additional configuration for the CODEC. These configurations are done to reduce
4548
the time needed for the Codec to power off. If these configurations are removed,
4649
then a long delay should be added between powering off the Codec and switching
4750
off the I2S peripheral MCLK clock (which is the operating clock for Codec).
4851
If this delay is not inserted, then the codec will not shut down properly and
4952
it results in high noise after shut down. */
50-
RF_CALL_BLOCKING(writeRegister(Register::AnalogZcAndSrSettings, AnalogSoftRampA_t(SoftRamp::Disabled) |
53+
RF_CALL(writeRegister(Register::AnalogZcAndSrSettings, AnalogSoftRampA_t(SoftRamp::Disabled) |
5154
AnalogSoftRampB_t(SoftRamp::Disabled) |
5255
AnalogZeroCrossingA_t(ZeroCrossing::Disabled) |
5356
AnalogZeroCrossingB_t(ZeroCrossing::Disabled)));
5457
/* Disable the digital soft ramp */
55-
RF_CALL_BLOCKING(writeRegister(Register::MiscellaneousControls, MiscellaneousControls_t(0x00)));
58+
RF_CALL(writeRegister(Register::MiscellaneousControls, MiscellaneousControls_t(0x00)));
5659
/* Disable the limiter attack level */
57-
RF_CALL_BLOCKING(writeRegister(Register::LimiterControl1MinMaxThresholds, LimiterControl1MinMaxThresholds_t(0x00)));
60+
RF_CALL(writeRegister(Register::LimiterControl1MinMaxThresholds, LimiterControl1MinMaxThresholds_t(0x00)));
5861
RF_END_RETURN(success);
5962
}
6063

@@ -75,23 +78,71 @@ CS43L22<I2cMaster, I2sMaster>::readRegister(Register reg)
7578
{
7679
RF_BEGIN();
7780
rx_buffer = static_cast<uint8_t>(reg);
81+
// First, set the internal address pointer
82+
// of the DAC to the requested register
83+
this->transaction.configureWrite(&rx_buffer, 1);
84+
RF_CALL(this->runTransaction());
7885
this->transaction.configureRead(&rx_buffer, 1);
7986
RF_END_RETURN_CALL(this->runTransaction());
8087
}
8188

8289
template<typename I2cMaster, typename I2sMaster>
8390
ResumableResult<bool>
84-
CS43L22<I2cMaster, I2sMaster>::setMasterVolume(centiBels_t vol)
91+
CS43L22<I2cMaster, I2sMaster>::setMasterVolume(centiBel_t vol)
8592
{
8693
RF_BEGIN();
87-
if (vol > MaxVolume)
88-
vol = MaxVolume;
89-
else if (vol < MinVolume)
90-
vol = MinVolume;
91-
vol /= 5;
92-
RF_CALL_BLOCKING(writeRegister(Register::MasterVolumeControlA, static_cast<MasterVol_t>(vol)));
93-
RF_CALL_BLOCKING(writeRegister(Register::MasterVolumeControlB, static_cast<MasterVol_t>(vol)));
94+
{
95+
volume = vol;
96+
if (volume > MaxVolume)
97+
volume = MaxVolume;
98+
else if (volume < MinVolume)
99+
volume = MinVolume;
100+
volume /= 5;
101+
if (volume < -128)
102+
volume += 256;
103+
}
104+
RF_CALL(writeRegister(Register::MasterVolumeControlA, static_cast<MasterVol_t>(volume)));
105+
RF_CALL(writeRegister(Register::MasterVolumeControlB, static_cast<MasterVol_t>(volume)));
94106
RF_END_RETURN(true);
95107
}
96108

109+
template<typename I2cMaster, typename I2sMaster>
110+
void
111+
CS43L22<I2cMaster, I2sMaster>::regToCentibel(uint8_t reg)
112+
{
113+
volume = reg;
114+
if (volume <= 24 and volume >= 0)
115+
volume *= 5;
116+
else if (volume <= 52 and volume > 24)
117+
volume = MinVolume;
118+
else if (volume <= 127 and volume > 52)
119+
volume = (256-volume)*(-5);
120+
else
121+
{
122+
volume |= 0xFF00;
123+
volume *= 5;
124+
}
125+
}
126+
127+
template<typename I2cMaster, typename I2sMaster>
128+
ResumableResult<bool>
129+
CS43L22<I2cMaster, I2sMaster>::setMasterVolumeRelative(centiBel_t rel_vol)
130+
{
131+
RF_BEGIN();
132+
if (RF_CALL(getMasterVolume()))
133+
{
134+
regToCentibel(rx_buffer);
135+
volume += rel_vol;
136+
RF_RETURN_CALL(setMasterVolume(volume));
137+
}
138+
RF_END_RETURN(false);
139+
}
140+
141+
template<typename I2cMaster, typename I2sMaster>
142+
ResumableResult<bool>
143+
CS43L22<I2cMaster, I2sMaster>::getMasterVolume()
144+
{
145+
return readRegister(Register::MasterVolumeControlA);
146+
}
147+
97148
} // namespace modm

0 commit comments

Comments
 (0)