diff options
author | Anton Luka Šijanec <anton@sijanec.eu> | 2024-03-07 17:12:17 +0100 |
---|---|---|
committer | Anton Luka Šijanec <anton@sijanec.eu> | 2024-03-07 17:12:17 +0100 |
commit | 2292ad2ec16c22eead9426bf4d70755864b80fb3 (patch) | |
tree | 60cf02b5ae9bc52233c79ac4e11d198347458198 /prog/baozveza | |
parent | dn02b.fix (diff) | |
download | r-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-x | prog/baozveza/dsp | bin | 0 -> 24216 bytes | |||
-rw-r--r-- | prog/baozveza/dsp.c | 106 | ||||
-rwxr-xr-x | prog/baozveza/vis | bin | 0 -> 40432 bytes | |||
-rw-r--r-- | prog/baozveza/vis.c | 165 |
4 files changed, 271 insertions, 0 deletions
diff --git a/prog/baozveza/dsp b/prog/baozveza/dsp Binary files differnew file mode 100755 index 0000000..1ecf469 --- /dev/null +++ b/prog/baozveza/dsp 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 Binary files differnew file mode 100755 index 0000000..9679415 --- /dev/null +++ b/prog/baozveza/vis 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); +} + |