Extract LOTS of stuff into an audio API.

Prevent all manner of type and implementation leakage.
This commit is contained in:
Jared Boone 2016-02-05 16:25:43 -08:00
parent 1b793da17f
commit 0294165481
8 changed files with 208 additions and 96 deletions

View File

@ -25,8 +25,7 @@
#include "portapack_shared_memory.hpp"
using namespace portapack;
#include "i2s.hpp"
using namespace lpc43xx;
#include "audio.hpp"
#include "utility.hpp"
@ -128,20 +127,20 @@ AnalogAudioView::AnalogAudioView(
this->on_show_options_modulation();
};
field_volume.set_value((receiver_model.headphone_volume() - wolfson::wm8731::headphone_gain_range.max).decibel() + 99);
field_volume.set_value((receiver_model.headphone_volume() - audio::headphone::volume_range().max).decibel() + 99);
field_volume.on_change = [this](int32_t v) {
this->on_headphone_volume_changed(v);
};
audio::output::start();
update_modulation(static_cast<ReceiverModel::Mode>(modulation));
}
AnalogAudioView::~AnalogAudioView() {
// TODO: Manipulating audio codec here, and in ui_receiver.cpp. Good to do
// both?
i2s::i2s0::tx_mute();
audio_codec.headphone_mute();
audio::output::stop();
receiver_model.disable();
}
@ -286,11 +285,13 @@ void AnalogAudioView::on_reference_ppm_correction_changed(int32_t v) {
}
void AnalogAudioView::on_headphone_volume_changed(int32_t v) {
const auto new_volume = volume_t::decibel(v - 99) + wolfson::wm8731::headphone_gain_range.max;
const auto new_volume = volume_t::decibel(v - 99) + audio::headphone::volume_range().max;
receiver_model.set_headphone_volume(new_volume);
}
void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) {
audio::output::mute();
const auto is_wideband_spectrum_mode = (modulation == ReceiverModel::Mode::SpectrumAnalysis);
receiver_model.set_baseband_configuration({
.mode = toUType(modulation),
@ -300,7 +301,9 @@ void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) {
receiver_model.set_baseband_bandwidth(is_wideband_spectrum_mode ? 12000000 : 1750000);
receiver_model.enable();
i2s::i2s0::tx_unmute();
if( !is_wideband_spectrum_mode ) {
audio::output::unmute();
}
}
} /* namespace ui */

View File

@ -21,6 +21,154 @@
#include "audio.hpp"
#include "portapack.hpp"
using portapack::i2c0;
using portapack::clock_manager;
#include "wm8731.hpp"
using wolfson::wm8731::WM8731;
#include "i2s.hpp"
using namespace lpc43xx;
namespace audio {
namespace {
constexpr i2s::ConfigTX i2s0_config_tx {
.dao = i2s::DAO {
.wordwidth = i2s::WordWidth::Bits16,
.mono = 0,
.stop = 1,
.reset = 0,
.ws_sel = 0,
.ws_halfperiod = 0x0f,
.mute = 1,
},
.txrate = i2s::MCLKRate {
.x_divider = 0,
.y_divider = 0,
},
.txbitrate = i2s::BitRate {
.bitrate = 7,
},
.txmode = i2s::Mode {
.clksel = i2s::ClockSelect::BaseAudioClkOrExternalMCLK,
.four_pin = 0,
.mclk_out_en = 1,
},
};
constexpr i2s::ConfigRX i2s0_config_rx {
.dai = i2s::DAI {
.wordwidth = i2s::WordWidth::Bits16,
.mono = 0,
.stop = 1,
.reset = 0,
.ws_sel = 1,
.ws_halfperiod = 0x0f,
},
.rxrate = i2s::MCLKRate {
.x_divider = 0,
.y_divider = 0,
},
.rxbitrate = i2s::BitRate {
.bitrate = 7,
},
.rxmode = i2s::Mode {
.clksel = i2s::ClockSelect::BaseAudioClkOrExternalMCLK,
.four_pin = 1,
.mclk_out_en = 0,
},
};
constexpr i2s::ConfigDMA i2s0_config_dma {
.dma1 = i2s::DMA {
.rx_enable = 1,
.tx_enable = 0,
.rx_depth = 4,
.tx_depth = 0,
},
.dma2 = i2s::DMA {
.rx_enable = 0,
.tx_enable = 1,
.rx_depth = 0,
.tx_depth = 4,
},
};
constexpr uint8_t wm8731_i2c_address = 0x1a;
WM8731 audio_codec { i2c0, wm8731_i2c_address };
} /* namespace */
namespace output {
void start() {
i2s::i2s0::tx_start();
unmute();
}
void stop() {
mute();
i2s::i2s0::tx_stop();
}
void mute() {
i2s::i2s0::tx_mute();
audio_codec.headphone_mute();
}
void unmute() {
i2s::i2s0::tx_unmute();
}
} /* namespace output */
namespace headphone {
volume_range_t volume_range() {
return wolfson::wm8731::headphone_gain_range;
}
void set_volume(const volume_t volume) {
audio_codec.set_headphone_volume(volume);
}
} /* namespace headphone */
namespace debug {
int reg_count() {
return wolfson::wm8731::reg_count;
}
uint16_t reg_read(const int register_number) {
return audio_codec.read(register_number);
}
} /* namespace debug */
void init() {
clock_manager.start_audio_pll();
audio_codec.init();
i2s::i2s0::configure(
i2s0_config_tx,
i2s0_config_rx,
i2s0_config_dma
);
}
void shutdown() {
audio_codec.reset();
output::stop();
}
void set_rate(const Rate rate) {
clock_manager.set_base_audio_clock_divider(toUType(rate));
}
} /* namespace audio */

View File

@ -22,72 +22,47 @@
#ifndef __AUDIO_H__
#define __AUDIO_H__
#include "i2s.hpp"
using namespace lpc43xx;
#include "volume.hpp"
#include <cstdint>
namespace audio {
constexpr i2s::ConfigTX i2s0_config_tx {
.dao = i2s::DAO {
.wordwidth = i2s::WordWidth::Bits16,
.mono = 0,
.stop = 1,
.reset = 0,
.ws_sel = 0,
.ws_halfperiod = 0x0f,
.mute = 1,
},
.txrate = i2s::MCLKRate {
.x_divider = 0,
.y_divider = 0,
},
.txbitrate = i2s::BitRate {
.bitrate = 7,
},
.txmode = i2s::Mode {
.clksel = i2s::ClockSelect::BaseAudioClkOrExternalMCLK,
.four_pin = 0,
.mclk_out_en = 1,
},
namespace output {
void start();
void stop();
void mute();
void unmute();
} /* namespace output */
namespace headphone {
volume_range_t volume_range();
void set_volume(const volume_t volume);
} /* namespace headphone */
namespace debug {
int reg_count();
uint16_t reg_read(const int register_number);
} /* namespace debug */
void init();
void shutdown();
enum class Rate {
Hz_12000 = 4,
Hz_24000 = 2,
Hz_48000 = 1,
};
constexpr i2s::ConfigRX i2s0_config_rx {
.dai = i2s::DAI {
.wordwidth = i2s::WordWidth::Bits16,
.mono = 0,
.stop = 1,
.reset = 0,
.ws_sel = 1,
.ws_halfperiod = 0x0f,
},
.rxrate = i2s::MCLKRate {
.x_divider = 0,
.y_divider = 0,
},
.rxbitrate = i2s::BitRate {
.bitrate = 7,
},
.rxmode = i2s::Mode {
.clksel = i2s::ClockSelect::BaseAudioClkOrExternalMCLK,
.four_pin = 1,
.mclk_out_en = 0,
},
};
constexpr i2s::ConfigDMA i2s0_config_dma {
.dma1 = i2s::DMA {
.rx_enable = 1,
.tx_enable = 0,
.rx_depth = 4,
.tx_depth = 0,
},
.dma2 = i2s::DMA {
.rx_enable = 0,
.tx_enable = 1,
.rx_depth = 0,
.tx_depth = 4,
},
};
void set_rate(const Rate rate);
} /* namespace audio */

View File

@ -50,8 +50,6 @@ I2C i2c0(&I2CD0);
SPI ssp0(&SPID1);
SPI ssp1(&SPID2);
wolfson::wm8731::WM8731 audio_codec { i2c0, portapack::wm8731_i2c_address };
si5351::Si5351 clock_generator {
i2c0, hackrf::one::si5351_i2c_address
};
@ -129,17 +127,8 @@ void init() {
clock_manager.set_reference_ppb(persistent_memory::correction_ppb());
clock_manager.run_at_full_speed();
clock_manager.start_audio_pll();
audio_codec.init();
i2s::i2s0::configure(
audio::i2s0_config_tx,
audio::i2s0_config_rx,
audio::i2s0_config_dma
);
i2s::i2s0::tx_start();
i2s::i2s0::rx_start();
audio::init();
clock_manager.enable_first_if_clock();
clock_manager.enable_second_if_clock();
clock_manager.enable_codec_clocks();
@ -152,7 +141,7 @@ void shutdown() {
display.shutdown();
radio::disable();
audio_codec.reset();
audio::shutdown();
clock_manager.shutdown();
power.shutdown();

View File

@ -25,7 +25,6 @@
#include "i2c_pp.hpp"
#include "spi_pp.hpp"
#include "wm8731.hpp"
#include "si5351.hpp"
#include "lcd_ili9341.hpp"
@ -43,8 +42,6 @@ extern I2C i2c0;
extern SPI ssp0;
extern SPI ssp1;
extern wolfson::wm8731::WM8731 audio_codec;
extern si5351::Si5351 clock_generator;
extern ClockManager clock_manager;

View File

@ -26,6 +26,8 @@
#include "portapack.hpp"
using namespace portapack;
#include "audio.hpp"
#include "dsp_fir_taps.hpp"
#include "dsp_iir.hpp"
#include "dsp_iir_config.hpp"
@ -62,7 +64,7 @@ void AMConfig::apply() const {
audio_12k_hpf_300hz_config
};
shared_memory.baseband_queue.push(message);
clock_manager.set_base_audio_clock_divider(4);
audio::set_rate(audio::Rate::Hz_12000);
}
void NBFMConfig::apply() const {
@ -76,7 +78,7 @@ void NBFMConfig::apply() const {
audio_24k_deemph_300_6_config
};
shared_memory.baseband_queue.push(message);
clock_manager.set_base_audio_clock_divider(2);
audio::set_rate(audio::Rate::Hz_24000);
}
void WFMConfig::apply() const {
@ -89,7 +91,7 @@ void WFMConfig::apply() const {
audio_48k_deemph_2122_6_config
};
shared_memory.baseband_queue.push(message);
clock_manager.set_base_audio_clock_divider(1);
audio::set_rate(audio::Rate::Hz_48000);
}
static constexpr std::array<AMConfig, 3> am_configs { {
@ -314,7 +316,7 @@ void ReceiverModel::update_headphone_volume() {
// TODO: Manipulating audio codec here, and in ui_receiver.cpp. Good to do
// both?
audio_codec.set_headphone_volume(headphone_volume_);
audio::headphone::set_volume(headphone_volume_);
}
void ReceiverModel::update_modulation_configuration() {

View File

@ -26,6 +26,8 @@
#include "radio.hpp"
#include "string_format.hpp"
#include "audio.hpp"
namespace ui {
/* DebugMemoryView *******************************************************/
@ -260,8 +262,8 @@ DebugMenuView::DebugMenuView(NavigationView& nav) {
[](const size_t register_number) { return portapack::clock_generator.read_register(register_number); }
); } },
{ "WM8731", [&nav](){ nav.push<RegistersView>(
"WM8731", RegistersWidgetConfig { wolfson::wm8731::reg_count, 1, 3, 4 },
[](const size_t register_number) { return portapack::audio_codec.read(register_number); }
"WM8731", RegistersWidgetConfig { audio::debug::reg_count(), 1, 3, 4 },
[](const size_t register_number) { return audio::debug::reg_read(register_number); }
); } },
{ "Temperature", [&nav](){ nav.push<TemperatureView>(); } },
} });

View File

@ -56,10 +56,6 @@ constexpr GPIO gpio_cpld_tdo = gpio[GPIO1_8]; // P1_5
constexpr GPIO gpio_cpld_tck = gpio[GPIO3_0]; // P6_1
constexpr GPIO gpio_cpld_tdi = gpio[GPIO3_1]; // P6_2
/* I2C0 */
constexpr uint8_t wm8731_i2c_address = 0x1a;
} /* namespace portapack */
#endif/*__PORTAPACK_HAL_H__*/