transceiver

This commit is contained in:
2025-10-05 19:35:08 +02:00
parent 96689cc3a6
commit 391c5e5c7c
10 changed files with 273 additions and 647 deletions

12
Cargo.lock generated
View File

@ -3330,6 +3330,18 @@ dependencies = [
"mio",
"pin-project-lite",
"slab",
"tokio-macros",
]
[[package]]
name = "tokio-macros"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]

View File

@ -10,4 +10,4 @@ egui_plot = "0.33.0"
hound = "3.5.1"
plotters = "0.3.7"
rand = "0.9.2"
tokio = "1.47.1"
tokio = { version = "1.47.1", features = ["macros", "sync", "time"] }

BIN
a.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

525
main.rs
View File

@ -1,525 +0,0 @@
#![allow(dead_code)]
use std::{
collections::VecDeque,
f32::consts::PI,
fs::File,
i16,
io::{self, Read, Write, stdout},
ops::{Add, Div, Mul, Sub},
os::unix::thread,
sync::{
Arc,
atomic::{AtomicU32, Ordering},
mpsc::{self, Receiver, Sender, TryRecvError, channel, sync_channel},
},
time::Duration,
};
mod bfsk;
mod complex;
pub mod fft;
mod filtering;
mod iq;
mod nco;
mod units;
mod windows;
mod ted;
use bfsk::BFSKMod;
use complex::Complex;
use complex::Complex32;
use cpal::{
SampleRate,
traits::{DeviceTrait, HostTrait, StreamTrait},
};
use fft::DFTAlgorithm;
use nco::Nco;
use eframe::{
egui::{self, Color32, Context, Vec2b, debug_text::print, decode_animated_image_uri},
glow::TOP_LEVEL_ARRAY_STRIDE,
};
use egui_plot::{
self, AxisHints, Bar, BarChart, HLine, Legend, Line, LineStyle, Plot, PlotPoints, VLine,
};
use plotters::style::Color;
use rand::{Rng, seq::index::sample};
use crate::{
bfsk::BFSKDem, fft::{dft::NaiveDFT, FFT}, filtering::{
dc_block::DCBlocker,
fir::FIRFilter,
impulse_response::design::{self, frequency_response, ir_from_transfer_function},
}, iq::IQSampler, ted::elg::ELGate, units::frequency::{self, hz_to_rad_per_sample}
};
// Utilities
fn map<T>(input: T, in_min: T, in_max: T, out_min: T, out_max: T) -> T
where
T: Clone + Add<Output = T> + Mul<Output = T> + Sub<Output = T> + Div<Output = T>,
{
((input - in_min.clone()) / (in_max - in_min)) * (out_max - out_min.clone()) + out_min
}
const BAUD_RATE: u32 = 1000;
fn main() {
//modulate();
//demodulate();
//return;
// Set up CPAL
let host = cpal::default_host();
let device = host
.default_input_device()
.expect("No input device available");
let mut config = device
.supported_input_configs()
.unwrap()
.next()
.unwrap()
.with_sample_rate(SampleRate(48000));
// Channel to move samples from callback to main thread
let (tx, rx) = sync_channel::<f32>(4096);
// Build input stream
/*
let stream = device
.build_input_stream(
&config.into(),
move |data: &[f32], _| {
for x in data.iter() {
let _ = tx.send(*x * 30.); // non-blocking send
}
},
move |err| eprintln!("Stream error: {}", err),
None,
)
.unwrap();
stream.play().unwrap();
*/
let (eye_tx, eye_rx) = mpsc::channel::<Vec<f32>>();
let (ctx_tx, ctx_rx) = mpsc::channel::<Arc<egui::Context>>();
std::thread::spawn(move || demodulator(rx, eye_tx, ctx_rx));
std::thread::spawn(move || {
let spec = hound::WavSpec {
channels: 1,
sample_rate: 48000,
bits_per_sample: 16,
sample_format: hound::SampleFormat::Int,
};
let mut writer = hound::WavWriter::create("audio/noised.wav", spec).unwrap();
let mut reader = hound::WavReader::open("audio/rec.wav").unwrap();
let mut rand = rand::rng();
let samples = reader.samples::<i16>();
for x in samples {
let noise = rand.random::<f32>() * 2. - 1.;
let sample = x.unwrap() as f32 / i16::MAX as f32 + noise * 0.9;
let _ = tx.send(sample);
writer
.write_sample((sample * i16::MAX as f32) as i16)
.unwrap();
std::thread::sleep(Duration::from_micros(21));
}
writer.finalize().unwrap();
});
let native_options = eframe::NativeOptions::default();
let _ = eframe::run_native(
"Egui",
native_options,
Box::new(|cc| Ok(Box::new(EguiApp::new(cc, eye_rx, ctx_tx)))),
);
}
fn demodulator(
rx: Receiver<f32>,
eye_sender: Sender<Vec<f32>>,
ctx_rx: Receiver<Arc<egui::Context>>,
) {
// Wait for egui context to request redraw
let ctx = ctx_rx.recv().unwrap();
// Modulation parameters
let frequency = 1700.;
let deviation = 500.;
// Data parameters
let sample_rate = 48000;
let baud_rate = BAUD_RATE;
let sample_per_symbol = sample_rate / baud_rate;
let mut iq_sampler = IQSampler::new(hz_to_rad_per_sample(frequency, sample_rate as f32));
// Corellators
let mut nco_pos = Nco::new(hz_to_rad_per_sample(deviation, sample_rate as f32));
let mut nco_neg = Nco::new(hz_to_rad_per_sample(-deviation, sample_rate as f32));
let corellator_length = (sample_per_symbol as f32 * 1.5) as usize;
let corellator_pos = (0..corellator_length)
.map(|i| {
nco_pos.step();
nco_pos.cexp() * windows::blackmann(i as f32 / (corellator_length as f32))
//nco_pos.cexp()
})
.collect::<Vec<_>>();
let corellator_neg = (0..corellator_length)
.map(|i| {
nco_neg.step();
nco_neg.cexp() * windows::blackmann(i as f32 / (corellator_length as f32))
//nco_neg.cexp()
})
.collect::<Vec<_>>();
let mut matched_filter_pos = FIRFilter::new(&corellator_pos);
let mut matched_filter_neg = FIRFilter::new(&corellator_neg);
matched_filter_pos.normalize_freq(hz_to_rad_per_sample(deviation,sample_rate as f32));
matched_filter_neg.normalize_freq(hz_to_rad_per_sample(deviation,sample_rate as f32));
let loop_p = 0.003;
let loop_i = 0.001;
let mut matched_filter = FIRFilter::new(&[Complex32::new(1., 0.); 20]);
matched_filter.normalize_dc();
let mut loop_filter_ir = vec![Complex32::new(loop_i, 0.); 30];
let len = loop_filter_ir.len();
//loop_filter_ir[0] = Complex32::new(loop_p + loop_i, 0.);
loop_filter_ir[len - 1] = Complex32::new(loop_p + loop_i, 0.);
let mut loop_filter = FIRFilter::new(&loop_filter_ir);
//loop_filter.normalize_dc();
//loop_filter.normalize_sum();
let mut elg = ELGate::new(sample_per_symbol as f32, loop_filter);
let mut dc_blocker = DCBlocker::new(0.999);
// Timing recovery
let mut preamble_count = 0;
let mut bit_index = 0;
let mut last = 0u8;
while let Ok(real_sample) = rx.recv() {
let iq = iq_sampler.sample(real_sample);
// Perform corellation
let neg_energy = matched_filter_neg.next(iq);
let pos_energy = matched_filter_pos.next(iq);
let matched =
matched_filter.next_real(dc_blocker.next_real(pos_energy.mag() - neg_energy.mag()));
if let Some((elg_sample, eye)) = elg.next_eye(matched) {
let _ = eye_sender.send(eye);
ctx.request_repaint();
//last >>= 1;
//last |= (!bit as u8) << 7;
let bit = elg_sample > 0.;
if elg_sample * elg_sample > 0.005 {
last >>= 1;
last |= (bit as u8) << 7;
//last <<= 1;
//last |= ((bit) as u8);
if preamble_count >= 2 {
bit_index += 1;
if bit_index >= 8 {
if last == 4 {
print!(" -- EOT");
println!();
preamble_count = 0;
bit_index = 0;
last = 0;
} else {
print!("{}", last as char);
bit_index = 0;
let _ = stdout().flush();
}
}
} else if last == 0xD8 {
preamble_count += 1;
if preamble_count == 2 {
println!("Incoming: ");
}
}
}
}
}
}
//#[derive(Default)]
struct EguiApp {
eye_rx: Receiver<Vec<f32>>,
eyes: VecDeque<Vec<f32>>,
}
impl EguiApp {
fn new(
cc: &eframe::CreationContext<'_>,
eye_rx: Receiver<Vec<f32>>,
ctx_tx: Sender<Arc<egui::Context>>,
) -> Self {
ctx_tx.send(Arc::new(cc.egui_ctx.clone())).unwrap();
Self {
eye_rx,
eyes: VecDeque::new(),
}
}
}
impl eframe::App for EguiApp {
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
egui::CentralPanel::default().show(ctx, |ui| {
let max_eyes = 100;
while let Ok(eye) = self.eye_rx.try_recv() {
self.eyes.push_back(eye);
}
while self.eyes.len() > max_eyes {
self.eyes.pop_front();
}
let axis_hints = AxisHints::new_x().min_thickness(2.);
Plot::new("Eye")
.legend(Legend::default())
.show_axes(Vec2b::TRUE)
.custom_x_axes(vec![axis_hints])
.show(ui, |plot_ui| {
//plot_ui.set_auto_bounds(Vec2b { x: false, y: false });
plot_ui.hline(HLine::new("", 0.).color(Color32::DARK_RED).width(2.));
for eye in self.eyes.iter() {
let line = Line::new(
"Eye",
eye.iter()
.enumerate()
.map(|(i, x)| [i as f64, *x as f64])
.collect::<Vec<_>>(),
)
.color(Color32::LIGHT_GREEN);
plot_ui.line(line);
}
})
});
}
}
fn demodulate() {
let mut reader = hound::WavReader::open("audio/modulated.wav").unwrap();
let samples = reader.samples::<i16>();
// Modulation parameters
let frequency = 1700.;
let deviation = 500.;
// Data parameters
let sample_rate = 48000;
let baud_rate = BAUD_RATE;
let sample_per_symbol = sample_rate / baud_rate;
let mut iq_sampler = IQSampler::new(hz_to_rad_per_sample(frequency, sample_rate as f32));
let iq = samples
.map(|x| iq_sampler.sample(x.unwrap() as f32 / i16::MAX as f32))
.collect::<Vec<_>>();
let mut nco_pos = Nco::new(hz_to_rad_per_sample(deviation, sample_rate as f32));
let mut nco_neg = Nco::new(hz_to_rad_per_sample(-deviation, sample_rate as f32));
let corellator_pos = (0..(sample_per_symbol * 1))
.map(|_| {
nco_pos.step();
nco_pos.cexp()
})
.collect::<Vec<_>>();
let corellator_neg = (0..(sample_per_symbol * 1))
.map(|_| {
nco_neg.step();
nco_neg.cexp()
})
.collect::<Vec<_>>();
let mut matched_filter_pos = FIRFilter::new(&corellator_pos);
let mut matched_filter_neg = FIRFilter::new(&corellator_neg);
let mut dem = vec![];
for x in &iq {
let pos = matched_filter_pos.next(x.clone());
let neg = matched_filter_neg.next(*x);
dem.push(pos.mag() - neg.mag());
}
// Symbol recovery
let mut bits = vec![];
let delta = 0.5;
let alpha = 0.01;
let mut current_sps = sample_per_symbol as f32;
let mut current_position = current_sps / 2.;
while current_position < dem.len() as f32 {
// Sample before after
let early_id = (current_position - (delta * current_sps)).max(0.).floor() as u32;
let late_id = (current_position + (delta * current_sps)).max(0.).floor() as u32;
if late_id as usize >= dem.len() {
break;
}
let early = dem[early_id as usize];
let late = dem[late_id as usize];
let error = early * early - late * late;
current_sps -= alpha * error;
bits.push(dem[current_position.floor() as usize] > 0.);
current_position += current_sps;
}
//assert!(bits.len() % 8 == 0);
let mut out_file = File::create("out.txt").unwrap();
let mut strip = 0;
let bit_slice = bits.as_slice();
for i in 0..100 {
let byte = bits_to_byte(&bit_slice[(i as usize)..(i as usize + 8)]);
if byte == 0b01010111u8 {
strip = i + 8;
}
}
for i in 0..strip {
bits.remove(i as usize);
}
for x in bits.chunks(8) {
if x.len() != 8 {
break;
}
out_file.write_all(&[bits_to_byte(x)]).unwrap();
}
}
fn modulate() {
// Modulation parameters
let frequency = 1700.;
let deviation = 500.;
// Data parameter
let sample_rate = 48000;
let baud_rate = BAUD_RATE;
let host = cpal::default_host();
let device = host.default_output_device().unwrap();
let mut supported_configs_range = device.supported_output_configs().unwrap();
let supported_config = supported_configs_range
.find(|config| {
config.sample_format() == cpal::SampleFormat::F32
&& config.min_sample_rate().0 <= 48000
&& config.max_sample_rate().0 >= 48000
})
.expect("Device does not support 48kHz f32 output");
let config = supported_config
.with_sample_rate(cpal::SampleRate(48_000))
.config();
loop {
let mut buffer = String::new();
let stdin = io::stdin(); // We get `Stdin` here.
stdin.read_line(&mut buffer).unwrap();
for c in buffer.bytes() {
print!("{}", c as char);
}
println!();
// Construct payload
let mut bitstream = std::iter::repeat_n(0b01010101u8, 64)
.chain(std::iter::repeat_n(0xD8, 2))
.chain(buffer.bytes())
.chain(std::iter::repeat_n(4u8, 32))
.flat_map(byte_to_bits);
let mut modulator = BFSKMod::new(
sample_rate / baud_rate,
units::frequency::hz_to_rad_per_sample(deviation, sample_rate as f32),
&mut bitstream,
);
let mut lo = Nco::new(units::frequency::hz_to_rad_per_sample(
frequency,
sample_rate as f32,
));
// To send
let stream = modulator
.zip(lo)
.map(|(s, up)| (s * up).re)
.collect::<Vec<_>>();
let sample_clock = Arc::new(AtomicU32::new(0));
let (tx, rx) = channel::<()>();
let stream = device
.build_output_stream(
&config,
move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
for d in data.iter_mut() {
if sample_clock.load(Ordering::Relaxed) as usize == stream.len() {
tx.send(()).unwrap();
break;
}
*d = stream[sample_clock.fetch_add(1, Ordering::Relaxed) as usize]
}
},
move |err| {
eprintln!("Stream error: {}", err);
},
None,
)
.unwrap();
stream.play().unwrap();
let _ = rx.recv();
stream.pause().unwrap();
}
}
fn byte_to_bits(byte: u8) -> Vec<bool> {
vec![
byte & 1 == 1,
(byte >> 1) & 1 == 1,
(byte >> 2) & 1 == 1,
(byte >> 3) & 1 == 1,
(byte >> 4) & 1 == 1,
(byte >> 5) & 1 == 1,
(byte >> 6) & 1 == 1,
(byte >> 7) & 1 == 1,
]
}
/*
fn bits_to_byte(bits: &[bool]) -> u8 {
bits[7] as u8 |
bits[6] as u8 >> 1 |
bits[5] as u8 >> 2 |
bits[4] as u8 >> 3 |
bits[3] as u8 >> 4 |
bits[2] as u8 >> 5 |
bits[1] as u8 >> 6 |
bits[0] as u8 >> 7
}
*/
fn bits_to_byte(bits: &[bool]) -> u8 {
bits[0] as u8
| (bits[1] as u8) << 1
| (bits[2] as u8) << 2
| (bits[3] as u8) << 3
| (bits[4] as u8) << 4
| (bits[5] as u8) << 5
| (bits[6] as u8) << 6
| (bits[7] as u8) << 7
}

110
out.csv
View File

@ -1,110 +0,0 @@
0.38777804,
0.5346923,
0.955388,
1.733541,
5.2373223,
45.05751,
44.103336,
4.6842055,
1.8379081,
0.87091005,
0.5719485,
0.35533598,
0.27624997,
0.19268566,
0.16302158,
0.121304035,
0.10800954,
0.08377376,
0.077206604,
0.061651066,
0.058252066,
0.047531676,
0.045770597,
0.037980493,
0.037127394,
0.031228758,
0.03090615,
0.026285518,
0.026280245,
0.022565575,
0.02275963,
0.019703189,
0.020024413,
0.01745844,
0.017861607,
0.015673414,
0.01613357,
0.014235352,
0.014733706,
0.013069027,
0.013593689,
0.01211653,
0.012661362,
0.011337315,
0.011897493,
0.010705299,
0.011277529,
0.010171418,
0.010757942,
0.00974708,
0.010348838,
0.009411645,
0.010026283,
0.009147926,
0.009779742,
0.008949807,
0.00960072,
0.008821197,
0.009495176,
0.008750506,
0.009448569,
0.008736015,
0.009464292,
0.008779442,
0.009542818,
0.008887626,
0.009689722,
0.009043873,
0.009894198,
0.00927059,
0.010178313,
0.009571863,
0.010547835,
0.009952907,
0.011006483,
0.010420783,
0.011571476,
0.0110045895,
0.012267068,
0.011714736,
0.013115023,
0.012580418,
0.014148514,
0.013637692,
0.015413456,
0.014933306,
0.01697256,
0.016537804,
0.018906314,
0.01854057,
0.021339945,
0.021077268,
0.024448153,
0.024345227,
0.02848497,
0.028632956,
0.033848535,
0.03441413,
0.04118385,
0.042437002,
0.05156152,
0.05403404,
0.066911034,
0.071660355,
0.09098071,
0.100297675,
0.13183416,
0.1515972,
0.20976184,
0.25736627,
1 0.38777804
2 0.5346923
3 0.955388
4 1.733541
5 5.2373223
6 45.05751
7 44.103336
8 4.6842055
9 1.8379081
10 0.87091005
11 0.5719485
12 0.35533598
13 0.27624997
14 0.19268566
15 0.16302158
16 0.121304035
17 0.10800954
18 0.08377376
19 0.077206604
20 0.061651066
21 0.058252066
22 0.047531676
23 0.045770597
24 0.037980493
25 0.037127394
26 0.031228758
27 0.03090615
28 0.026285518
29 0.026280245
30 0.022565575
31 0.02275963
32 0.019703189
33 0.020024413
34 0.01745844
35 0.017861607
36 0.015673414
37 0.01613357
38 0.014235352
39 0.014733706
40 0.013069027
41 0.013593689
42 0.01211653
43 0.012661362
44 0.011337315
45 0.011897493
46 0.010705299
47 0.011277529
48 0.010171418
49 0.010757942
50 0.00974708
51 0.010348838
52 0.009411645
53 0.010026283
54 0.009147926
55 0.009779742
56 0.008949807
57 0.00960072
58 0.008821197
59 0.009495176
60 0.008750506
61 0.009448569
62 0.008736015
63 0.009464292
64 0.008779442
65 0.009542818
66 0.008887626
67 0.009689722
68 0.009043873
69 0.009894198
70 0.00927059
71 0.010178313
72 0.009571863
73 0.010547835
74 0.009952907
75 0.011006483
76 0.010420783
77 0.011571476
78 0.0110045895
79 0.012267068
80 0.011714736
81 0.013115023
82 0.012580418
83 0.014148514
84 0.013637692
85 0.015413456
86 0.014933306
87 0.01697256
88 0.016537804
89 0.018906314
90 0.01854057
91 0.021339945
92 0.021077268
93 0.024448153
94 0.024345227
95 0.02848497
96 0.028632956
97 0.033848535
98 0.03441413
99 0.04118385
100 0.042437002
101 0.05156152
102 0.05403404
103 0.066911034
104 0.071660355
105 0.09098071
106 0.100297675
107 0.13183416
108 0.1515972
109 0.20976184
110 0.25736627

View File

@ -1 +0,0 @@
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

BIN
out.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -1,3 +0,0 @@
<EFBFBD><EFBFBD>ibidi Toilet[1],[2] est une web-série[3] machinima, créée par Alexey Gerasimov et diffusée sur sa chaîne YouTube DaFuq!?Boom! Produite à l'aide de Source Filmmaker, la série suit une guerre fictive entre des toilettes à tête humaine et des personnages humanoïdes dotés d'appareils électroniques à la place de la tête.
<10> 8<>a<EFBFBD>9<10>0<10>:1<><31><EFBFBD>0<EFBFBD><30>77<10>:8<><38><EFBFBD><EFBFBD>29<32><39><EFBFBD>:9:<3A><><EFBFBD>T:<3A><><EFBFBD>2<EFBFBD>27<10><>T;<3B><>29<18><16><><EFBFBD>4<EFBFBD>4<EFBFBD>4<10><>4<EFBFBD>2:<10>2<EFBFBD><32>27:<3A>:7<><37>aԶ2<D4B6>$7<>29<32>2:<10>4<EFBFBD>06<30><36>:9<10>4<EFBFBD>2<EFBFBD>9<10><>Թ<EFBFBD><D4B9>:<<3C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:<<16>27<10>09<30><39><EFBFBD>:<3A><>29<32><39>:<3A><><EFBFBD>47<10>2<10>0<EFBFBD><30><EFBFBD>T<EFBFBD><54>T<EFBFBD>0<EFBFBD><30>77<37> 68<36>0<10><>9<EFBFBD>1<EFBFBD>4<EFBFBD><34><EFBFBD><EFBFBD><EFBFBD>9<EFBFBD>77:<10>:<10>0<EFBFBD>9<EFBFBD><39>2:<3A>2<EFBFBD><32><EFBFBD>T<EFBFBD><54>2<10>08<><38><EFBFBD><EFBFBD>aT<61>2<EFBFBD>4<EFBFBD><34>:<3A><><EFBFBD>77<10>2<10>0<EFBFBD><30><EFBFBD>T<EFBFBD><54>T<EFBFBD>0<EFBFBD><30>77<37> 68<36>0<10>0<EFBFBD>9<10>0<EFBFBD><30>:6<>:<3A>2<EFBFBD>$7<>29<32>2:<16>27<32><37>7<EFBFBD><37>:9<>2<EFBFBD><32>2<EFBFBD>0<EFBFBD><30>1<10>0<EFBFBD><30><EFBFBD>T<EFBFBD><54>T<EFBFBD>0<EFBFBD><30>77-8<><38>9<EFBFBD><61><D1B3>2<05><><<3C>7<EFBFBD><37><EFBFBD>9<EFBFBD><39><EFBFBD>4<EFBFBD>4<EFBFBD>4<10><>4<EFBFBD>2:<10><><EFBFBD>77<37>2<10><>9<EFBFBD><39>T<EFBFBD><54>T<EFBFBD><54><EFBFBD>27<32>9<10><>:<3A>2<EFBFBD><32><EFBFBD>29<32>2<10><>1<EFBFBD>4<EFBFBD>2<EFBFBD>27:<3A>2<10><>9<10><><EFBFBD><EFBFBD><EFBFBD>9<EFBFBD>aP<10>aU<61>2<10>2<EFBFBD><32><EFBFBD><EFBFBD><EFBFBD>T<EFBFBD>0<10>2<10><>:<3A><16>09<30><39>:9<><39>:<10>2<10><>T<EFBFBD><54>T<EFBFBD><54><EFBFBD><EFBFBD>77<16>2:<10><>9<EFBFBD><39><EFBFBD>4<EFBFBD>4<EFBFBD>4<10><>4<EFBFBD>2<EFBFBD>9<16>:<3A>2<10><><EFBFBD>2<EFBFBD>2<:<3A>0<EFBFBD>29<32><39>9:<3A>28<>2<EFBFBD>07:6q<36><71>08<30>0<EFBFBD>2<EFBFBD><32>2<10>2<10><>4<EFBFBD>2:<3A><>9<EFBFBD>0<EFBFBD><30>1<10><>9<10>aU<61><55>9<10><13><><EFBFBD><EFBFBD><EFBFBD>9<EFBFBD><39>:<10>2<10><><EFBFBD><EFBFBD><EFBFBD>9<EFBFBD>2:<10><><EFBFBD><EFBFBD>07:<3A><><EFBFBD>2<EFBFBD><32><EFBFBD><EFBFBD><EFBFBD>2<10>0<EFBFBD><30><EFBFBD><EFBFBD>2<10>2<10>U<EFBFBD><55><EFBFBD>4<EFBFBD>4<EFBFBD>4<10>]<10>4<EFBFBD><34><EFBFBD><EFBFBD><EFBFBD>9<10>09<10>2<EFBFBD><32><16><>4<EFBFBD>2:<14>2<EFBFBD><32>77<37><37><EFBFBD>2<EFBFBD>4<EFBFBD>9<EFBFBD>4<EFBFBD><34>T<10>:<3A><><EFBFBD><EFBFBD>07<10>0<EFBFBD>9<10>0<EFBFBD><30><EFBFBD>T<EFBFBD><54>2<10>2<10><>:<<10>4<EFBFBD><34>Է9<10>06<30><16>4<EFBFBD><34>-<2D><><16>4<EFBFBD>9<EFBFBD>77:<3A><><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD><32>6<EFBFBD>4<EFBFBD><34>77<10>2<EFBFBD><32>7<EFBFBD><37><EFBFBD><EFBFBD>T<EFBFBD>49<10>0<10>29<32>2<16>27<32><37>T<EFBFBD><54><EFBFBD>4<EFBFBD>07:<10><>:<3A>2<EFBFBD>78<37><38><EFBFBD>4<EFBFBD><34>7<EFBFBD><37><EFBFBD>.<2E>-<2D>.<17><><16><>4<EFBFBD>2:<16><><EFBFBD>4<EFBFBD><34>9:<3A><><EFBFBD><EFBFBD>9<10><>9<EFBFBD>792<39><32>9<10><>9<EFBFBD><39>9:<3A><><16><>4<EFBFBD>2<EFBFBD>9<16><>0<10><><EFBFBD>2<10><>7<EFBFBD><37><EFBFBD>4<EFBFBD>2<EFBFBD><32><EFBFBD>4<EFBFBD><34>2:<3A><>:<3A>2<10>0<EFBFBD>9<10><><EFBFBD>9<EFBFBD><39><EFBFBD>2<10><>4:<3A><>7<EFBFBD><37><EFBFBD><EFBFBD>T<EFBFBD>49<10>0<10>29<32>2<EFBFBD>0<EFBFBD><30>1<10><>0<EFBFBD><30><EFBFBD><EFBFBD>2<EFBFBD><32><EFBFBD><EFBFBD>46<34>0<EFBFBD>1<EFBFBD><31><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD><32>:9<10>29<32>2<10>4<EFBFBD>4<EFBFBD>0<10>09<10>292<39>2<EFBFBD><32>0<EFBFBD><30>77<37><37>0<EFBFBD><30>2<EFBFBD><32>:<<3C><>9:<3A><>9<10><>]<5D>aP<61><50>0<10><>T<EFBFBD><54>4<EFBFBD>2<EFBFBD>aP<10><><EFBFBD>T<EFBFBD><54><EFBFBD>7<EFBFBD>2<EFBFBD><32><1B>2:<3A>aP<61><50>0<10><>9<EFBFBD>:<3A>2<EFBFBD>aP<10><><EFBFBD>T<EFBFBD><54><EFBFBD>7<EFBFBD>2<18>0<EFBFBD><30>1<10><>9<10><>:<<3C><>76<37>0<EFBFBD>9<10><><EFBFBD>T<EFBFBD>4<EFBFBD>2<10><>9<EFBFBD><39>9:<3A><>9<17>a@<10>09<30>49<10>2<10><><EFBFBD>T<EFBFBD><54><EFBFBD>7<EFBFBD>2<EFBFBD><10><>9<EFBFBD><39>9:<3A><>9<EFBFBD>77:<3A><><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD><32><EFBFBD>T<EFBFBD>aP<61>27<32>0<EFBFBD>49<10>0<10>29<32>2<10><>9<EFBFBD><39><EFBFBD>4<EFBFBD>4<EFBFBD>4<10><>4<EFBFBD>2<EFBFBD>9<EFBFBD>2:<10><>06<30><36>0<EFBFBD><30>2<10><>77:<10><><EFBFBD>::<3A>2<EFBFBD>1<EFBFBD><31>4<<3C><><EFBFBD>2<10>2<EFBFBD><32><EFBFBD>06<30><36>29<10><>:9<10><>4<EFBFBD>1<EFBFBD>2<10><>9<EFBFBD><39>9:<3A><>9

BIN
sine.wav

Binary file not shown.

View File

@ -11,16 +11,198 @@ mod windows;
mod ted;
mod math;
use cpal::Data;
use eframe::egui;
use std::{collections::VecDeque, time::Duration};
use tokio::{join, select, time::timeout};
use eframe::{egui, glow::SAMPLE_MASK_VALUE};
use tokio::sync::mpsc::{Receiver, Sender, channel};
use crate::{bfsk::BFSKMod, complex::Complex32, filtering::{dc_block::DCBlocker, fir::FIRFilter}, iq::IQSampler, nco::Nco, ted::elg::ELGate, units::frequency::hz_to_rad_per_sample};
const BAUD_RATE: u32 = 1000;
const SAMPLE_RATE: u32 = 48000;
enum TransceiverState
// Modulation parameters
const CENTER_FREQ: f32 = 1700.;
const DEVIATION: f32 = 500.;
pub trait SampleSender
{
Idle,
Receiving,
Transmitting,
fn open_link(&mut self);
fn send_samples(&mut self, samples: &[f32]);
fn close_link(&mut self);
}
struct Transceiver
{
data_receiver: Receiver<Vec<u8>>,
data_sender: Sender<Vec<u8>>,
samples_sender: Sender<f32>,
}
impl Transceiver
{
pub async fn start<T: SampleSender>(sample_sender: T) -> Self
{
let (transmitter_tx, transmitter_rx) = channel::<Vec<u8>>(4096);
let (acknowledged_tx, acknowledged_rx) = channel::<()>(32);
let (ack_tx, ack_rx) = channel::<()>(32);
let (samples_tx, samples_rx) = channel::<f32>(4096);
let (receiver_tx, receiver_rx) = channel::<Vec<u8>>(4096);
join!(
Self::transmitter(acknowledged_rx, transmitter_rx, ack_rx, sample_sender),
Self::receiver(acknowledged_tx, samples_rx, receiver_tx, ack_tx)
);
Self
{
data_receiver: receiver_rx,
data_sender: transmitter_tx,
samples_sender: samples_tx
}
}
async fn transmitter<T: SampleSender>(mut acknowledged: Receiver<()>, mut data_receiver: Receiver<Vec<u8>>, mut ack_receiver: Receiver<()>, mut samples_sender: T)
{
let mut send_queue: VecDeque<Frame> = VecDeque::new();
loop
{
if !send_queue.is_empty()
{
let to_send = send_queue.pop_front().unwrap();
// Create modulation
let bytes = to_send.bytes();
let mut bit_stream = bytes.iter().flat_map(|x| byte_to_bits(*x));
let mut modulator = BFSKMod::new((SAMPLE_RATE as f32 / BAUD_RATE as f32).round() as u32,
hz_to_rad_per_sample(DEVIATION, SAMPLE_RATE as f32),
&mut bit_stream);
let mut up_lo = Nco::new(hz_to_rad_per_sample(CENTER_FREQ, SAMPLE_RATE as f32));
let mut sample_buffer = vec![];
for (m, up) in modulator.zip(up_lo)
{
let sample = m * up;
sample_buffer.push(sample.re); // Project IQ
}
samples_sender.open_link();
samples_sender.send_samples(&sample_buffer);
samples_sender.close_link();
if let Frame::Data(_) = to_send
{
// Wait for ack
while !acknowledged.is_empty()
{
let _ = acknowledged.blocking_recv();
}
let ack_timout = timeout(Duration::from_secs(2), acknowledged.recv()).await;
if let Ok(Some(())) = ack_timout
{
// ACK Received : Ok
}
else
{
// Try again
send_queue.push_front(to_send);
}
}
}
else
{
let new = select!
{
Some(x) = data_receiver.recv() => Frame::Data(x),
Some(()) = ack_receiver.recv() => Frame::Ack,
};
match new
{
Frame::Ack => send_queue.push_front(Frame::Ack), // Highest importance
Frame::Data(x) => send_queue.push_back(Frame::Data(x))
}
}
}
}
async fn receiver(acknowledged: Sender<()>, mut samples: Receiver<f32>, data_sender: Sender<Vec<u8>>, ack_sender: Sender<()>)
{
let mut iq_sampler = IQSampler::new(hz_to_rad_per_sample(CENTER_FREQ, SAMPLE_RATE as f32));
let samples_per_symbol = (SAMPLE_RATE as f32) / (BAUD_RATE as f32);
let correllator_length = samples_per_symbol as usize;
let mut pos_nco = Nco::new(hz_to_rad_per_sample(DEVIATION, SAMPLE_RATE as f32));
let mut neg_nco = Nco::new(hz_to_rad_per_sample(-DEVIATION, SAMPLE_RATE as f32));
let pos_ir = (0..correllator_length).map(|_| {pos_nco.step(); pos_nco.cexp()});
let neg_ir = (0..correllator_length).map(|_| {neg_nco.step(); neg_nco.cexp()});
let mut pos_correllator = FIRFilter::new(&pos_ir.collect::<Vec<_>>());
let mut neg_correllator = FIRFilter::new(&neg_ir.collect::<Vec<_>>());
let mut matched_lowpass = FIRFilter::new(&vec![Complex32::new(1., 0.); samples_per_symbol as usize]);
let mut dc_block = DCBlocker::new(0.995);
let loop_i = 0.1;
let loop_p = 0.1;
let mut loop_ir = vec![Complex32::new(loop_i, 0.); samples_per_symbol as usize];
loop_ir.push(Complex32::new(loop_p, 0.));
let mut elg = ELGate::new(samples_per_symbol, FIRFilter::new(&loop_ir));
// Frame reconstruction
let mut last_byte = 0x00u8;
let mut frame_constructor = FrameConstructor::new();
let mut bit_count: Option<u32> = None;
while let Some(sample) = samples.recv().await
{
let iq = iq_sampler.sample(sample);
let matched = dc_block.next_real(matched_lowpass.next_real(pos_correllator.next(iq).mag() - neg_correllator.next(iq).mag()));
if let Some(bit_sample) = elg.next(matched)
{
last_byte <<= 1;
last_byte |= (bit_sample > 0.) as u8;
bit_count = bit_count.map(|x| x + 1);
if last_byte == 0xD8 // Potential frame starts
{
last_byte = 0;
frame_constructor = FrameConstructor::new();
bit_count = Some(0);
}
if let Some(8) = bit_count
{
let frame_opt = frame_constructor.add_byte(last_byte);
if let Ok(None) = frame_opt
{
bit_count = Some(0);
}
if let Ok(Some(Frame::Ack)) = frame_opt
{
bit_count = None;
acknowledged.send(()).await.unwrap(); // Send acknowledgement to transmitter
}
if let Ok(Some(Frame::Data(ref frame_data))) = frame_opt
{
bit_count = None;
data_sender.send(frame_data.to_vec()).await.unwrap();
ack_sender.send(()).await.unwrap();
}
if let Err(()) = frame_opt
{
bit_count = None; // Erroneous frame, ignore
}
}
}
}
}
}
enum Frame
@ -29,6 +211,76 @@ enum Frame
Ack
}
type FrameConstructionError = ();
pub struct FrameConstructor
{
frame: Vec<u8>,
frame_countdown: Option<u16>,
checksum: u8,
}
impl FrameConstructor
{
pub fn new() -> Self
{
Self
{
frame: Vec::new(),
frame_countdown: None,
checksum: 0u8,
}
}
pub fn add_byte(&mut self, byte: u8) -> Result<Option<Frame>, FrameConstructionError>
{
if self.frame.is_empty() && byte != 0xC4 && byte != 0x4C
{
return Err(());
}
if self.frame.is_empty() && byte == 0xC4
{
return Ok(Some(Frame::Ack));
}
if self.frame.is_empty() && byte == 0x4C
{
return Ok(None);
}
self.frame.push(byte);
// Retrieve length
if self.frame.len() == 1
{
self.frame_countdown = Some(self.frame[0] as u16);
return Ok(None);
}
if self.frame.len() == 2
{
*self.frame_countdown.as_mut().unwrap() |= (self.frame[1] as u16) << 8;
return Ok(None);
}
if self.frame_countdown.unwrap() == 0
{
// All data has been received
if self.checksum == byte
{
return Ok(Some(Frame::Data(self.frame.iter().skip(2).copied().collect())));
}
return Err(());
}
self.frame.push(byte);
self.checksum ^= byte;
*self.frame_countdown.as_mut().unwrap() -= 1;
Ok(None)
}
}
impl Frame
{
pub fn bytes(&self) -> Vec<u8>
@ -51,6 +303,7 @@ impl Frame
assert!(x.len() < 65536, "Data size over MTU");
let len_u16 = x.len() as u16;
output_bytes.push(0x4C); // DATA FRAME
output_bytes.push((len_u16 & 0xFF).try_into().unwrap());
output_bytes.push(((len_u16 >> 8) & 0xFF).try_into().unwrap());
@ -60,7 +313,7 @@ impl Frame
}
Frame::Ack =>
{
output_bytes.push(0xC4);
output_bytes.push(0xC4); // ACK FRAME
}
}