summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--fourier.c99
-rwxr-xr-xfrekvence.php76
-rw-r--r--makefile10
4 files changed, 186 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index 366cd1f..cd15f56 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,6 @@ core
.gdb_history
ptt
sio_record.c
+frekvence.h
+fourier
+naprave
diff --git a/fourier.c b/fourier.c
new file mode 100644
index 0000000..def5c13
--- /dev/null
+++ b/fourier.c
@@ -0,0 +1,99 @@
+#include <complex.h>
+#include <math.h>
+#include <sys/param.h> // MIN/MAX
+#include <stdio.h> // debug only
+#include "frekvence.h"
+#define SAMPLES 256
+#define FREKVENC (sizeof frekvence/sizeof frekvence[0])
+struct fourier {
+ void (* callback)(struct fourier *);
+ enum ton trenutni;
+ enum ton zadnji_klican;
+ unsigned count;
+ double samples[SAMPLES];
+ unsigned sample;
+ complex sums[FREKVENC];
+ double rate;
+ unsigned minimal_duration;
+#ifdef USERDATA
+ USERDATA
+#else
+ void * userdata;
+#endif
+};
+void add_sample (struct fourier * f, double received) {
+ for (unsigned frekvenca = 0; frekvenca < FREKVENC; frekvenca++) {
+ f->sums[frekvenca] += received*cpow(M_E, -2*M_PI*I*frekvence[frekvenca]*f->sample/f->rate);
+ f->sums[frekvenca] -= f->samples[f->sample % SAMPLES]*cpow(M_E, -2*M_PI*I*frekvence[frekvenca]*(f->sample-SAMPLES)/f->rate);
+ }
+ int najv[3] = { 0 };
+ double val[3] = { 0 };
+ for (unsigned i = 0; i < FREKVENC; i++)
+ for (int j = 0; j < 3; j++) {
+ double iabs = cabs(f->sums[i]);
+ if (iabs > val[j]) {
+ for (int k = 2; k > j; k--) {
+ najv[k] = najv[k-1];
+ val[k] = val[k-1];
+ }
+ najv[j] = i;
+ val[j] = iabs;
+ break;
+ }
+ }
+ enum ton trenutni = ni;
+ if (val[1] > val[0]/3 && val[2] < val[1]/3) {
+ int večja = MAX(frekvence[najv[0]], frekvence[najv[1]]);
+ int manjša = MIN(frekvence[najv[0]], frekvence[najv[1]]);
+ enum ton znaki[4][4] =
+ {{dtmf_1, dtmf_2, dtmf_3, dtmf_a},
+ {dtmf_4, dtmf_5, dtmf_6, dtmf_b},
+ {dtmf_7, dtmf_8, dtmf_9, dtmf_c},
+ {dtmf_zvezdica, dtmf_0, dtmf_lojtra, dtmf_d}};
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+ int getidx (int freq) {
+ for (int i = 0; i < 8; i++)
+ if (freq == frekvence[i])
+ return i%4;
+ return -1;
+ }
+#pragma GCC diagnostic pop
+ if (getidx(manjša) == -1 || getidx(večja) == -1)
+ trenutni = ni;
+ else
+ trenutni = znaki[getidx(manjša)][getidx(večja)];
+ }
+ if (val[1] < val[0]/3 && najv[0] > 7)
+ trenutni = band+najv[0]-band_tipka;
+ if (trenutni == f->trenutni) {
+ if (f->count++ == f->minimal_duration && f->zadnji_klican != f->trenutni) {
+ f->zadnji_klican = f->trenutni;
+ f->callback(f);
+ }
+ } else {
+ f->count = 0;
+ f->trenutni = trenutni;
+ }
+ f->samples[f->sample++ % SAMPLES] = received;
+}
+#if __INCLUDE_LEVEL__ == 0
+#include <stdio.h>
+#include <string.h>
+void callback (struct fourier * f) {
+ printf("%s\n", toni[f->trenutni]);
+}
+int main (void) {
+ struct fourier f;
+ memset(&f, 0, sizeof f);
+ f.callback = callback;
+ f.minimal_duration = SAMPLES;
+ f.rate = 8000;
+ int received = 0;
+ while ((received = getchar()) != EOF) {
+ unsigned char intermed = received;
+ char recvd = *(char *) &intermed;
+ add_sample(&f, recvd);
+ }
+}
+#endif
diff --git a/frekvence.php b/frekvence.php
new file mode 100755
index 0000000..c085d21
--- /dev/null
+++ b/frekvence.php
@@ -0,0 +1,76 @@
+#!/usr/bin/php
+<?php
+$i = <<<HEREDOC
+1209 dtmf_c1
+1336 dtmf_c2
+1477 dtmf_c3
+1633 dtmf_c4
+697 dtmf_r1
+770 dtmf_r2
+852 dtmf_r3
+941 dtmf_r4
+2100 band_tipka
+800 spodnja_tipka
+1000 zgornja_tipka
+1450 oranžna_tipka
+1750 plava_tipka
+HEREDOC;
+// 1092 roger_prvi preveč mažeta 3. vrstico dtmfjev
+// 869 roger_drugi če dodaš, moraš popraviti tudi v $t spodaj - ZAMIKI!
+// 123 ctcss_123 nesmiselno zaznavati skupaj - ctcss je treba zaznavati posebej!
+$f = [];
+foreach (explode("\n", $i) as $l) {
+ if (trim($l) == "")
+ break;
+ $e = explode("\t", trim($l));
+ $f[$e[0]] = $e[1];
+}
+echo "static int frekvence[] = {" . PHP_EOL;
+foreach ($f as $k => $v)
+ echo " $k, // $v" . PHP_EOL;
+echo "};" . PHP_EOL;
+echo "enum frekvenca {" . PHP_EOL;
+foreach ($f as $k => $v)
+ echo " $v, // $k" . PHP_EOL;
+echo "};" . PHP_EOL;
+echo "static char * imena_frekvenc[] = {" . PHP_EOL;
+foreach ($f as $k => $v)
+ echo " \"$v\", // $k" . PHP_EOL;
+echo "};" . PHP_EOL;
+$t = <<<HEREDOC
+ni
+dtmf_1
+dtmf_2
+dtmf_3
+dtmf_4
+dtmf_5
+dtmf_6
+dtmf_7
+dtmf_8
+dtmf_9
+dtmf_0
+dtmf_a
+dtmf_b
+dtmf_c
+dtmf_d
+dtmf_zvezdica
+dtmf_lojtra
+band
+spodnja
+zgornja
+oranžna
+plava
+HEREDOC;
+// roger1
+// roger2
+// ctcss
+$t = explode("\n", trim($t));
+echo "enum ton {" . PHP_EOL;
+foreach ($t as $ton)
+ echo " $ton," . PHP_EOL;
+echo "};" . PHP_EOL;
+echo "static char * toni[] = {" . PHP_EOL;
+foreach ($t as $ton)
+ echo " \"$ton\"," . PHP_EOL;
+echo "};" . PHP_EOL;
+?>
diff --git a/makefile b/makefile
index 3a2b79f..32eed24 100644
--- a/makefile
+++ b/makefile
@@ -3,7 +3,7 @@ CC=cc
MYCFLAGS=-O0 -Wall -Wextra -Wformat -pedantic -g -I. # -fsanitize=address
MYLDFLAGS=
-default: ptt naprave
+default: ptt naprave fourier
ptt: ptt.c
$(CC) $(MYCFLAGS) $(CFLAGS) $< -o$@ $(MYLDFLAGS) $(LDFLAGS)
@@ -11,6 +11,12 @@ ptt: ptt.c
naprave: naprave.c
$(CC) $(MYCFLAGS) $(CFLAGS) $< -o$@ $(MYLDFLAGS) $(LDFLAGS) -lsoundio
+fourier: fourier.c frekvence.h
+ $(CC) $(MYCFLAGS) $(CFLAGS) $< -o$@ $(MYLDFLAGS) $(LDFLAGS) -lm
+
+frekvence.h: frekvence.php
+ ./frekvence.php > frekvence.h
+
install:
mkdir -p $(DESTDIR)/usr/bin/
cp ptt $(DESTDIR)/usr/bin/
@@ -18,7 +24,7 @@ install:
distclean: clean
clean:
- rm -rf tmp
+ rm -rf tmp fourier frekvence.h
valgrind:
valgrind --error-exitcode=59 --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind-out.txt $(CMD)