diff --git a/src/aptsyncer.rs b/src/aptsyncer.rs new file mode 100644 index 0000000..cfce5c0 --- /dev/null +++ b/src/aptsyncer.rs @@ -0,0 +1,108 @@ +const SYNC_LENGHT : usize = 40; +const SYNCA_SEQ : [bool; 40] = [false, false, false, false, + true, true, false, false, // Pulse 1 + true, true, false, false, // Pulse 2 + true, true, false, false, // Pulse 3 + true, true, false, false, // Pulse 4 + true, true, false, false, // Pulse 5 + true, true, false, false, // Pulse 6 + true, true, false, false, // Pulse 7 + false, false, false, false, + false, false, false, false,]; + +const SYNCB_SEQ : [bool; 40] = [false, false, false, false, + true, true, true, false, false, + true, true, true, false, false, + true, true, true, false, false, + true, true, true, false, false, + true, true, true, false, false, + true, true, true, false, false, + true, true, true, false, false, + false]; + + +pub enum SyncedSample { + Sample(f32), + SyncA(f32), + SyncB(f32) +} + +pub struct APTSyncer<'a> { + state: Vec, + pos : usize, + nones_read: usize, + max_level : f32, + iterator: Box + 'a> +} + +impl<'a> APTSyncer<'a> { + pub fn from(mut iterator: I) -> APTSyncer<'a> where I: Iterator + 'a { + let mut state = Vec::new(); + let mut max_level = 0.0; + for _ in 0..SYNC_LENGHT { + match iterator.next() { + Some(x) => { + state.push(x); + max_level = f32::max(x, max_level); + }, + None => panic!("Could not retrieve enough samples to prime syncer") + } + } + + APTSyncer { + state: state, + pos: 0, + nones_read: 0, + max_level: max_level, + iterator: Box::new(iterator) + } + } + + fn is_marker(&mut self, marker : [bool; 40]) -> bool { + let mut score = 0; + for i in 0..SYNC_LENGHT { + let sync_pos = (self.pos + i) % SYNC_LENGHT; + let sample = self.state[sync_pos] / self.max_level; + if (sample > 0.5 && marker[i]) || (sample <= 0.5 && !marker[i]) { + score += 1; + } + } + + return score == 40; + } +} + +impl<'a> Iterator for APTSyncer<'a> { + type Item = SyncedSample; + + fn next(&mut self) -> Option { + + let is_a = self.is_marker(SYNCA_SEQ); + let is_b = self.is_marker(SYNCB_SEQ); + + let sample = self.state[self.pos]; + match self.iterator.next() { + Some(x) => { + self.state[self.pos] = x; + self.max_level = f32::max(x, self.max_level); + }, + None => self.nones_read += 1 + }; + + if self.nones_read >= SYNC_LENGHT { + return None; + } + + self.pos = (self.pos + 1) % SYNC_LENGHT; + + if is_a { + return Some(SyncedSample::SyncA(sample)); + } + else if is_b { + return Some(SyncedSample::SyncB(sample)); + } + else { + return Some(SyncedSample::Sample(sample)); + } + } +} diff --git a/src/main.rs b/src/main.rs index e55d2c6..5f567c5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ mod firfilter; mod resamplers; mod mixer; mod amdemod; +mod aptsyncer; use std::fs::File; use std::path::Path; @@ -15,6 +16,7 @@ use utils::float_sample_iterator; use firfilter::FIRFilter; use amdemod::SquaringAMDemodulator; use resamplers::{Upsampler, Downsampler}; +use aptsyncer::{APTSyncer, SyncedSample}; const LINES_PER_SECOND: u32 = 2; const PIXELS_PER_LINE: u32 = 2080; @@ -116,20 +118,36 @@ fn main() { let filter = FIRFilter::from(demod, coeffs); let upsampler = Upsampler::from(filter, 13); let downsampler = Downsampler::from(upsampler, 150); + let syncer = APTSyncer::from(downsampler); let mut x = 0; let mut y = 0; let mut max_level = 0.0; - for sample in downsampler { + + for synced_sample in syncer { + let sample = match synced_sample { + SyncedSample::Sample(s) => s, + SyncedSample::SyncA(s) =>{ + x = 0; + s + } + SyncedSample::SyncB(s) =>{ + x = PIXELS_PER_LINE / 2; + s + } + }; + max_level = f32::max(sample, max_level); let color = (sample / max_level * 255.0) as u8; - println!("{}", color); + //println!("{}", color); - img.put_pixel(x,y,image::Luma([color])); + if y < lines { + img.put_pixel(x,y,image::Luma([color])); + } x += 1; - if x > PIXELS_PER_LINE { + if x >= PIXELS_PER_LINE { x = 0; y += 1; }