In each project, we will explain our project part by part. Each part includes a brief explanation and the test method. At the end of each project, we will have an acknowledgement. You can build the code documentation by the following command:
cargo doc --open
[TOC]
We have mainly four components:
- Block buffer: The queue-like structure for stream data. Both original version and concurrent version are defined in block_buffer.rs.
- Sample I/O Stream: The structures operate on sample streams. Sample streams are divided into instream and outstream. Instreams read samples from physics world and store the data in its buffer. Ostreams fetch samples to its buffer and write them to the physics world. The sample streams are in samples_stream.rs.
- Physics packet sender/receiver: Structures send or receive packet. Sender owns an sample instream and receiver owns an sample outstream. They are responsible for packet detection, modulation and demodulation. The sender and receiver are in phy_packet.rs
- Physics layer: The assembled physics layer. Provide basic data transmission over acoustic link. There three types of links: PSK, OFDM and PSK with error correction. The physics layers are in phy_layer.rs.
The whole project structure lies below:
In this part, we implement
buffer
andconcurrent_buffer
: Basic block data structure. (buffer.rs, concurrent_buffer.rs)cpal_stream
: Audio I/O stream. (cpal_stream.rs)hound_stream
: wav file I/O stream. (hound_stream.rs)
We use cpal_stream
to realize audio recording and playing. We use hound_stream
to read audio files.
You can test part1 ck1 by the following command.
cargo test part1_ck1 --release -- --ignored
The program will start recording immediately for 10s.
You can test part1 ck2 by
cargo test part1_ck2 --release -- --ignored
The program will play a 10-second music clip while recording at the same time. After 10 seconds, it will replay the recorded sound.
We use previously defined structure: cpal_stream
to write part2.
You can test part2 ck1 by
cargo test part2_ck1 --release -- --ignored
The program will play the signal
In this part, we implement
- PSK modulation:
PSK
is an implementor ofModem
which supoortmodulate
anddemodulate
.(psk.rs) - Correlation frame detection:
CorrelationFraming
is an implementor ofFrameDetector
which supporton_sample
.(frame_detect.rs) - Chirp signal as preamble:
ChirpUpDown
is an implementor ofPreambleGen
, which supportgenerate
,len
,norm
and other helper functions.(preambles.rs) - Packet sender and receiver:
PhySender
is an implementor ofPacketSender
, which supportsend
function.PhyReceiver
is an implementor ofPacketReceiver
, which supporrecv
andrecv_timeout
functions.(txrx.rs).
Note: This test need two nodes to test. This test should be done in a quite room.
To test part 3, you can run the following POSIX shell command on two devices,
where $seed
is a integer for pseudo-random generator seed.
# on sender device
./input_gen.py $seed > INPUT.txt
cargo test part3_ck1_send --release -- --ignored
# on receiver device
cargo test part3_ck1_recv --release -- --ignored
./input_gen.py $seed > INPUT.txt
./cmp.py
Less than 15 seconds transmission time is expected.
Less than 100 bit filps is expected.
In this part, we implemented file transmission with error correction.
- In
phy_layer
module, we addedAtomicPHY
which use sequence number and CRC checksum to ensure the data integrity of received data packets and infer the number of lost packets between two successful transmitted packets. - In
tests/part4.rs
,- sender:
The data file is chunked into fixed size shards
and extra 30 chunks are generated with Reed-Solomon encoder.
The chunks are then sent via
AtomicPHY
. - receiver:
Receiver data shards and error correction chunks via
AtomicPHY
. Erase the lost shards and corrupted shards. Recover the data file with Reed-Solomon decode.
- sender:
The data file is chunked into fixed size shards
and extra 30 chunks are generated with Reed-Solomon encoder.
The chunks are then sent via
To test part 4, you can run the following POSIX shell command on two devices,
where $seed
is a integer for pseudo-random generator seed.
# on sender device
./input_gen.py $seed > INPUT.txt
cargo test part4_send --release --features nofloat -- --ignored
# on receiver device
cargo test part4_recv --release --features nofloat -- --ignored
./input_gen.py $seed > INPUT.txt
./cmp.py
Less than 20 seconds transmission time is expected.
The comparison result should be empty which indicates that the OUTPUT.txt
is identical to INPUT.txt
.
In this part, we implemented OFDM+BPSK modulation which should at least double the bandwidth.
- In
modem
module, we implemented OFDM+BPSK modem inofdm
sub-module. - In
phy_layer
module, we implementedHighBpsPHY
which use the OFDM modem to achieve higher bit rate in file transmission task.
To test part 5, you can run the following POSIX shell command on two devices,
where $seed
is a integer for pseudo-random generator seed.
# on sender device
./input_gen.py $seed > INPUT.txt
cargo test part5_send --release --features nofloat -- --ignored
# on receiver device
cargo test part5_recv --release --features nofloat -- --ignored
./input_gen.py $seed > INPUT.txt
./cmp.py
Less than 9 seconds transmission time is expected.
We should see less than 100 bit flips in the comparison result.
In this part, we use fixed-point numbers instead of floating point nubers in preamble generation/detection and modulation/demodulation.
Thanks to the trait oriented feature provided by rust programming language, we are able to complete this part by only adding a few lines of code.
- In
traits/sample.rs
, thetrait Sample
is an abstraction of the common operations required to support acoustic link on floating point numbers and fixed point number. - Fixed point number special function evaluation are done by CORDIC algorithm, which involves only integer arithmetics.
- For
modem
,preamble
andframe_detect
module, we can use eitherfp32
orfixed::types::I32F32
, which is controlled by the compilation flagnofloat
. - NOTE our OFDM modem currently only works with floating point numbers, so it is excluded when the flag
nofloat
is presented.
You can test part 6 by running the following POSIX shell command on two devices,
where $seed
is an integer used as pseudo-random number generator seed.
# on sender device
./input_gen.py $seed > INPUT.txt
cargo test part3_ck1_send --release --features nofloat -- --ignored
# on receiver device
cargo test part3_ck1_recv --release --features nofloat -- --ignored
./input_gen.py $seed > INPUT.txt
./cmp.py
The sender should finish transmission within 15 seconds.
The receiver should receive and write the file OUTPUT.txt
without error.
Less than 100 bit flips is expected in the result of comparison.
We didn't build everything from ground up, instead, we leverage the existing vast rust eco-system.
As designing and analysing the whole system is quite beyond our capability, we referred to some journal papers, academic reports and blog posts.
Here, we express our sincere gratefulness to the authors of the following libraries/papers
- crates.io cpal: for audio input/output.
- crates.io hound: for WAV audio file format encode/decode.
- crates.io crc: for various CRC checksum/digest algorithm.
- crates.io reed-solomon-erasure: for high-performance reed solomon erasure code encode/decode.
- crates.io rustfft: for heavily optimized radix-4 FFT/IFFT.
- crates.io fixed, crates.io cordic, crates.io az: for fixed point number arithmetic operation and elementary function evaluation using only integer arithmetic.
- IEEE SIGCOMM 2013. Dhwani: secure peer-to-peer acoustic NFC: The paper gives a brief analysis of the transmission media (the air, within 0.5 meter). They also measures the basic property of the commodity audio I/O devices (the microphone and the speaker on middle-end laptop/cellphone). We have borrowed the frame preamble from Dhwani, which is a linear up-down chirp signal. It shows great synchronization accuracy and anti-noise ability.
- openofdm: an hardware implementation of 802.11 OFDM decoder: We have implemented a phase shifting correction similar to the one in OpenOFDM. Our preamble detection algorithm is also inspired by OpenOFDM.
- See
proj1_acoustic_link
crate for PHY layer optimization for wired-connection - See
proj2_multiple_access
crate for MAC implementation
- In
proj1_acoustic_link::phy_packet::modem
, addedline_code::LineCode
for 4b5b+nrzi encoding. We try to utilize digital baseband transmission for wired-connection which have better throughput. - In
proj1_acoustic_link::phy_packet::frame_detect
andproj1_acoustic_link::phy_packet::preamble
, use shorter preamble for each frame to achieve higher efficiency. - In
proj2_multiple_access/bin/part1_send.rs
andproj2_multiple_access/bin/part1_recv.rs
, we send/receive the file directly using PHY layer service.
git checkout proj2-part1
cd proj2_multiple_access
# sender
cargo run --release --bin part1_send
# receiver
cargo run --release --bin part1_recv
# checking correctness
./cmp INPUT.bin OUTPUT.bin
The transmission should finish in about 6 seconds after tx/rx started.
There should be no more than 100 bit filps.
- In
proj2_multiple_access/bin/part2_send.rs
andproj2_multiple_access/bin/part2_recv.rs
, we introduce ACK mechanism, that is:- Tx sends every data chunk and its sequence number to Rx
- Rx reply ACK with the sequence number if a data chunk can be correctly decoded.
- Tx wait for
ACK_TIMEOUT
time and try to receive ACK packets from Rx. - Tx tries to re-send the data chunks whose ACK never come after
ACK_TIMEOUT
time. - Repeat the above steps until Tx/Rx find out that all the data chunks are correctly delivered.
git checkout proj2-part1
cd proj2_multiple_access
# sender
cargo run --release --bin part2_send
# receiver
cargo run --release --bin part2_recv
# checking correctness
./cmp INPUT.bin OUTPUT.bin
- The transmission should finish in about 9 seconds after tx/rx started.
- There should be no bit filps.
- If we unplug the wire during transmission, sender should detect and report
link error
after 20 seconds.
Not done yet.
Failed to meet the performance requirements
Failed to meet the performance requirements
Not done yet.
Not done yet.
- WARP project for CSMA MAC reference design