AI prompts
base on Amateur radio packet experimentation framework # AMPKT - Amateur radio packet explorer
This is a project to facilitate experimentation with connecting two Linux
machine's network stacks via the amateur radio bands.
## Required Hardware
You will need two full-duplex SDRs, one for each machine. They will also need to
be compatible with SoapySDR.
Hardware that is known to work:
- USRP N210
- BladeRF
- LimeSDR
## Getting Started
1. Build the project:
```console
cargo build --release
```
2. Connect your SDR hardware and start the `ampkt` binary (note that you will
probably need to run with `sudo` so that the `tap` interface can be
created):
```console
sudo ./target/release/ampkt "driver=bladerf" 433000000 435000000
```
This will start ampkt using bladerf hardware, Txing on 433MHz and Rxing on
435MHz.
3. On a second machine do the same, ensuring that you swap the frequencies.
4. On both machines, bring up the tap interface and assign an IP address:
```console
sudo ifconfig tap0 up
sudo ip add 10.0.0.1/24 dev tap0
```
Making sure you use a different IP address on the other machine.
5. At this point you should have working comms. You can check running `ping`and
seeing whether you get a reply from the other machine
```console
ping 10.0.0.2
```
## Technical Information
A Linux [TAP](https://www.kernel.org/doc/html/v5.8/networking/tuntap.html)
interface is created. This interface is used as the sink for the RX path and the
source for the TX path.
### Tx Path
Each incoming packet that is read from the tap interface is converted into a
frame. The frame consists of a sync header (repeated twice) a frame size (as
u16) followed by the packet data. We then convert the frame to a stream of
symbols. We use QPSK modulation which means we have two bits per symbol. Each
2-bit nibble is converted into a symbol using the following map:
```
A => 0b00
B => 0b01
C => 0b10
D => 0b11
```
We then module the symbol stream into QPSK with the following constellation:
```
Im
|
B | A
|
|
-------------> re
|
|
D | C
|
```
The output of the QPSK modulator is then sent to the SDR for Tx.
### Rx Path
Samples from the SDR are first sent into the clock sync block. This block
decimates the incoming stream by selection of particular samples from the input
stream. The number of samples that are 'skipped' during selection is shifted by
an error function which attempts to pick the sample at the peak of a symbol.
The decimated stream is then sent into the carrier sync block. This attempts to
compensate for any difference in clocks between the SDRs by 'de-reotating' the
constellation. When this block has 'locked' the output should be stable samples
in each quadrent of the constellation plot.
Next, the samples passed through the QPSK demodulator which converts the samples
into a stream of symbols.
The symbol stream is then passed through a frame decoder. This block attempts to
create the original packet of data from a stream of symbols. We use a SYNC
header of 16-bytes (repeated twice) to resolve the phase ambiguity. Then the
computed difference in phase is applied to all incoming symbols to decode the
frame.
Finally the frames are written to the TAP interface for injection into the Linux
kernel network stack.
", Assign "at most 3 tags" to the expected json: {"id":"2218","tags":[]} "only from the tags list I provide: [{"id":77,"name":"3d"},{"id":89,"name":"agent"},{"id":17,"name":"ai"},{"id":54,"name":"algorithm"},{"id":24,"name":"api"},{"id":44,"name":"authentication"},{"id":3,"name":"aws"},{"id":27,"name":"backend"},{"id":60,"name":"benchmark"},{"id":72,"name":"best-practices"},{"id":39,"name":"bitcoin"},{"id":37,"name":"blockchain"},{"id":1,"name":"blog"},{"id":45,"name":"bundler"},{"id":58,"name":"cache"},{"id":21,"name":"chat"},{"id":49,"name":"cicd"},{"id":4,"name":"cli"},{"id":64,"name":"cloud-native"},{"id":48,"name":"cms"},{"id":61,"name":"compiler"},{"id":68,"name":"containerization"},{"id":92,"name":"crm"},{"id":34,"name":"data"},{"id":47,"name":"database"},{"id":8,"name":"declarative-gui "},{"id":9,"name":"deploy-tool"},{"id":53,"name":"desktop-app"},{"id":6,"name":"dev-exp-lib"},{"id":59,"name":"dev-tool"},{"id":13,"name":"ecommerce"},{"id":26,"name":"editor"},{"id":66,"name":"emulator"},{"id":62,"name":"filesystem"},{"id":80,"name":"finance"},{"id":15,"name":"firmware"},{"id":73,"name":"for-fun"},{"id":2,"name":"framework"},{"id":11,"name":"frontend"},{"id":22,"name":"game"},{"id":81,"name":"game-engine "},{"id":23,"name":"graphql"},{"id":84,"name":"gui"},{"id":91,"name":"http"},{"id":5,"name":"http-client"},{"id":51,"name":"iac"},{"id":30,"name":"ide"},{"id":78,"name":"iot"},{"id":40,"name":"json"},{"id":83,"name":"julian"},{"id":38,"name":"k8s"},{"id":31,"name":"language"},{"id":10,"name":"learning-resource"},{"id":33,"name":"lib"},{"id":41,"name":"linter"},{"id":28,"name":"lms"},{"id":16,"name":"logging"},{"id":76,"name":"low-code"},{"id":90,"name":"message-queue"},{"id":42,"name":"mobile-app"},{"id":18,"name":"monitoring"},{"id":36,"name":"networking"},{"id":7,"name":"node-version"},{"id":55,"name":"nosql"},{"id":57,"name":"observability"},{"id":46,"name":"orm"},{"id":52,"name":"os"},{"id":14,"name":"parser"},{"id":74,"name":"react"},{"id":82,"name":"real-time"},{"id":56,"name":"robot"},{"id":65,"name":"runtime"},{"id":32,"name":"sdk"},{"id":71,"name":"search"},{"id":63,"name":"secrets"},{"id":25,"name":"security"},{"id":85,"name":"server"},{"id":86,"name":"serverless"},{"id":70,"name":"storage"},{"id":75,"name":"system-design"},{"id":79,"name":"terminal"},{"id":29,"name":"testing"},{"id":12,"name":"ui"},{"id":50,"name":"ux"},{"id":88,"name":"video"},{"id":20,"name":"web-app"},{"id":35,"name":"web-server"},{"id":43,"name":"webassembly"},{"id":69,"name":"workflow"},{"id":87,"name":"yaml"}]" returns me the "expected json"