Skip to content
This repository was archived by the owner on Apr 1, 2025. It is now read-only.

Commit 82e9db1

Browse files
committed
Add varicode shared module
1 parent 987d82e commit 82e9db1

File tree

5 files changed

+98
-115
lines changed

5 files changed

+98
-115
lines changed

dsp/src/codec/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod varicode;

dsp/src/codec/varicode.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
use std::collections::HashMap;
2+
3+
#[rustfmt::skip]
4+
const VARICODE: [u32; 128] = [
5+
// 0x00
6+
0b1010101011, 0b1011011011, 0b1011101101, 0b1101110111,
7+
0b1011101011, 0b1101011111, 0b1011101111, 0b1011111101,
8+
0b1011111111, 0b11101111, 0b11101, 0b1101101111,
9+
0b1011011101, 0b11111, 0b1101110101, 0b1110101011,
10+
// 0x10
11+
0b1011110111, 0b1011110101, 0b1110101101, 0b1110101111,
12+
0b1101011011, 0b1101101011, 0b1101101101, 0b1101010111,
13+
0b1101111011, 0b1101111101, 0b1110110111, 0b1101010101,
14+
0b1101011101, 0b1110111011, 0b1011111011, 0b1101111111,
15+
// 0x20
16+
0b1, 0b111111111, 0b101011111, 0b111110101,
17+
0b111011011, 0b1011010101, 0b1010111011, 0b101111111,
18+
0b11111011, 0b11110111, 0b101101111, 0b111011111,
19+
0b1110101, 0b110101, 0b1010111, 0b110101111,
20+
// 0x30
21+
0b10110111, 0b10111101, 0b11101101, 0b11111111,
22+
0b101110111, 0b101011011, 0b101101011, 0b110101101,
23+
0b110101011, 0b110110111, 0b11110101, 0b110111101,
24+
0b111101101, 0b1010101, 0b111010111, 0b1010101111,
25+
// 0x40
26+
0b1010111101, 0b1111101, 0b11101011, 0b10101101,
27+
0b10110101, 0b1110111, 0b11011011, 0b11111101,
28+
0b101010101, 0b1111111, 0b111111101, 0b101111101,
29+
0b11010111, 0b10111011, 0b11011101, 0b10101011,
30+
// 0x50
31+
0b11010101, 0b111011101, 0b10101111, 0b1101111,
32+
0b1101101, 0b101010111, 0b110110101, 0b101011101,
33+
0b101110101, 0b101111011, 0b1010101101, 0b111110111,
34+
0b111101111, 0b111111011, 0b1010111111, 0b101101101,
35+
// 0x60
36+
0b1011011111, 0b1011, 0b1011111, 0b101111,
37+
0b101101, 0b11, 0b111101, 0b1011011,
38+
0b101011, 0b1101, 0b111101011, 0b10111111,
39+
0b11011, 0b111011, 0b1111, 0b111,
40+
// 0x70
41+
0b111111, 0b110111111, 0b10101, 0b10111,
42+
0b101, 0b110111, 0b1111011, 0b1101011,
43+
0b11011111, 0b1011101, 0b111010101, 0b1010110111,
44+
0b110111011, 0b1010110101, 0b1011010111, 0b1110110101,
45+
];
46+
47+
fn bits(x: u32) -> impl Iterator<Item = bool> + Clone {
48+
// Extract bits, starting from the most significant 1-bit.
49+
(0..=x.ilog2()).rev().map(move |i| ((x >> i) & 1) != 0)
50+
}
51+
52+
/// Encode an ASCII byte into a stream of bits.
53+
///
54+
/// # Panics
55+
///
56+
/// Panics if the byte is not valid ASCII (outside of the range 0-127).
57+
pub fn encode_ascii_byte(ascii: u8) -> impl Iterator<Item = bool> + Clone {
58+
bits(VARICODE[ascii as usize] << 2)
59+
}
60+
61+
pub struct VaricodeDecode {
62+
bits: u32,
63+
lookup: HashMap<u32, u8>,
64+
}
65+
66+
impl VaricodeDecode {
67+
pub fn new() -> Self {
68+
Self {
69+
bits: 0,
70+
lookup: VARICODE
71+
.iter()
72+
.enumerate()
73+
.map(|(i, &x)| (x << 2, i as u8))
74+
.collect(),
75+
}
76+
}
77+
78+
/// Process an incoming bit.
79+
///
80+
/// If a byte has been successfully decoded from the sequence of bits,
81+
/// it will be returned.
82+
pub fn process(&mut self, bit: bool) -> Option<u8> {
83+
self.bits = (self.bits << 1) | bit as u32;
84+
let lookup = self.lookup.get(&self.bits).copied();
85+
if (self.bits & 0b11) == 0b00 {
86+
self.bits = 0;
87+
}
88+
lookup
89+
}
90+
}

dsp/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pub mod agc;
22
pub mod buffer;
33
pub mod channel;
4+
pub mod codec;
45
pub mod early_late;
56
pub mod filter;
67
pub mod iq;

labs/bpsk31-demod/src/main.rs

Lines changed: 4 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
use std::collections::HashMap;
2-
31
use hound::{WavReader, WavSpec, WavWriter};
42
use k9api_dsp::{
53
agc::Agc,
4+
codec::varicode::VaricodeDecode,
65
early_late::EarlyLate,
76
filter::{Fir, Passband, Window, WindowMethod},
87
iq::IQ,
@@ -52,13 +51,8 @@ fn main() {
5251
let mut matched_filter = Fir::raised_cosine(65, 1.0, 16.0);
5352
let mut timing = EarlyLate::new(0.0, 16);
5453

55-
let mut varicode_lookup = HashMap::new();
56-
for (i, &code) in VARICODE.iter().enumerate() {
57-
varicode_lookup.insert(code, i as u8);
58-
}
59-
6054
let mut differential = InverseDifferential::new();
61-
let mut bits: u32 = 0;
55+
let mut varicode = VaricodeDecode::new();
6256
let mut output = String::new();
6357

6458
loop {
@@ -88,19 +82,8 @@ fn main() {
8882
// TODO may need phase correction. Right now it seems to be in phase
8983
let bit = !differential.process(bit_sample.i > 0.0);
9084

91-
bits <<= 1;
92-
bits |= bit as u32;
93-
if bits != 0 && bits & 0b11 == 0 {
94-
println!("{:b}", bits);
95-
// End-of-character (two zeros) detected, and not idle:
96-
output.push(
97-
varicode_lookup
98-
.get(&(bits >> 2))
99-
.map(|&byte| byte as char)
100-
.unwrap_or(char::REPLACEMENT_CHARACTER),
101-
);
102-
103-
bits = 0;
85+
if let Some(byte) = varicode.process(bit) {
86+
output.push(byte as char);
10487
}
10588
}
10689
}
@@ -189,50 +172,6 @@ impl AFDomain {
189172
}
190173
}
191174

192-
#[rustfmt::skip]
193-
const VARICODE: [u32; 128] = [
194-
// 0x00
195-
0b1010101011, 0b1011011011, 0b1011101101, 0b1101110111,
196-
0b1011101011, 0b1101011111, 0b1011101111, 0b1011111101,
197-
0b1011111111, 0b11101111, 0b11101, 0b1101101111,
198-
0b1011011101, 0b11111, 0b1101110101, 0b1110101011,
199-
// 0x10
200-
0b1011110111, 0b1011110101, 0b1110101101, 0b1110101111,
201-
0b1101011011, 0b1101101011, 0b1101101101, 0b1101010111,
202-
0b1101111011, 0b1101111101, 0b1110110111, 0b1101010101,
203-
0b1101011101, 0b1110111011, 0b1011111011, 0b1101111111,
204-
// 0x20
205-
0b1, 0b111111111, 0b101011111, 0b111110101,
206-
0b111011011, 0b1011010101, 0b1010111011, 0b101111111,
207-
0b11111011, 0b11110111, 0b101101111, 0b111011111,
208-
0b1110101, 0b110101, 0b1010111, 0b110101111,
209-
// 0x30
210-
0b10110111, 0b10111101, 0b11101101, 0b11111111,
211-
0b101110111, 0b101011011, 0b101101011, 0b110101101,
212-
0b110101011, 0b110110111, 0b11110101, 0b110111101,
213-
0b111101101, 0b1010101, 0b111010111, 0b1010101111,
214-
// 0x40
215-
0b1010111101, 0b1111101, 0b11101011, 0b10101101,
216-
0b10110101, 0b1110111, 0b11011011, 0b11111101,
217-
0b101010101, 0b1111111, 0b111111101, 0b101111101,
218-
0b11010111, 0b10111011, 0b11011101, 0b10101011,
219-
// 0x50
220-
0b11010101, 0b111011101, 0b10101111, 0b1101111,
221-
0b1101101, 0b101010111, 0b110110101, 0b101011101,
222-
0b101110101, 0b101111011, 0b1010101101, 0b111110111,
223-
0b111101111, 0b111111011, 0b1010111111, 0b101101101,
224-
// 0x60
225-
0b1011011111, 0b1011, 0b1011111, 0b101111,
226-
0b101101, 0b11, 0b111101, 0b1011011,
227-
0b101011, 0b1101, 0b111101011, 0b10111111,
228-
0b11011, 0b111011, 0b1111, 0b111,
229-
// 0x70
230-
0b111111, 0b110111111, 0b10101, 0b10111,
231-
0b101, 0b110111, 0b1111011, 0b1101011,
232-
0b11011111, 0b1011101, 0b111010101, 0b1010110111,
233-
0b110111011, 0b1010110101, 0b1011010111, 0b1110110101,
234-
];
235-
236175
#[derive(Clone)]
237176
struct InverseDifferential {
238177
last: bool,

labs/bpsk31/src/main.rs

Lines changed: 2 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::iter::repeat;
33
use k9api_dsp::amplify;
44
use k9api_dsp::buffer::Buffer;
55
use k9api_dsp::channel::Awgn;
6+
use k9api_dsp::codec::varicode;
67
use k9api_dsp::filter::{Fir, Passband, Window, WindowMethod};
78
use k9api_dsp::math::Real;
89
use k9api_dsp::resample::Upsample;
@@ -26,7 +27,7 @@ fn main() {
2627
let bytes = b"CQ CQ CQ de K9API K9API K9API pse K\n";
2728
let mut diff = Differential::new();
2829
let mut bits = preamble
29-
.chain(bytes.iter().flat_map(|&b| bits(VARICODE[b as usize] << 2)))
30+
.chain(bytes.iter().flat_map(|&b| varicode::encode_ascii_byte(b)))
3031
.chain(postamble)
3132
.map(move |bit| Some(diff.process(bit)))
3233
.chain(repeat(None).take(30))
@@ -155,55 +156,6 @@ fn to_wav_file(sample_rate: u32, mut generator: impl FnMut(&mut [Real])) {
155156
writer.finalize().unwrap();
156157
}
157158

158-
fn bits(x: u32) -> impl Iterator<Item = bool> + Clone {
159-
// Extract bits, starting from the most significant 1-bit.
160-
(0..=x.ilog2()).rev().map(move |i| ((x >> i) & 1) != 0)
161-
}
162-
163-
#[rustfmt::skip]
164-
const VARICODE: [u32; 128] = [
165-
// 0x00
166-
0b1010101011, 0b1011011011, 0b1011101101, 0b1101110111,
167-
0b1011101011, 0b1101011111, 0b1011101111, 0b1011111101,
168-
0b1011111111, 0b11101111, 0b11101, 0b1101101111,
169-
0b1011011101, 0b11111, 0b1101110101, 0b1110101011,
170-
// 0x10
171-
0b1011110111, 0b1011110101, 0b1110101101, 0b1110101111,
172-
0b1101011011, 0b1101101011, 0b1101101101, 0b1101010111,
173-
0b1101111011, 0b1101111101, 0b1110110111, 0b1101010101,
174-
0b1101011101, 0b1110111011, 0b1011111011, 0b1101111111,
175-
// 0x20
176-
0b1, 0b111111111, 0b101011111, 0b111110101,
177-
0b111011011, 0b1011010101, 0b1010111011, 0b101111111,
178-
0b11111011, 0b11110111, 0b101101111, 0b111011111,
179-
0b1110101, 0b110101, 0b1010111, 0b110101111,
180-
// 0x30
181-
0b10110111, 0b10111101, 0b11101101, 0b11111111,
182-
0b101110111, 0b101011011, 0b101101011, 0b110101101,
183-
0b110101011, 0b110110111, 0b11110101, 0b110111101,
184-
0b111101101, 0b1010101, 0b111010111, 0b1010101111,
185-
// 0x40
186-
0b1010111101, 0b1111101, 0b11101011, 0b10101101,
187-
0b10110101, 0b1110111, 0b11011011, 0b11111101,
188-
0b101010101, 0b1111111, 0b111111101, 0b101111101,
189-
0b11010111, 0b10111011, 0b11011101, 0b10101011,
190-
// 0x50
191-
0b11010101, 0b111011101, 0b10101111, 0b1101111,
192-
0b1101101, 0b101010111, 0b110110101, 0b101011101,
193-
0b101110101, 0b101111011, 0b1010101101, 0b111110111,
194-
0b111101111, 0b111111011, 0b1010111111, 0b101101101,
195-
// 0x60
196-
0b1011011111, 0b1011, 0b1011111, 0b101111,
197-
0b101101, 0b11, 0b111101, 0b1011011,
198-
0b101011, 0b1101, 0b111101011, 0b10111111,
199-
0b11011, 0b111011, 0b1111, 0b111,
200-
// 0x70
201-
0b111111, 0b110111111, 0b10101, 0b10111,
202-
0b101, 0b110111, 0b1111011, 0b1101011,
203-
0b11011111, 0b1011101, 0b111010101, 0b1010110111,
204-
0b110111011, 0b1010110101, 0b1011010111, 0b1110110101,
205-
];
206-
207159
#[derive(Clone)]
208160
struct Differential {
209161
acc: bool,

0 commit comments

Comments
 (0)