1use crate::{
33 bitstream::{EncodingVariant, TrackCodec, TrackDataStreamT},
34 diskimage::TrackRegion,
35 io::{Error, ErrorKind, Read, Result, Seek, SeekFrom},
36 range_check::RangeChecker,
37 DiskDataEncoding,
38};
39use bit_vec::BitVec;
40use std::ops::Index;
41
42pub const FM_BYTE_LEN: usize = 16;
43pub const FM_MARKER_LEN: usize = 64;
44
45pub const FM_MARKER_DATA_MASK: u64 = 0x0000_0000_0000_5555;
47
48pub const FM_MARKER_CLOCK_MASK: u64 = 0xAAAA_AAAA_AAAA_AAAA;
49pub const FM_MARKER_CLOCK_PATTERN: u64 = 0xAAAA_AAAA_AAAA_A02A;
50
51#[doc(hidden)]
52#[macro_export]
53macro_rules! fm_offset {
54 ($x:expr) => {
55 $x * 16
56 };
57}
58
59pub struct FmCodec {
60 bit_vec: BitVec,
61 clock_map: BitVec,
62 weak_enabled: bool,
63 weak_mask: BitVec,
64 initial_phase: usize,
65 bit_cursor: usize,
66 track_padding: usize,
67 data_ranges: RangeChecker,
68 data_ranges_filtered: RangeChecker,
69}
70
71pub enum FmEncodingType {
72 Data,
73 AddressMark,
74}
75
76pub fn get_fm_sync_offset(track: &BitVec) -> Option<bool> {
77 match find_sync(track, 0) {
78 Some(offset) => {
79 if offset % 2 == 0 {
80 Some(false)
81 }
82 else {
83 Some(true)
84 }
85 }
86 None => None,
87 }
88}
89
90pub fn find_sync(track: &BitVec, start_idx: usize) -> Option<usize> {
91 let mut shift_reg: u32 = 0;
92
93 for (i, bit) in track.into_iter().skip(start_idx).enumerate() {
94 shift_reg = shift_reg << 1 | (bit as u32);
95
96 if i >= 32 && shift_reg == 0xAA_AA_AA_AA {
97 return Some(i - 32);
98 }
99 }
100 None
101}
102
103impl TrackCodec for FmCodec {
104 fn encoding(&self) -> DiskDataEncoding {
105 DiskDataEncoding::Fm
106 }
107
108 fn len(&self) -> usize {
109 self.bit_vec.len()
110 }
111
112 fn is_empty(&self) -> bool {
113 self.bit_vec.is_empty()
114 }
115
116 fn replace(&mut self, new_bits: BitVec) {
117 self.bit_vec = new_bits;
118 }
119
120 fn data_bits(&self) -> &BitVec {
121 &self.bit_vec
122 }
123
124 fn data(&self) -> Vec<u8> {
125 self.bit_vec.to_bytes()
126 }
127
128 fn set_clock_map(&mut self, clock_map: BitVec) {
129 self.clock_map = clock_map;
130 }
131
132 fn clock_map(&self) -> &BitVec {
133 &self.clock_map
134 }
135
136 fn clock_map_mut(&mut self) -> &mut BitVec {
137 &mut self.clock_map
138 }
139
140 fn enable_weak(&mut self, enable: bool) {
141 self.weak_enabled = enable;
142 }
143
144 fn weak_mask(&self) -> &BitVec {
145 &self.weak_mask
146 }
147
148 fn has_weak_bits(&self) -> bool {
149 !self.detect_weak_bits(6).0 > 0
150 }
151
152 fn weak_data(&self) -> Vec<u8> {
153 self.weak_mask.to_bytes()
154 }
155
156 fn set_track_padding(&mut self) {
157 let mut wrap_buffer: [u8; 4] = [0; 4];
158
159 if self.bit_vec.len() % 8 == 0 {
160 let found_pad = false;
164 for pad in 1..16 {
166 log::trace!(
167 "bitcells: {} data bits: {} window_start: {}",
168 self.bit_vec.len(),
169 self.bit_vec.len() / 2,
170 self.bit_vec.len() - (8 * 2)
171 );
172 let wrap_addr = (self.bit_vec.len() / 2) - (8 * 2);
173
174 self.track_padding = pad;
175
176 self.seek(SeekFrom::Start(wrap_addr as u64)).unwrap();
177 self.read_exact(&mut wrap_buffer).unwrap();
178
179 log::trace!(
180 "set_track_padding(): wrap_buffer at {}, pad {}: {:02X?}",
181 wrap_addr,
182 pad,
183 wrap_buffer
184 );
185 }
186
187 if !found_pad {
188 log::warn!("set_track_padding(): Unable to determine track padding.");
190 self.track_padding = 0;
191 }
192 }
193 else {
194 self.track_padding = 0;
197 }
198 }
199
200 fn read_raw_byte(&self, index: usize) -> Option<u8> {
201 if index >= self.len() {
202 return None;
203 }
204
205 let mut byte = 0;
206 for bi in index..std::cmp::min(index + 8, self.bit_vec.len()) {
207 byte = (byte << 1) | self.bit_vec[bi] as u8;
208 }
209 Some(byte)
210 }
211
212 fn read_decoded_byte(&self, index: usize) -> Option<u8> {
213 if index >= self.bit_vec.len() || index >= self.clock_map.len() {
214 log::error!(
215 "read_decoded_byte(): index out of bounds: {} vec: {} clock_map:{}",
216 index,
217 self.bit_vec.len(),
218 self.clock_map.len()
219 );
220 return None;
221 }
222 let p_off: usize = self.clock_map[index] as usize;
223 let mut byte = 0;
224 for bi in (index..std::cmp::min(index + FM_BYTE_LEN, self.bit_vec.len()))
225 .skip(p_off)
226 .step_by(2)
227 {
228 byte = (byte << 1) | self.bit_vec[bi] as u8;
229 }
230 Some(byte)
231 }
232
233 fn write_buf(&mut self, buf: &[u8], offset: usize) -> Option<usize> {
234 let encoded_buf = Self::encode(buf, false, EncodingVariant::Data);
235
236 let mut copy_len = encoded_buf.len();
237 if self.bit_vec.len() < offset + encoded_buf.len() {
238 copy_len = self.bit_vec.len() - offset;
239 }
240
241 let mut bits_written = 0;
242
243 let phase = !self.clock_map[offset] as usize;
244 println!("write_buf(): offset: {} phase: {}", offset, phase);
245
246 for (i, bit) in encoded_buf.into_iter().enumerate().take(copy_len) {
247 self.bit_vec.set(offset + phase + i, bit);
248 bits_written += 1;
249 }
250
251 let bytes_written = bits_written + 7 / 8;
252 Some(bytes_written)
253 }
254
255 fn write_raw_buf(&mut self, buf: &[u8], offset: usize) -> usize {
256 let mut bytes_written = 0;
257 let mut offset = offset;
258
259 for byte in buf {
260 for bit_pos in (0..8).rev() {
261 let bit = byte & (0x01 << bit_pos) != 0;
262 self.bit_vec.set(offset, bit);
263 offset += 1;
264 }
265 bytes_written += 1;
266 }
267
268 bytes_written
269 }
270
271 fn encode(&self, data: &[u8], prev_bit: bool, encoding_type: EncodingVariant) -> BitVec {
272 let mut bitvec = BitVec::new();
273 let mut bit_count = 0;
274
275 for &byte in data {
276 for i in (0..8).rev() {
277 let bit = (byte & (1 << i)) != 0;
278 if bit {
279 bitvec.push(false);
281 bitvec.push(true);
282 }
283 else {
284 let previous_bit = if bitvec.is_empty() {
286 prev_bit
287 }
288 else {
289 bitvec[bitvec.len() - 1]
290 };
291
292 if previous_bit {
293 bitvec.push(false);
294 }
295 else {
296 bitvec.push(true);
297 }
298 bitvec.push(false);
299 }
300
301 bit_count += 1;
302
303 if let EncodingVariant::AddressMark = encoding_type {
305 if bit_count == 4 {
306 bitvec.set(bitvec.len() - 2, false);
308 }
309 }
310 }
311
312 bit_count = 0;
314 }
315
316 bitvec
317 }
318
319 fn find_marker(&self, marker: u64, mask: Option<u64>, start: usize, limit: Option<usize>) -> Option<(usize, u16)> {
320 if self.bit_vec.is_empty() {
322 return None;
323 }
324
325 let mask = mask.unwrap_or(!0);
326
327 let mut shift_reg: u64 = 0;
328 let mut shift_ct: u32 = 0;
329
330 let search_limit = if let Some(provided_limit) = limit {
331 std::cmp::min(provided_limit, self.bit_vec.len())
332 }
333 else {
334 self.bit_vec.len()
335 };
336
337 for bi in start..search_limit {
338 shift_reg = (shift_reg << 1) | self.bit_vec[bi] as u64;
339 shift_ct += 1;
340
341 let have_marker = (shift_reg & FM_MARKER_CLOCK_MASK) == FM_MARKER_CLOCK_PATTERN;
342 let have_data = (shift_reg & FM_MARKER_DATA_MASK & mask) == marker & FM_MARKER_DATA_MASK & mask;
343
344 if shift_ct >= 64 && have_marker {
345 log::debug!(
346 "found marker clock at {}: Shift reg {:16X}: data: {:16X} mask: {:16X}, marker data: {:16X}",
347 bi - 64,
348 shift_reg & FM_MARKER_CLOCK_MASK,
349 shift_reg & FM_MARKER_DATA_MASK,
350 mask,
351 marker & FM_MARKER_DATA_MASK
352 );
353 }
354
355 if shift_ct >= 64 && have_marker && have_data {
356 log::debug!(
357 "Fm::find_marker(): Found marker at {} data match: {}",
358 bi - 64,
359 have_data
360 );
361 return Some(((bi - 64) + 1, (shift_reg & 0xFFFF) as u16));
362 }
363 }
364 log::debug!("Fm::find_marker(): Failed to find marker!");
365 None
366 }
367
368 fn set_data_ranges(&mut self, ranges: Vec<(usize, usize)>) {
369 let filtered_ranges = ranges
372 .iter()
373 .filter(|(start, end)| !(*start >= self.bit_vec.len() || *end >= self.bit_vec.len()))
374 .map(|(start, end)| (*start, *end))
375 .collect::<Vec<(usize, usize)>>();
376
377 self.data_ranges_filtered = RangeChecker::new(filtered_ranges);
378 self.data_ranges = RangeChecker::new(ranges);
379 }
380
381 fn is_data(&self, index: usize, wrapping: bool) -> bool {
382 if wrapping {
383 self.data_ranges.contains(index)
384 }
385 else {
386 self.data_ranges_filtered.contains(index)
387 }
388 }
389
390 fn debug_marker(&self, index: usize) -> String {
391 let mut shift_reg: u64 = 0;
392 for bi in index..std::cmp::min(index + 64, self.bit_vec.len()) {
393 shift_reg = (shift_reg << 1) | self.bit_vec[bi] as u64;
394 }
395 format!("{:16X}/{:064b}", shift_reg, shift_reg)
396 }
397
398 fn debug_decode(&self, index: usize) -> String {
399 let mut shift_reg: u32 = 0;
400 let start = index << 1;
401 for bi in (start..std::cmp::min(start + 64, self.bit_vec.len())).step_by(2) {
402 shift_reg = (shift_reg << 1) | self.bit_vec[self.initial_phase + bi] as u32;
403 }
404 format!("{:08X}/{:032b}", shift_reg, shift_reg)
405 }
406}
407
408impl FmCodec {
409 pub const WEAK_BIT_RUN: usize = 6;
410
411 pub fn new(mut bit_vec: BitVec, bit_ct: Option<usize>, weak_mask: Option<BitVec>) -> Self {
412 if let Some(bit_ct) = bit_ct {
414 bit_vec.truncate(bit_ct);
415 }
416
417 let encoding_sync = get_fm_sync_offset(&bit_vec).unwrap_or(false);
418 let sync = encoding_sync.into();
419
420 let clock_map = BitVec::from_elem(bit_vec.len(), encoding_sync);
421 let weak_mask = match weak_mask {
422 Some(mask) => mask,
423 None => BitVec::from_elem(bit_vec.len(), false),
424 };
425
426 if weak_mask.len() < bit_vec.len() {
427 panic!("Weak mask must be the same length as the bit vector");
428 }
429
430 FmCodec {
431 bit_vec,
432 clock_map,
433 weak_enabled: true,
434 weak_mask,
435 initial_phase: sync,
436 bit_cursor: sync,
437 track_padding: 0,
438 data_ranges: Default::default(),
439 data_ranges_filtered: Default::default(),
440 }
441 }
442
443 pub fn weak_data(&self) -> Vec<u8> {
444 self.weak_mask.to_bytes()
445 }
446
447 pub fn set_weak_mask(&mut self, weak_mask: BitVec) -> Result<()> {
448 if weak_mask.len() != self.bit_vec.len() {
449 return Err(Error::new(
450 ErrorKind::InvalidInput,
451 "Weak mask must be the same length as the bit vector",
452 ));
453 }
454 self.weak_mask = weak_mask;
455
456 Ok(())
457 }
458
459 pub fn encode(data: &[u8], prev_bit: bool, encoding_type: EncodingVariant) -> BitVec {
460 let mut bitvec = BitVec::new();
461 let mut bit_count = 0;
462
463 for &byte in data {
464 for i in (0..8).rev() {
465 let bit = (byte & (1 << i)) != 0;
466 if bit {
467 bitvec.push(false);
469 bitvec.push(true);
470 }
471 else {
472 let previous_bit = if bitvec.is_empty() {
474 prev_bit
475 }
476 else {
477 bitvec[bitvec.len() - 1]
478 };
479
480 if previous_bit {
481 bitvec.push(false);
482 }
483 else {
484 bitvec.push(true);
485 }
486 bitvec.push(false);
487 }
488
489 bit_count += 1;
490
491 if let EncodingVariant::AddressMark = encoding_type {
493 if bit_count == 4 {
494 bitvec.set(bitvec.len() - 2, false);
496 }
497 }
498 }
499
500 bit_count = 0;
502 }
503
504 bitvec
505 }
506
507 pub fn encode_marker(data: &[u8]) -> u64 {
512 assert_eq!(data.len(), 4);
513
514 let mut accum: u64 = 0;
515 let mut previous_bit = false;
518
519 for &byte in data {
520 for i in (0..8).rev() {
521 let bit = (byte & (1 << i)) != 0;
522 if bit {
523 accum = (accum << 2) | 0b01;
525 }
526 else {
527 if !previous_bit {
529 accum = (accum << 2) | 0b10;
530 }
531 else {
532 accum <<= 2;
533 }
534 }
535 previous_bit = bit;
536 }
537 }
538 accum
539 }
540
541 #[allow(dead_code)]
542 fn read_bit(self) -> Option<bool> {
543 if self.weak_enabled && self.weak_mask[self.bit_cursor] {
544 Some(rand::random())
546 }
547 else {
548 Some(self.bit_vec[self.bit_cursor])
549 }
550 }
551 #[allow(dead_code)]
552 fn read_bit_at(&self, index: usize) -> Option<bool> {
553 if self.weak_enabled && self.weak_mask[self.initial_phase + (index << 1)] {
554 Some(rand::random())
556 }
557 else {
558 Some(self.bit_vec[self.initial_phase + (index << 1)])
559 }
560 }
561
562 fn ref_bit_at(&self, index: usize) -> &bool {
563 let p_off: usize = self.clock_map[index] as usize;
564 if self.weak_enabled && self.weak_mask[p_off + (index << 1)] {
565 &self.bit_vec[p_off + (index << 1)]
568 }
569 else {
570 &self.bit_vec[p_off + (index << 1)]
571 }
572 }
573
574 pub(crate) fn detect_weak_bits(&self, run: usize) -> (usize, usize) {
575 let mut region_ct = 0;
576 let mut weak_bit_ct = 0;
577 let mut zero_ct = 0;
578
579 for bit in self.bit_vec.iter() {
580 if !bit {
581 zero_ct += 1;
582 }
583 else {
584 if zero_ct >= run {
585 region_ct += 1;
586 }
587 zero_ct = 0;
588 }
589
590 if zero_ct > 3 {
591 weak_bit_ct += 1;
592 }
593 }
594
595 (region_ct, weak_bit_ct)
596 }
597
598 #[allow(dead_code)]
599 pub(crate) fn detect_weak_regions(&self, run: usize) -> Vec<TrackRegion> {
600 let mut regions = Vec::new();
601
602 let mut zero_ct = 0;
603 let mut region_start = 0;
604 for (i, bit) in self.bit_vec.iter().enumerate() {
605 if !bit {
606 zero_ct += 1;
607 }
608 else {
609 if zero_ct >= run {
610 regions.push(TrackRegion {
611 start: region_start,
612 end: i - 1,
613 });
614 }
615 zero_ct = 0;
616 }
617
618 if zero_ct == run {
619 region_start = i;
620 }
621 }
622
623 regions
624 }
625
626 #[allow(dead_code)]
630 pub(crate) fn create_weak_bit_mask(&self, run: usize) -> BitVec {
631 let mut weak_bitvec = BitVec::new();
632 let mut zero_ct = 0;
633 for bit in self.bit_vec.iter() {
634 if !bit {
635 zero_ct += 1;
636 }
637 else {
638 zero_ct = 0;
639 }
640
641 if zero_ct > run {
642 weak_bitvec.push(true);
643 }
644 else {
645 weak_bitvec.push(false);
646 }
647 }
648
649 assert_eq!(weak_bitvec.len(), self.bit_vec.len());
650
651 weak_bitvec
652 }
653}
654
655impl Iterator for FmCodec {
656 type Item = bool;
657
658 fn next(&mut self) -> Option<Self::Item> {
659 if self.bit_cursor >= (self.bit_vec.len() - 1) {
660 return None;
661 }
662
663 let mut data_idx = self.bit_cursor + 1;
666 if data_idx > (self.bit_vec.len() - self.track_padding) {
667 data_idx = 0;
669 }
670
671 let decoded_bit = if self.weak_enabled && self.weak_mask[data_idx] {
672 rand::random()
674 }
675 else {
676 self.bit_vec[data_idx]
677 };
678
679 let new_cursor = data_idx + 1;
680 if new_cursor >= (self.bit_vec.len() - self.track_padding) {
681 self.bit_cursor = 0;
683 }
684 else {
685 self.bit_cursor = new_cursor;
686 }
687
688 Some(decoded_bit)
689 }
690}
691
692impl Seek for FmCodec {
693 fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
694 let (base, offset) = match pos {
695 SeekFrom::Start(offset) => (0, offset as isize),
697 SeekFrom::End(offset) => (self.bit_vec.len() as isize, offset as isize),
698 SeekFrom::Current(offset) => (self.bit_cursor as isize, offset as isize),
699 };
700
701 let new_pos = base.checked_add(offset).ok_or(Error::new(
702 ErrorKind::InvalidInput,
703 "invalid seek to a negative or overflowed position",
704 ))?;
705
706 let mut new_cursor = (new_pos as usize) << 1;
707 if !self.clock_map[new_cursor] {
723 new_cursor += 1;
725 }
726
727 if new_cursor > self.bit_vec.len() {
728 return Err(Error::new(
729 ErrorKind::InvalidInput,
730 "invalid seek to a negative or overflowed position",
731 ));
732 }
733
734 self.bit_cursor = new_cursor;
735 Ok(self.bit_cursor as u64)
738 }
739}
740
741impl Read for FmCodec {
742 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
743 let mut bytes_read = 0;
744 for byte in buf.iter_mut() {
745 let mut byte_val = 0;
746 for _ in 0..8 {
747 if let Some(bit) = self.next() {
748 byte_val = (byte_val << 1) | bit as u8;
749 }
750 else {
751 break;
752 }
753 }
754 *byte = byte_val;
755 bytes_read += 1;
756 }
757 Ok(bytes_read)
758 }
759}
760
761impl Index<usize> for FmCodec {
762 type Output = bool;
763
764 fn index(&self, index: usize) -> &Self::Output {
765 if index >= self.bit_vec.len() {
766 panic!("index out of bounds");
767 }
768
769 self.ref_bit_at(index)
771 }
772}
773
774impl TrackDataStreamT for FmCodec {}