mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-09-20 16:15:51 +00:00
Extract LOTS of stuff into an audio API.
Prevent all manner of type and implementation leakage.
This commit is contained in:
parent
1b793da17f
commit
0294165481
@ -25,8 +25,7 @@
|
|||||||
#include "portapack_shared_memory.hpp"
|
#include "portapack_shared_memory.hpp"
|
||||||
using namespace portapack;
|
using namespace portapack;
|
||||||
|
|
||||||
#include "i2s.hpp"
|
#include "audio.hpp"
|
||||||
using namespace lpc43xx;
|
|
||||||
|
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
@ -128,20 +127,20 @@ AnalogAudioView::AnalogAudioView(
|
|||||||
this->on_show_options_modulation();
|
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) {
|
field_volume.on_change = [this](int32_t v) {
|
||||||
this->on_headphone_volume_changed(v);
|
this->on_headphone_volume_changed(v);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
audio::output::start();
|
||||||
|
|
||||||
update_modulation(static_cast<ReceiverModel::Mode>(modulation));
|
update_modulation(static_cast<ReceiverModel::Mode>(modulation));
|
||||||
}
|
}
|
||||||
|
|
||||||
AnalogAudioView::~AnalogAudioView() {
|
AnalogAudioView::~AnalogAudioView() {
|
||||||
// TODO: Manipulating audio codec here, and in ui_receiver.cpp. Good to do
|
// TODO: Manipulating audio codec here, and in ui_receiver.cpp. Good to do
|
||||||
// both?
|
// both?
|
||||||
i2s::i2s0::tx_mute();
|
audio::output::stop();
|
||||||
|
|
||||||
audio_codec.headphone_mute();
|
|
||||||
|
|
||||||
receiver_model.disable();
|
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) {
|
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);
|
receiver_model.set_headphone_volume(new_volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) {
|
void AnalogAudioView::update_modulation(const ReceiverModel::Mode modulation) {
|
||||||
|
audio::output::mute();
|
||||||
|
|
||||||
const auto is_wideband_spectrum_mode = (modulation == ReceiverModel::Mode::SpectrumAnalysis);
|
const auto is_wideband_spectrum_mode = (modulation == ReceiverModel::Mode::SpectrumAnalysis);
|
||||||
receiver_model.set_baseband_configuration({
|
receiver_model.set_baseband_configuration({
|
||||||
.mode = toUType(modulation),
|
.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.set_baseband_bandwidth(is_wideband_spectrum_mode ? 12000000 : 1750000);
|
||||||
receiver_model.enable();
|
receiver_model.enable();
|
||||||
|
|
||||||
i2s::i2s0::tx_unmute();
|
if( !is_wideband_spectrum_mode ) {
|
||||||
|
audio::output::unmute();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace ui */
|
} /* namespace ui */
|
||||||
|
@ -21,6 +21,154 @@
|
|||||||
|
|
||||||
#include "audio.hpp"
|
#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 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 */
|
} /* namespace audio */
|
||||||
|
@ -22,72 +22,47 @@
|
|||||||
#ifndef __AUDIO_H__
|
#ifndef __AUDIO_H__
|
||||||
#define __AUDIO_H__
|
#define __AUDIO_H__
|
||||||
|
|
||||||
#include "i2s.hpp"
|
#include "volume.hpp"
|
||||||
using namespace lpc43xx;
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace audio {
|
namespace audio {
|
||||||
|
|
||||||
constexpr i2s::ConfigTX i2s0_config_tx {
|
namespace output {
|
||||||
.dao = i2s::DAO {
|
|
||||||
.wordwidth = i2s::WordWidth::Bits16,
|
void start();
|
||||||
.mono = 0,
|
void stop();
|
||||||
.stop = 1,
|
|
||||||
.reset = 0,
|
void mute();
|
||||||
.ws_sel = 0,
|
void unmute();
|
||||||
.ws_halfperiod = 0x0f,
|
|
||||||
.mute = 1,
|
} /* namespace output */
|
||||||
},
|
|
||||||
.txrate = i2s::MCLKRate {
|
namespace headphone {
|
||||||
.x_divider = 0,
|
|
||||||
.y_divider = 0,
|
volume_range_t volume_range();
|
||||||
},
|
|
||||||
.txbitrate = i2s::BitRate {
|
void set_volume(const volume_t volume);
|
||||||
.bitrate = 7,
|
|
||||||
},
|
} /* namespace headphone */
|
||||||
.txmode = i2s::Mode {
|
|
||||||
.clksel = i2s::ClockSelect::BaseAudioClkOrExternalMCLK,
|
namespace debug {
|
||||||
.four_pin = 0,
|
|
||||||
.mclk_out_en = 1,
|
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 {
|
void set_rate(const Rate rate);
|
||||||
.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,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
} /* namespace audio */
|
} /* namespace audio */
|
||||||
|
|
||||||
|
@ -50,8 +50,6 @@ I2C i2c0(&I2CD0);
|
|||||||
SPI ssp0(&SPID1);
|
SPI ssp0(&SPID1);
|
||||||
SPI ssp1(&SPID2);
|
SPI ssp1(&SPID2);
|
||||||
|
|
||||||
wolfson::wm8731::WM8731 audio_codec { i2c0, portapack::wm8731_i2c_address };
|
|
||||||
|
|
||||||
si5351::Si5351 clock_generator {
|
si5351::Si5351 clock_generator {
|
||||||
i2c0, hackrf::one::si5351_i2c_address
|
i2c0, hackrf::one::si5351_i2c_address
|
||||||
};
|
};
|
||||||
@ -129,17 +127,8 @@ void init() {
|
|||||||
clock_manager.set_reference_ppb(persistent_memory::correction_ppb());
|
clock_manager.set_reference_ppb(persistent_memory::correction_ppb());
|
||||||
clock_manager.run_at_full_speed();
|
clock_manager.run_at_full_speed();
|
||||||
|
|
||||||
clock_manager.start_audio_pll();
|
audio::init();
|
||||||
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();
|
|
||||||
|
|
||||||
clock_manager.enable_first_if_clock();
|
clock_manager.enable_first_if_clock();
|
||||||
clock_manager.enable_second_if_clock();
|
clock_manager.enable_second_if_clock();
|
||||||
clock_manager.enable_codec_clocks();
|
clock_manager.enable_codec_clocks();
|
||||||
@ -152,7 +141,7 @@ void shutdown() {
|
|||||||
display.shutdown();
|
display.shutdown();
|
||||||
|
|
||||||
radio::disable();
|
radio::disable();
|
||||||
audio_codec.reset();
|
audio::shutdown();
|
||||||
clock_manager.shutdown();
|
clock_manager.shutdown();
|
||||||
|
|
||||||
power.shutdown();
|
power.shutdown();
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
#include "i2c_pp.hpp"
|
#include "i2c_pp.hpp"
|
||||||
#include "spi_pp.hpp"
|
#include "spi_pp.hpp"
|
||||||
#include "wm8731.hpp"
|
|
||||||
#include "si5351.hpp"
|
#include "si5351.hpp"
|
||||||
#include "lcd_ili9341.hpp"
|
#include "lcd_ili9341.hpp"
|
||||||
|
|
||||||
@ -43,8 +42,6 @@ extern I2C i2c0;
|
|||||||
extern SPI ssp0;
|
extern SPI ssp0;
|
||||||
extern SPI ssp1;
|
extern SPI ssp1;
|
||||||
|
|
||||||
extern wolfson::wm8731::WM8731 audio_codec;
|
|
||||||
|
|
||||||
extern si5351::Si5351 clock_generator;
|
extern si5351::Si5351 clock_generator;
|
||||||
extern ClockManager clock_manager;
|
extern ClockManager clock_manager;
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
#include "portapack.hpp"
|
#include "portapack.hpp"
|
||||||
using namespace portapack;
|
using namespace portapack;
|
||||||
|
|
||||||
|
#include "audio.hpp"
|
||||||
|
|
||||||
#include "dsp_fir_taps.hpp"
|
#include "dsp_fir_taps.hpp"
|
||||||
#include "dsp_iir.hpp"
|
#include "dsp_iir.hpp"
|
||||||
#include "dsp_iir_config.hpp"
|
#include "dsp_iir_config.hpp"
|
||||||
@ -62,7 +64,7 @@ void AMConfig::apply() const {
|
|||||||
audio_12k_hpf_300hz_config
|
audio_12k_hpf_300hz_config
|
||||||
};
|
};
|
||||||
shared_memory.baseband_queue.push(message);
|
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 {
|
void NBFMConfig::apply() const {
|
||||||
@ -76,7 +78,7 @@ void NBFMConfig::apply() const {
|
|||||||
audio_24k_deemph_300_6_config
|
audio_24k_deemph_300_6_config
|
||||||
};
|
};
|
||||||
shared_memory.baseband_queue.push(message);
|
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 {
|
void WFMConfig::apply() const {
|
||||||
@ -89,7 +91,7 @@ void WFMConfig::apply() const {
|
|||||||
audio_48k_deemph_2122_6_config
|
audio_48k_deemph_2122_6_config
|
||||||
};
|
};
|
||||||
shared_memory.baseband_queue.push(message);
|
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 { {
|
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
|
// TODO: Manipulating audio codec here, and in ui_receiver.cpp. Good to do
|
||||||
// both?
|
// both?
|
||||||
|
|
||||||
audio_codec.set_headphone_volume(headphone_volume_);
|
audio::headphone::set_volume(headphone_volume_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReceiverModel::update_modulation_configuration() {
|
void ReceiverModel::update_modulation_configuration() {
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
#include "radio.hpp"
|
#include "radio.hpp"
|
||||||
#include "string_format.hpp"
|
#include "string_format.hpp"
|
||||||
|
|
||||||
|
#include "audio.hpp"
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
/* DebugMemoryView *******************************************************/
|
/* DebugMemoryView *******************************************************/
|
||||||
@ -260,8 +262,8 @@ DebugMenuView::DebugMenuView(NavigationView& nav) {
|
|||||||
[](const size_t register_number) { return portapack::clock_generator.read_register(register_number); }
|
[](const size_t register_number) { return portapack::clock_generator.read_register(register_number); }
|
||||||
); } },
|
); } },
|
||||||
{ "WM8731", [&nav](){ nav.push<RegistersView>(
|
{ "WM8731", [&nav](){ nav.push<RegistersView>(
|
||||||
"WM8731", RegistersWidgetConfig { wolfson::wm8731::reg_count, 1, 3, 4 },
|
"WM8731", RegistersWidgetConfig { audio::debug::reg_count(), 1, 3, 4 },
|
||||||
[](const size_t register_number) { return portapack::audio_codec.read(register_number); }
|
[](const size_t register_number) { return audio::debug::reg_read(register_number); }
|
||||||
); } },
|
); } },
|
||||||
{ "Temperature", [&nav](){ nav.push<TemperatureView>(); } },
|
{ "Temperature", [&nav](){ nav.push<TemperatureView>(); } },
|
||||||
} });
|
} });
|
||||||
|
@ -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_tck = gpio[GPIO3_0]; // P6_1
|
||||||
constexpr GPIO gpio_cpld_tdi = gpio[GPIO3_1]; // P6_2
|
constexpr GPIO gpio_cpld_tdi = gpio[GPIO3_1]; // P6_2
|
||||||
|
|
||||||
/* I2C0 */
|
|
||||||
|
|
||||||
constexpr uint8_t wm8731_i2c_address = 0x1a;
|
|
||||||
|
|
||||||
} /* namespace portapack */
|
} /* namespace portapack */
|
||||||
|
|
||||||
#endif/*__PORTAPACK_HAL_H__*/
|
#endif/*__PORTAPACK_HAL_H__*/
|
||||||
|
Loading…
Reference in New Issue
Block a user