summaryrefslogtreecommitdiffstats
path: root/prog/baozveza
diff options
context:
space:
mode:
authorAnton Luka Šijanec <anton@sijanec.eu>2024-03-07 17:12:17 +0100
committerAnton Luka Šijanec <anton@sijanec.eu>2024-03-07 17:12:17 +0100
commit2292ad2ec16c22eead9426bf4d70755864b80fb3 (patch)
tree60cf02b5ae9bc52233c79ac4e11d198347458198 /prog/baozveza
parentdn02b.fix (diff)
downloadr-2292ad2ec16c22eead9426bf4d70755864b80fb3.tar
r-2292ad2ec16c22eead9426bf4d70755864b80fb3.tar.gz
r-2292ad2ec16c22eead9426bf4d70755864b80fb3.tar.bz2
r-2292ad2ec16c22eead9426bf4d70755864b80fb3.tar.lz
r-2292ad2ec16c22eead9426bf4d70755864b80fb3.tar.xz
r-2292ad2ec16c22eead9426bf4d70755864b80fb3.tar.zst
r-2292ad2ec16c22eead9426bf4d70755864b80fb3.zip
Diffstat (limited to 'prog/baozveza')
-rwxr-xr-xprog/baozveza/dspbin0 -> 24216 bytes
-rw-r--r--prog/baozveza/dsp.c106
-rwxr-xr-xprog/baozveza/visbin0 -> 40432 bytes
-rw-r--r--prog/baozveza/vis.c165
4 files changed, 271 insertions, 0 deletions
diff --git a/prog/baozveza/dsp b/prog/baozveza/dsp
new file mode 100755
index 0000000..1ecf469
--- /dev/null
+++ b/prog/baozveza/dsp
Binary files differ
diff --git a/prog/baozveza/dsp.c b/prog/baozveza/dsp.c
new file mode 100644
index 0000000..9b406e1
--- /dev/null
+++ b/prog/baozveza/dsp.c
@@ -0,0 +1,106 @@
+#include <math.h>
+#include <complex.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+void fft (double complex * out, const double complex * in, int n, bool inverse, int skip) { // use skip=1 for initial calling. internal parameter for recursion.
+ if (n == 1) {
+ out[0] = in[0];
+ return;
+ }
+ double complex omega = cpow(M_E, -2*M_PI*I/n); // nth root of unity (omega^(n-1)=1)
+ if (inverse)
+ omega = conj(omega);
+ // fprintf(stderr, "omega je %lf+%lfi, n je %d\n", creal(omega), cimag(omega), n);
+ fft(out, in, n/2, inverse, skip*2);
+ fft(out+n/2, in+skip, n/2, inverse, skip*2);
+ for (int i = 0; i < n/2; i++) {
+ double complex sod = out[i];
+ double complex lih = out[n/2+i];
+ out[i] = (sod + cpow(omega, i)*lih)/(skip == 1 && inverse ? n : 1);
+ out[n/2+i] = (sod - cpow(omega, i)*lih)/(skip == 1 && inverse ? n : 1);
+ }
+}
+double complex qam (int stopnja /* koren orderja */ , int simbol) {
+ double x = simbol%stopnja-(stopnja-1.0)/2.0;
+ double y = simbol/stopnja-(stopnja-1.0)/2.0;
+ return y*I+x;
+}
+int qam_symbols (int stopnja) { // how many possible symbols does this qam configuration let you use
+ return stopnja*stopnja;
+}
+int ofdm_columns (int vzorcev, int skip /* 1 za 0 razmika */) {
+ return 1+((vzorcev-1)/skip);
+}
+void ofdm (double complex * out /* space for vzorcev values */, int vzorcev /* must be power of 2 */, int skip, int stopnja, uint64_t simbol) {
+ memset(out, 0, sizeof out[0] * vzorcev);
+ for (int i = 0; i < ofdm_columns(vzorcev, skip); i++) {
+ out[i*skip] = qam(stopnja, simbol % qam_symbols(stopnja));
+ simbol /= qam_symbols(stopnja);
+ }
+} // returns frequency domain, run ifft to get complex time domain, which then has to be moduliran
+void moduliraj (double * out, double complex * in, int insize, int faktor) {
+ for (int i = 0; i < insize*faktor; i++)
+ out[i] = in[i%insize]*sin(M_PI*2*i/(insize*faktor))+in[i%insize]*cos(M_PI*2*i/(insize*faktor));
+}
+#ifdef MODEMTEST
+#include <stdio.h>
+#include <error.h>
+#include <stdlib.h>
+#include <unistd.h>
+int main (int argc, char ** argv) {
+ if (argc != 5)
+ error(1, 0, "%s log_2(vzorcev) ofdm_skip stopnja faktor_modulacije", argv[0]);
+ int vzorcev = 1 << atoi(argv[1]);
+ int skip = atoi(argv[2]);
+ int stopnja = atoi(argv[3]);
+ int faktor = atoi(argv[4]);
+ int simbolov = pow(qam_symbols(stopnja), ofdm_columns(vzorcev, skip));
+ fprintf(stderr, "s temi nastavitvami je stoplcev %d, vsak nosi %d simbolov, skupaj je torej na voljo %d simbolov\n", ofdm_columns(vzorcev, skip), qam_symbols(stopnja), simbolov);
+ while (true)
+ for (int simbol = 0; simbol < simbolov; simbol++) {
+ double complex frequency[vzorcev];
+ double complex time[vzorcev];
+ double modulirano[vzorcev*faktor];
+ ofdm(frequency, vzorcev, skip, stopnja, simbol);
+ fft(time, frequency, vzorcev, true, 1);
+ moduliraj(modulirano, time, vzorcev, faktor);
+ write(STDOUT_FILENO, modulirano, sizeof modulirano);
+ }
+}
+#endif
+#ifdef FFTTEST
+#include <stdio.h>
+int main () {
+ printf("fft test.\n");
+ double complex sinusoid[128];
+ for (int i = 0; i < 128; i++) {
+ sinusoid[i] = cpow(M_E, 2*M_PI*I/8*i);
+ for (int j = 0; j < 16+creal(sinusoid[i])*16; j++) printf("#");
+ printf("\n");
+ }
+ double complex freq[128];
+ printf("fft:\n");
+ fft(freq, sinusoid, 128, false, 1);
+ for (int i = 0; i < 128; i++) {
+ for (int j = 0; j < 16+creal(freq[i]); j++) printf("#");
+ printf("\n");
+ }
+ printf("ifft:\n");
+ fft(sinusoid, freq, 128, true, 1);
+ for (int i = 0; i < 128; i++) {
+ for (int j = 0; j < 16+creal(sinusoid[i])*16; j++) printf("#");
+ printf("\n");
+ }
+ double complex testdata[] = {1, 2, 3, 4};
+ double complex output[4];
+ fft(output, testdata, 4, false, 1);
+ fft(testdata, output, 4, true, 1);
+ printf("fftd:\n");
+ for (int i = 0; i < 4; i++)
+ printf("%lf+%lfi\n", creal(output[i]), cimag(output[i]));
+ printf("ifftd:\n");
+ for (int i = 0; i < 4; i++)
+ printf("%lf+%lfi\n", creal(testdata[i]), cimag(testdata[i]));
+}
+#endif
diff --git a/prog/baozveza/vis b/prog/baozveza/vis
new file mode 100755
index 0000000..9679415
--- /dev/null
+++ b/prog/baozveza/vis
Binary files differ
diff --git a/prog/baozveza/vis.c b/prog/baozveza/vis.c
new file mode 100644
index 0000000..02a4e99
--- /dev/null
+++ b/prog/baozveza/vis.c
@@ -0,0 +1,165 @@
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <X11/Xutil.h>
+#include <assert.h>
+#include <unistd.h>
+#include <poll.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include "dsp.c"
+#include <error.h>
+#include <stdlib.h>
+#include <errno.h>
+enum whattodraw {
+ whattodraw_abs,
+ whattodraw_re,
+ whattodraw_im
+};
+int main (int argc, char ** argv) {
+ if (argc != 3)
+ error(1, 0, "argv[1] must be set. fft length will then be 2**argv[1]\nargv[2] must be set. peak value will then be argv[2] -- use a floating point.");
+ double peak = strtod(argv[2], NULL);
+ Display *dpy = XOpenDisplay(NULL);
+ assert(dpy);
+ int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
+ int width = 200;
+ int height = 400;
+ Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, width, height, 0, blackColor, blackColor);
+ // We want to get MapNotify events
+ XSelectInput(dpy, w, StructureNotifyMask | KeyPressMask | ExposureMask | VisibilityChangeMask);
+ // "Map" the window (that is, make it appear on the screen)
+ XMapWindow(dpy, w);
+ // Create a "Graphics Context"
+ GC gc = XCreateGC(dpy, w, 0, NULL);
+ // Tell the GC we draw using the white color
+ XSetForeground(dpy, gc, 0xff0000);
+ // Wait for the MapNotify event
+ struct pollfd pollfd[2] = {
+ {
+ .fd = XConnectionNumber(dpy),
+ .events = POLLIN | POLLHUP
+ },
+ {
+ .fd = STDIN_FILENO,
+ .events = POLLIN
+ }
+ };
+ int flags = fcntl(XConnectionNumber(dpy), F_GETFL, 0);
+ assert(flags != -1);
+ flags |= O_NONBLOCK;
+ assert(fcntl(XConnectionNumber(dpy), F_SETFL, flags) == 0);
+ bool flush = false;
+ int spectrumheight = 100;
+ void draw_ui () {
+ XSetForeground(dpy, gc, 0xff0000);
+ XDrawLine(dpy, w, gc, 0, spectrumheight+1, width, spectrumheight+1);
+ }
+ int capturesize = 1 << atoi(argv[1]);
+ unsigned received_bytes = 0;
+ double samples[capturesize];
+ enum whattodraw whattodraw = whattodraw_abs;
+ unsigned block = 0;
+ while (XPending(dpy) || poll(pollfd, 2, -1) > 0) {
+ if (pollfd[0].revents & POLLIN || XPending(dpy)) {
+ while (XPending(dpy)) {
+ XEvent e;
+ XNextEvent(dpy, &e);
+ switch (e.type) {
+ case ConfigureNotify:
+ width = e.xconfigure.width;
+ height = e.xconfigure.height;
+ break;
+ case MapNotify:
+ case Expose:
+ case VisibilityChangeMask:
+ draw_ui();
+ flush = true;
+ break;
+ case DestroyNotify:
+ goto end;
+ case KeyPress:
+ switch (XLookupKeysym(&e.xkey, 0)) {
+ case XK_Up:
+ spectrumheight--;
+ break;
+ case XK_Down:
+ spectrumheight++;
+ break;
+ case XK_a:
+ case XK_A:
+ whattodraw = whattodraw_abs;
+ break;
+ case XK_r:
+ case XK_R:
+ whattodraw = whattodraw_re;
+ break;
+ case XK_i:
+ case XK_I:
+ whattodraw = whattodraw_im;
+ break;
+ }
+ draw_ui();
+ flush = true;
+ break;
+ case MappingNotify:
+ XRefreshKeyboardMapping(&e.xmapping);
+ break;
+ }
+ }
+ }
+ if (pollfd[1].revents & POLLIN) {
+ int rr = read(STDIN_FILENO, ((void *) samples)+received_bytes, sizeof samples-received_bytes);
+ if (rr == 0) { // EOF
+ pollfd[1].events = 0;
+ continue;
+ }
+ if (rr < 0)
+ error(1, errno, "stdin read");
+ received_bytes += rr;
+ if (received_bytes == capturesize*sizeof(samples[0])) {
+ double complex complex_samples[capturesize];
+ for (int i = 0; i < capturesize; i++)
+ complex_samples[i] = samples[i];
+ double complex spectrum[capturesize];
+ fft(spectrum, complex_samples, capturesize, false, 1);
+ XSetForeground(dpy, gc, blackColor);
+ XFillRectangle(dpy, w, gc, 0, 0, width, spectrumheight+1);
+ XSetForeground(dpy, gc, 0x00ff00);
+ for (int i = 0; i < capturesize; i++) {
+ double frequency;
+ switch (whattodraw) {
+ case whattodraw_abs:
+ frequency = cabs(spectrum[i]);
+ break;
+ case whattodraw_re:
+ frequency = creal(spectrum[i]);
+ break;
+ case whattodraw_im:
+ frequency = cimag(spectrum[i]);
+ break;
+ }
+ if (frequency > peak)
+ frequency = peak;
+ XSetForeground(dpy, gc, 0x00ff00);
+ XDrawLine(dpy, w, gc, i, spectrumheight, i, spectrumheight-(frequency/peak)*spectrumheight);
+ XSetForeground(dpy, gc, (frequency/peak)*0x00ff00+(frequency/peak)*0x0000ff);
+ XDrawPoint(dpy, w, gc, i, spectrumheight+2+block%(height-spectrumheight-2));
+ }
+ int scanner = spectrumheight+2+block%(height-spectrumheight-2);
+ XSetForeground(dpy, gc, 0xabcdef);
+ XFillRectangle(dpy, w, gc, 0, scanner+1, capturesize, 3);
+ flush = true;
+ received_bytes = 0;
+ block++;
+ }
+ }
+ if (flush) {
+ XFlush(dpy);
+ flush = false;
+ }
+ }
+ end:
+ XCloseDisplay(dpy);
+}
+