Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
8ab81f5
ukrainian translation (#127)
mrbloom Jan 7, 2026
f03487e
ukrainian translation (#126)
mrbloom Jan 7, 2026
dc05a39
ukrainian translation (#125)
mrbloom Jan 7, 2026
e1848a7
uk translation (#124)
mrbloom Jan 7, 2026
1a1fa69
cyclostationary ukrainian translation till FAM (#128)
mrbloom Jan 12, 2026
cfa8258
[Cyclostationary] explain minimum number of samples for FSM (#130)
777arc Jan 26, 2026
6d444e4
Updated root README
777arc Feb 3, 2026
2e838df
Detection chapter first draft (#132)
777arc Feb 4, 2026
897eb23
remove commented out code
777arc Feb 7, 2026
3ecd881
Vishwaksen additions (#135)
777arc Feb 9, 2026
5e6d9ed
Fix spectrogram time direction
777arc Feb 24, 2026
38b6ab4
formatOnSave=false
777arc Feb 25, 2026
60642ec
Random variables section (#137)
777arc Feb 25, 2026
6ecd108
Add external resources section to cyclostationary.rst
777arc Feb 26, 2026
b81e32d
French translation fix typos (#138)
aitzkora Feb 26, 2026
297af66
Add 'Napolitano' to spelling word list
777arc Feb 26, 2026
f4d348c
French translation new fix typos (#139)
aitzkora Feb 28, 2026
b73910c
svgs
777arc Mar 2, 2026
2d2b506
Add support options to README
777arc Mar 2, 2026
1973ece
spacing
777arc Mar 2, 2026
f35f890
[Chinese Translation] Update (#140)
doctormin Mar 16, 2026
592a35f
added full example to sync chapter
777arc Mar 16, 2026
4efd580
Chinese additions (#142)
doctormin Mar 17, 2026
b65d8d1
Added section using GPS as an example (#144)
777arc Mar 21, 2026
6cee67a
Fix mermaid diagram and do a grammar editing pass (#145)
777arc Mar 24, 2026
7de33bd
tweak RDS PSD script
777arc Mar 26, 2026
bd9ad3e
Adding French version of doa.rst and pysdr.rst (#146)
melmoth16 Mar 27, 2026
45c9bf2
update index-fr
777arc Mar 27, 2026
9443c54
Fix variable reference in power_mvdr function (#147)
jgroen Apr 9, 2026
24a162d
Creation of hackrf.rst in content-fr + finishing the doa.rst in conte…
melmoth16 Apr 15, 2026
d9a2261
Adding 2 new files in French : bladerf.rst and rtlsdr.rst also modify…
melmoth16 Apr 15, 2026
4350223
Add Dan to supporters
777arc Apr 20, 2026
37be401
remove extra conversion to dB and adjust results to retain top 95% va…
jgroen Apr 20, 2026
7146f19
clean up the 2D DOA code that crops
777arc Apr 20, 2026
67fe601
ln -s AGENTS.md CLAUDE.md
777arc Apr 20, 2026
39ba22c
remove old script
777arc Apr 21, 2026
f995a5e
Variable notation 'w' was used for the same as 'ω' in frequency_domai…
mchro May 20, 2026
56c3aef
Dutch translation updates (#154)
versd May 22, 2026
172a478
bump python version used in action to 3.12 and fix requirements file
777arc Jun 5, 2026
e99f95e
Added more pros and cons of analog vs digital vs hybrid arrays
777arc Jun 5, 2026
d5d37ae
beefed up the fractional delay filter subsection
777arc Jun 5, 2026
3b5f95e
add jons ladder pic
777arc Jun 5, 2026
4df3263
add root music section to DOA chapter
777arc Jun 5, 2026
87b66f3
emphasize np.roots
777arc Jun 5, 2026
943a168
spelling list
777arc Jun 5, 2026
96385f4
add venv to exclude_patterns and remove the old unused spelling list
777arc Jun 5, 2026
df26ff7
Added section on OQPSK, MSK, CPFSK (#156)
777arc Jun 6, 2026
d59639e
added qpsk msk spectrum comparison
777arc Jun 7, 2026
dc520fd
batch of grammar and other minor fixes across all chapters
777arc Jun 7, 2026
a519d7a
spelling
777arc Jun 7, 2026
54edb64
Add the Potik tone + noise demo to home page
777arc Jun 8, 2026
45ce481
updated doa and pulse shaping with latest material (#157)
versd Jun 8, 2026
a445e38
Update homepage.html with the new version of potik embed for cw-plus-…
potik-admin Jun 9, 2026
013e044
add pulse shaping potik demo
777arc Jun 21, 2026
5f11380
Added analog FPV video chapter (#160)
777arc Jun 22, 2026
a8a7f62
remove comment about 5 MHz intervals for fpv
777arc Jun 22, 2026
0834075
First cut of TDOA chapter (#161)
777arc Jun 25, 2026
99e8e75
Note about CAF
777arc Jun 26, 2026
9ea38fb
Added section about rake receivers to detection chapter
777arc Jun 27, 2026
7a1682e
Added boxcar pulse section to freq domain chapter
777arc Jul 2, 2026
922cbe7
added a section about overlap-save and overlap-add to filters chapter
777arc Jul 2, 2026
0525ced
tikz fix and spelling
777arc Jul 2, 2026
0aa9b4d
try deploy-pages@v5.0.0
777arc Jul 2, 2026
e24db01
Update frequency_domain.rst (#162)
Sheepwalrus Jul 6, 2026
c5bb330
why python
777arc Jul 8, 2026
d43a908
spelling
777arc Jul 8, 2026
7a46022
update email
777arc Jul 9, 2026
67842d7
categorize specific SDR chapters into a collapsible, expanded by defa…
777arc Jul 9, 2026
5364191
Try deploying jupyterlite
777arc Jul 9, 2026
bff838b
spelling
777arc Jul 9, 2026
29e6aea
try adding branding to jupyterlite
777arc Jul 9, 2026
a300a2c
RDS jupyterlite
777arc Jul 9, 2026
a52cdba
frequency domain ipynb
777arc Jul 9, 2026
8e84d01
sync ipynb
777arc Jul 9, 2026
d4c5f85
SEO tweaks
777arc Jul 10, 2026
f9ff1e5
Eye diagram interactive app (#163)
777arc Jul 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions .github/workflows/build-and-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ jobs:
uses: actions/checkout@v4.1.7

- name: apt installs
run: sudo apt update && sudo apt install -y texlive-latex-extra texlive-lang-cyrillic ghostscript
run: sudo apt update && sudo apt install -y texlive-latex-extra texlive-lang-cyrillic ghostscript libenchant-2-dev

- uses: actions/setup-python@v5.1.0
- uses: actions/setup-python@v6.2.0
with:
python-version: '3.10'
python-version: '3.12'

- name: pip installs
run: pip install -r requirements.txt
Expand Down Expand Up @@ -97,14 +97,24 @@ jobs:
env:
CREATOR_ID: ${{ secrets.CREATOR_ID }}

# Build a self-hosted JupyterLite environment into _build/jupyterlite so the
# interactive "run this code" links in the book point at our own deployment
# rather than a third-party demo site. Done last so its pip installs can't
# disturb the Sphinx builds above.
- name: Build JupyterLite
run: |
pip install -r requirements-jupyterlite.txt
jupyter lite build --contents jupyterlite --output-dir _build/jupyterlite
python jupyterlite/inject_branding.py _build/jupyterlite

- name: Upload artifact
uses: actions/upload-pages-artifact@v3.0.1
with:
path: './_build'

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4.0.5
uses: actions/deploy-pages@v5.0.0

- name: Get current date
id: date
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/build-and-spell-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ jobs:
uses: actions/checkout@v4.1.7

- name: apt installs
run: sudo apt update && sudo apt install -y texlive-latex-extra texlive-lang-cyrillic ghostscript
run: sudo apt update && sudo apt install -y texlive-latex-extra texlive-lang-cyrillic ghostscript libenchant-2-dev

- uses: actions/setup-python@v5.1.0
- uses: actions/setup-python@v6.2.0
with:
python-version: '3.10'
python-version: '3.12'

- name: pip installs
run: pip install -r requirements.txt
Expand Down
77 changes: 3 additions & 74 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,80 +1,9 @@
{
"esbonio.sphinx.confDir": "",
"cSpell.words": [
"arange",
"argmax",
"argsort",
"asarray",
"asmatrix",
"astype",
"AWGN",
"baseband",
"beamformer",
"beamformers",
"beamforming",
"boresight",
"bpsk",
"bytearray",
"CDMA",
"checkword",
"convolutional",
"Costas",
"datacast",
"dataword",
"demod",
"downconversion",
"dtype",
"endfire",
"Ettus",
"figsize",
"fillmein",
"firwin",
"fontsize",
"fromfile",
"Gbps",
"imag",
"lastseen",
"leftrightarrow",
"lfilter",
"linalg",
"linspace",
"mathrm",
"matplotlib",
"Mbps",
"mlen",
"multipath",
"MVDR",
"numpy",
"numtaps",
"Nyquist",
"OFDM",
"pinv",
"plen",
"postcostas",
"presync",
"pyplot",
"QPSK",
"radiotext",
"randint",
"randn",
"rgrids",
"Rinv",
"rlabel",
"savefig",
"scipy",
"thetamax",
"thetamin",
"Uplif",
"USRP",
"webp",
"wirelessly",
"xdata",
"xlabel",
"ydata",
"ylabel"
],
"githubPullRequests.ignoredPullRequestBranches": [
"master"
],
"python.analysis.typeCheckingMode": "basic"
"python.analysis.typeCheckingMode": "basic",
"editor.formatOnSave": false,
"editor.wordWrap": "on"
}
66 changes: 66 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Repository Guidance for AI Contributors

This repo is the source for the PySDR textbook, created using Sphinx.

## Human Notes

This section is for human reference only. It is not an instruction for agents and should not change behavior.

Marc uses AI to help create the JavaScript mini-apps and solve issues like when certain things are not rendered correctly, he doesn't use it to write the actual content, other than spelling/grammar edits and scanning for bugs/incorrectness.

## What to edit

- Edit the `.rst` files under `content/` and the Sphinx config/templates under the repo root.
- Treat `_build/` as generated output. Do not edit it directly.
- Images (primarily in SVG format) referenced by the RST live in _images/
- Python code used to produce images (primarily in SVG format) lives in figure-generating-scripts/
- If you change a page, also check whether image assets, scripts, or config in `_static/`, `_images/`, `conf.py`, or `Makefile` need matching updates.

## How to build locally

If the prompt does not ask to build it, then don't build it.

- Activate the project virtual environment which should be in the root of this repo under .venv

- Build the site using:

```bash
make fast-html
```

- The rendered HTML site will be in `_build/`.
- Open `_build/index.html` for the main site, or the relevant page under `_build/content/`.

## Practical workflow

- Make the source change.
- Run `make fast-html`.
- Inspect the generated HTML in `_build/` to verify the result.
- Keep changes minimal and aligned with the existing textbook style.

## Writing Style

Note to humans- This guidance is provided to AI to help edit, not actually write material, Marc's writes everything himself then uses AI for catching grammar issues and such.

PySDR's prose is intentionally instructional, conversational, and example-driven. When editing chapter text, match these patterns:

- Start with intuition before formalism. Explain the idea in plain language first, then introduce equations or code.
- Prefer short, direct paragraphs. Long sections are acceptable, but they should be broken up with transitions, examples, or figures.
- Use first-person plural sparingly but naturally (`we`, `let's`) to guide the reader through the material.
- Keep the tone approachable and lightly informal, but not casual or chatty.
- Use rhetorical questions and plain-English restatements when they help clarify a concept.
- Explain why a step matters, not just what the step is.
- Preserve the textbook’s teaching rhythm: concept, example, code, result, takeaway.
- Keep technical terminology precise, but avoid sounding overly academic or formal.
- When a section already has figures or code, make the surrounding prose point the reader to them and explain what they should notice.
- Avoid hype, filler, and motivational fluff.
- Lead with a concrete scenario before any equation. Pose a small "what if" with real numbers (e.g. "the emitter is 100 m closer to one sensor"), then generalize. Introduce the named concept (hyperbola, foci) in plain words before showing the formula.
- Read the equation back in plain English. Right after a .. math:: block, add a sentence translating it ("which reads: distance to one sensor minus distance to the other equals...").
- Explain why, not just what. For each fact, give the intuition behind it (why a range difference can't exceed the baseline) rather than stating it as a rule.
- Define jargon inline the moment it appears ("the baseline," "ill-conditioned, meaning small errors move the estimate a lot") instead of assuming the reader knows it.
- Use second person and rhetorical questions to walk the reader through the reasoning as if thinking aloud.

## Notes

- This project uses Sphinx and a custom `conf.py`.
- The repository already contains scripts and generated assets for many figures, so prefer reusing existing conventions instead of introducing new build patterns.
1 change: 1 addition & 0 deletions CLAUDE.md
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ endif
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
EXTENSIONS = -D extensions=sphinx.ext.mathjax,sphinx.ext.autosectionlabel,sphinxcontrib.tikz -D tikz_includegraphics_path=_images -D tikz_tikzlibraries=positioning,shapes,arrows,snakes
EXTENSIONS = -D extensions=sphinx.ext.mathjax,sphinx.ext.autosectionlabel,sphinxcontrib.tikz,sphinxcontrib.mermaid -D tikz_includegraphics_path=_images -D tikz_tikzlibraries=positioning,shapes,arrows,snakes
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .

Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# PySDR Textbook Source Material

This repo contains the source content used to generate the textbook [PySDR: A Guide to SDR and DSP using Python](https://pysdr.org) hosted at https://pysdr.org.

Feel free to submit an issue, or even a Pull Request (PR) with fixes or improvements. Those who submit valuable feedback/fixes be permanently added to the acknowledgments section. Not good at Git but have changes to suggest? Feel free to email Marc at marc@pysdr.org.
# PySDR

<p align="center">
<img width="200" src="https://raw.githubusercontent.com/777arc/PySDR/master/_images/fft_logo_wide.gif" />
</p>

[PySDR: A Guide to SDR and DSP using Python](https://pysdr.org) is a guide to software-defined radio (SDR) and RF signal processing using Python code examples, live at https://pysdr.org. It is a free online textbook that provides a gentle introduction to wireless communications and SDR using an abundance of diagrams, animations, and code examples. From FFTs to filters to digital modulation to receiving and transmitting from SDRs in Python, PySDR has you covered! This repo specifically contains the source content used to generate the textbook, including the body text and Python scripts to generate the figures. For questions/comments/suggestions feel free to submit an issue at the top of this page, or if you want to propose a change to the textbook (e.g. fix or improvement), you can use a Pull Request. Those who submit valuable feedback/fixes be permanently added to the acknowledgments section. Not good at Git but have changes to suggest? Feel free to email Marc at marc@pysdr.org.

You can also support PySDR through the [PySDR Patreon page](https://www.patreon.com/c/PySDR) or a [one-time donation](https://www.paypal.com/donate/?hosted_button_id=FH3LQCJRUVPWL).

## Building

Note that the website is now automatically built and deployed with each push/merge into master branch, using the GitHub action [build-and-deploy.yml](https://github.com/777arc/PySDR/blob/master/.github/workflows/build-and-deploy.yml) and the GitHub pages system for hosting the actual textbook.
Expand Down
2,496 changes: 1,158 additions & 1,338 deletions _images/2d_array_2d_doa_plot.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified _images/2d_array_3d_doa_plot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added _images/2d_array_ladder_pic.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading