Adding optimized signal generator

master
Ryan Summers 2021-08-10 13:39:33 +02:00
parent 4738a15886
commit d1b0a6956a
2 changed files with 18 additions and 24 deletions

View File

@ -279,7 +279,7 @@ const APP: () = {
let signal_config = { let signal_config = {
let frequency_tuning_word = let frequency_tuning_word =
(1u64 << (32 - BATCH_SIZE_SIZE_LOG2)) as u32; (1u64 << (32 - BATCH_SIZE_SIZE_LOG2)) as i32;
signal_generator::Config { signal_generator::Config {
// Same frequency as batch size. // Same frequency as batch size.

View File

@ -93,12 +93,12 @@ impl BasicConfig {
ftw / self.symmetry ftw / self.symmetry
} else { } else {
NYQUIST NYQUIST
} as u32, } as i32,
if symmetry_complement * NYQUIST > ftw { if symmetry_complement * NYQUIST > ftw {
ftw / symmetry_complement ftw / symmetry_complement
} else { } else {
NYQUIST NYQUIST
} as u32, } as i32,
]; ];
Ok(Config { Ok(Config {
@ -120,7 +120,7 @@ pub struct Config {
pub amplitude: i16, pub amplitude: i16,
/// The frequency tuning word of the signal. Phase is incremented by this amount /// The frequency tuning word of the signal. Phase is incremented by this amount
pub frequency_tuning_word: [u32; 2], pub frequency_tuning_word: [i32; 2],
} }
impl Default for Config { impl Default for Config {
@ -135,7 +135,7 @@ impl Default for Config {
#[derive(Debug)] #[derive(Debug)]
pub struct SignalGenerator { pub struct SignalGenerator {
phase_accumulator: u32, phase_accumulator: i32,
config: Config, config: Config,
} }
@ -174,32 +174,26 @@ impl core::iter::Iterator for SignalGenerator {
/// Get the next value in the generator sequence. /// Get the next value in the generator sequence.
fn next(&mut self) -> Option<i16> { fn next(&mut self) -> Option<i16> {
self.phase_accumulator = self.phase_accumulator.wrapping_add( let sign = self.phase_accumulator.is_negative();
if (self.phase_accumulator as i32).is_negative() { self.phase_accumulator = self
self.config.frequency_tuning_word[0] .phase_accumulator
} else { .wrapping_add(self.config.frequency_tuning_word[sign as usize]);
self.config.frequency_tuning_word[1]
},
);
let phase = self.phase_accumulator as i32; let scale = match self.config.signal {
Signal::Cosine => (dsp::cossin(self.phase_accumulator).0 >> 16),
let amplitude: i16 = match self.config.signal {
Signal::Cosine => (dsp::cossin(phase).0 >> 16) as i16,
Signal::Square => { Signal::Square => {
if phase.is_negative() { if sign {
i16::MAX -i16::MAX as i32
} else { } else {
-i16::MAX i16::MAX as i32
} }
} }
Signal::Triangle => i16::MAX - (phase.abs() >> 15) as i16, Signal::Triangle => {
i16::MAX as i32 - (self.phase_accumulator.abs() >> 15)
}
}; };
// Calculate the final output result as an i16. // Calculate the final output result as an i16.
let result = amplitude as i32 * self.config.amplitude as i32; Some(((self.config.amplitude as i32 * scale) >> 15) as _)
// Note: We downshift by 15-bits to preserve only one of the sign bits.
Some(((result + (1 << 14)) >> 15) as i16)
} }
} }