aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFreeArtMan <=>2015-09-26 14:32:36 +0100
committerFreeArtMan <=>2015-09-26 14:32:36 +0100
commitb32da0908a2768d03fe57c8b43435971d9685fec (patch)
treef8b314e3ad98b89be2f1e4cd40496fb26a56efb8
parent6b85a7d453414d31432e63045581b2602d4abf45 (diff)
downloadradiola-b32da0908a2768d03fe57c8b43435971d9685fec.tar.gz
radiola-b32da0908a2768d03fe57c8b43435971d9685fec.zip
Added test terminal waterafall
-rw-r--r--draw/glui.h40
-rw-r--r--draw/make.mk2
-rw-r--r--draw/tui.c214
-rw-r--r--draw/tui.h15
-rw-r--r--test/.gitignore1
-rw-r--r--test/Makefile2
-rwxr-xr-xtest/colors.sh25
-rw-r--r--test/ui_gl_waterfall.c7
-rw-r--r--test/ui_tui_waterfall.c325
9 files changed, 618 insertions, 13 deletions
diff --git a/draw/glui.h b/draw/glui.h
index e69de29..d55f931 100644
--- a/draw/glui.h
+++ b/draw/glui.h
@@ -0,0 +1,40 @@
+#ifndef __RADIOLA_GLUI_H
+#define __RADIOLA_GLUI_H
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+//to draw waterfall
+typedef struct glui_waterfall_t
+{
+ int type;
+ int h,w;
+ uint8_t *buf;
+ size_t buf_len;
+} glui_waterfall_t;
+
+typedef struct glui_t
+{
+ glui_waterfall_t *wf;
+} glui_t;
+
+//prepare terminal ui
+int glui_init( glui_t **t );
+//init waterfall
+int glui_waterfall( glui_t **t, glui_waterfall_t **w );
+//first draw, draw all buffer
+int glui_waterfall_draw( glui_waterfall_t *w );
+//redraw only changed lines
+int glui_waterfall_redraw( glui_waterfall_t *w );
+//update params of waterfall and then need to draw not redraw
+int glui_waterfall_update( glui_t *w );
+//push one line of data to buffer
+int glui_waterfall_data( glui_t *w, int len, uint8_t *buf );
+//return color
+uint8_t glui_waterfall_color( uint8_t d );
+//close terminal ui
+int glui_close( glui_t *t ); \ No newline at end of file
diff --git a/draw/make.mk b/draw/make.mk
index 1ce35d1..9756446 100644
--- a/draw/make.mk
+++ b/draw/make.mk
@@ -1,7 +1,7 @@
DIR_DRAW = draw/
SOURCES_DRAW += draw/glui.c draw/tui.c draw/ui.c
OBJECTS_DRAW += $(SOURCES_DRAW:.c=.o)
-LDFLAGS +=
+LDFLAGS += -lGL
OBJECTS_DIR_DRAW += $(subst $(DIR_DRAW),$(BUILD_DIR)$(DIR_DRAW),$(OBJECTS_DRAW))
diff --git a/draw/tui.c b/draw/tui.c
index 5f9b9c7..ba6ed1e 100644
--- a/draw/tui.c
+++ b/draw/tui.c
@@ -1,24 +1,95 @@
#include "tui.h"
+#define T_ESC "\x1b"
+
//prepare terminal ui
-int tui_init( tui_t *t )
+int tui_init( tui_t **t )
{
int ret = -1;
+ tui_t *tui=NULL;
+
//should be empty pointer
- if (t != NULL)
+ if (*t != NULL)
+ return -1;
+
+ tui = malloc( sizeof(tui_t) );
+ if ( tui == NULL )
return -1;
+
+ memset( tui, 0, sizeof( tui_t ) );
+
+ tui->ifd = STDIN_FILENO;
+ tui->ofd = STDOUT_FILENO;
+
+ //if you whant raw mode then you should set it man
+ if ( tcgetattr( tui->ifd, &tui->orig_i ) == -1 )
+ goto exit_error;
+ tui->raw_i = tui->orig_i;
+
+ if ( tcgetattr( tui->ofd, &tui->orig_o ) == -1 )
+ goto exit_error;
+ tui->raw_o = tui->orig_o;
+
+ //set not to echo output
+ /* input modes: no break, no CR to NL, no parity check, no strip char,
+ * no start/stop output control. */
+ tui->raw_i.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+ /* output modes - disable post raw */
+ tui->raw_i.c_oflag &= ~(OPOST);
+ /* control modes - set 8 bit chars */
+ tui->raw_i.c_cflag |= (CS8);
+ /* local modes - choing off, canonical off, no extended functions,
+ * no signal chars (^Z,^C) */
+ tui->raw_i.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
+ /* control chars - set return condition: min number of bytes and timer.
+ * We want read to return every single byte, without timeout. */
+
+ /* put terminal in raw mode after flushing */
+ if (tcsetattr( tui->ifd, TCSAFLUSH, &tui->raw_i) < 0)
+ {
+ //ERROR("Cannot set new terminal input attribures\n");
+ goto exit_error;
+ }
+
+ *t = tui;
+ ret = 0;
+
return ret;
+
+exit_error:
+ free( tui );
+ return -1;
}
//init waterfall
-int tui_waterfall( tui_t *t, tui_waterfall_t *w )
+int tui_waterfall( tui_t **t, tui_waterfall_t **w )
{
int ret=-1;
+ tui_waterfall_t *wtf = NULL;
+
//waterfall should be NULL
- if ( w != NULL )
+ if ( *w != NULL )
+ return -1;
+
+
+ wtf = malloc( sizeof(tui_waterfall_t) );
+ if ( wtf == NULL )
+ {
return -1;
+ }
+
+ memset( wtf, 0, sizeof(tui_waterfall_t) );
+
+ *w = wtf;
+ (*t)->wf = wtf;
+ ret = 0;
+
return ret;
+
+//exit_error:
+
+// return -1;
}
@@ -39,27 +110,158 @@ int tui_waterfall_redraw( tui_waterfall_t *w )
//update params of waterfall and then need to draw not redraw
-int tui_waterfall_update( tui_waterfall_t *w )
+int tui_waterfall_update( tui_t *t )
{
int ret = -1;
+ int row=-1,col=-1;
+ char buf[32];
+ int i;
+
+ //we trust that all params are ok
+
+ /* go to right marging and get position */
+ if ( write( t->ofd, "\x1b[999C", 6 ) != 6 )
+ goto exit_error;
+
+ if ( write( t->ofd, "\x1b[6n", 4 ) != 4 )
+ goto exit_error;
+
+ i = 0;
+ //printf("here=%d\n", sizeof(buf));
+ while (i < sizeof(buf)-1)
+ {
+ if ( read( t->ifd, buf+i,1 ) != 1 ) break;
+ if (buf[i] == 'R') break;
+ i++;
+ }
+ buf[i] = '\0';
+ //printf("i=%d,buf=[%s]\n",i,buf);
+
+ if ( buf[0] != '\x1b' || buf[1] != '[' )
+ {
+ goto exit_error;
+ }
+
+ //printf("i=%d,buf=[%s]\n",i,buf);
+
+ if ( sscanf( buf+2, "%d;%d", &row, &col) != 2 )
+ goto exit_error;
+
+ //write( t->ofd, "\x1b[1C", 4 );
+ write( t->ofd, T_ESC "[H" T_ESC "[2J", 7 );
+ write( t->ofd, T_ESC "[0;0H", 6);
+
+ t->wf->w = col;
+
+ ret = 0;
+
return ret;
+
+exit_error:
+
+ return -1;
}
//push one line of data to buffer
-int tui_waterfall_data( tui_waterfall_t *w, size_t *len, size_t *buf )
+int tui_waterfall_data( tui_t *t, int len, uint8_t *buf )
{
int ret = -1;
+ int i;
+
+
+
+ i = 0;
+ while ( (i< t->wf->w) && ( i<len) )
+ {
+ //printf("-%d", buf[i]);
+ uint8_t c = tui_waterfall_color( buf[i] );
+ char buf[32];
+ snprintf( buf, 32, T_ESC "[48;5;%dm " T_ESC "[0m",c);
+ write( t->ofd, buf, strlen(buf) );
+ i++;
+ }
+
return ret;
}
+uint8_t tui_waterfall_color( uint8_t d )
+{
+
+ uint8_t color=15;
+
+ /*
+ if ( d < 50 )
+ {
+ color = 17;
+ } else if ( d < 100 )
+ {
+ color = 18;
+ } else if ( d < 150 )
+ {
+ color = 19;
+ } else if ( d < 200 )
+ {
+ color = 20;
+ } else
+ {
+ color = 21;
+ }
+ */
+
+
+ if ( d == 0 )
+ {
+ color = 17;
+ } else if ( d == 1 )
+ {
+ color = 18;
+ } else if ( d == 2 )
+ {
+ color = 19;
+ } else if ( d == 3 )
+ {
+ color = 20;
+ } else if ( d == 4 )
+ {
+ color = 21;
+ } else if ( d == 5 )
+ {
+ color = 26;
+ } else if ( d == 6 )
+ {
+ color = 27;
+ } else if ( d == 7 )
+ {
+ color = 44;
+ } else
+ {
+ color = 230;
+ }
+
+ /*
+ uint8_t col[] = { 16,17,18,19,20,21,26,27,44,45,86,87,230,229,228,227,226,214,202,196,160,124,88,52 };
+ int len = 24;
+ int step = 256/len;
+
+ color = col[d/step];
+ */
+
+ return color;
+}
+
//close terminal ui
int tui_close( tui_t *t )
{
int ret = -1;
+
//shouldnt be empty pointer
if ( t == NULL )
return -1;
+
+ //restore terminal mode after closing
+ tcsetattr( t->ifd, TCSAFLUSH, &t->orig_i );
+
return ret;
}
diff --git a/draw/tui.h b/draw/tui.h
index 6357a59..a84379f 100644
--- a/draw/tui.h
+++ b/draw/tui.h
@@ -2,7 +2,9 @@
#define __RADIOLA_TUI_H
#include <stdio.h>
+#include <stdint.h>
#include <stdlib.h>
+#include <string.h>
#include <termios.h>
#include <unistd.h>
@@ -11,7 +13,8 @@ typedef struct tui_waterfall_t
{
int type;
int h,w;
-
+ uint8_t *buf;
+ size_t buf_len;
} tui_waterfall_t;
typedef struct tui_t
@@ -23,17 +26,19 @@ typedef struct tui_t
} tui_t;
//prepare terminal ui
-int tui_init( tui_t *t );
+int tui_init( tui_t **t );
//init waterfall
-int tui_waterfall( tui_t *t, tui_waterfall_t *w );
+int tui_waterfall( tui_t **t, tui_waterfall_t **w );
//first draw, draw all buffer
int tui_waterfall_draw( tui_waterfall_t *w );
//redraw only changed lines
int tui_waterfall_redraw( tui_waterfall_t *w );
//update params of waterfall and then need to draw not redraw
-int tui_waterfall_update( tui_waterfall_t *w );
+int tui_waterfall_update( tui_t *w );
//push one line of data to buffer
-int tui_waterfall_data( tui_waterfall_t *w, size_t *len, size_t *buf );
+int tui_waterfall_data( tui_t *w, int len, uint8_t *buf );
+//return color
+uint8_t tui_waterfall_color( uint8_t d );
//close terminal ui
int tui_close( tui_t *t );
diff --git a/test/.gitignore b/test/.gitignore
index bc5e3c4..c096546 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -1,4 +1,5 @@
get_device_list
read_samples
ui_tui_waterfall
+ui_gl_waterfall
*.o
diff --git a/test/Makefile b/test/Makefile
index 7fb106d..348fd86 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,7 +1,7 @@
CC=gcc
CFLAGS=-I../
#LDFLAGS= `pkg-config --libs libusb` -L../../../r820t -lr820t -Wl,-rpath=../../../r820t
-LDFLAGS=`pkg-config --libs libusb` -lrtlsdr ../radiola.o
+LDFLAGS=`pkg-config --libs libusb` -lrtlsdr -lm ../radiola.o
SOURCE = $(wildcard *.c)
OBJECTS =
BIN = $(SOURCE:.c=)
diff --git a/test/colors.sh b/test/colors.sh
new file mode 100755
index 0000000..7882c40
--- /dev/null
+++ b/test/colors.sh
@@ -0,0 +1,25 @@
+echo -en "\e[38;5;16m#\e[0m"
+echo -en "\e[38;5;17m#\e[0m"
+echo -en "\e[38;5;18m#\e[0m"
+echo -en "\e[38;5;19m#\e[0m"
+echo -en "\e[38;5;20m#\e[0m"
+echo -en "\e[38;5;21m#\e[0m"
+echo -en "\e[38;5;26m#\e[0m"
+echo -en "\e[38;5;27m#\e[0m"
+echo -en "\e[38;5;44m#\e[0m"
+echo -en "\e[38;5;45m#\e[0m"
+echo -en "\e[38;5;86m#\e[0m"
+echo -en "\e[38;5;87m#\e[0m"
+echo -en "\e[38;5;230m#\e[0m"
+echo -en "\e[38;5;229m#\e[0m"
+echo -en "\e[38;5;228m#\e[0m"
+echo -en "\e[38;5;227m#\e[0m"
+echo -en "\e[38;5;226m#\e[0m"
+echo -en "\e[38;5;214m#\e[0m"
+echo -en "\e[38;5;202m#\e[0m"
+echo -en "\e[38;5;202m#\e[0m"
+echo -en "\e[38;5;196m#\e[0m"
+echo -en "\e[38;5;160m#\e[0m"
+echo -en "\e[38;5;124m#\e[0m"
+echo -en "\e[38;5;88m#\e[0m"
+echo -en "\e[38;5;52m#\e[0m" \ No newline at end of file
diff --git a/test/ui_gl_waterfall.c b/test/ui_gl_waterfall.c
new file mode 100644
index 0000000..40872c8
--- /dev/null
+++ b/test/ui_gl_waterfall.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+int main()
+{
+ return 0;
+} \ No newline at end of file
diff --git a/test/ui_tui_waterfall.c b/test/ui_tui_waterfall.c
index a0a83bc..43a21e9 100644
--- a/test/ui_tui_waterfall.c
+++ b/test/ui_tui_waterfall.c
@@ -1,11 +1,336 @@
+#include <math.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
//radiola
#include <draw/tui.h>
+#include <hw/hw.h>
+
+#define SAMPLE_RATE 2048000
+
+#define CENTER_FREQ 100500000
+#define FFT_LEVEL 10
+#define FFT_SIZE (1 << FFT_LEVEL)
+#define BUF_LENGHT (2 * FFT_SIZE)
+#define PRESCALE 8
+#define POSTSCALE 2
+
+static rtlsdr_dev_t *dev = NULL;
+
+int16_t* Sinewave;
+int N_WAVE, LOG2_N_WAVE;
+double* power_table;
+
+int sdr_init()
+{
+ int ret;
+ uint32_t dev_index = 0;
+
+ //open tunner
+ ret = rtlsdr_open(&dev, (uint32_t)dev_index);
+ if ( ret < 0 )
+ {
+ printf("Cannot open device %02d\n", dev_index );
+ return -1;
+ }
+
+ ret = rtlsdr_reset_buffer(dev);
+ if ( ret < 0 )
+ {
+ printf("Couldnt reset buffer\n");
+ return -1;
+ }
+
+ ret = rtlsdr_set_sample_rate(dev, SAMPLE_RATE);
+ if ( ret < 0 )
+ {
+ printf("Coulnt set sample rate to %d\n", SAMPLE_RATE);
+ return -1;
+ }
+
+ ret = rtlsdr_set_center_freq( dev, CENTER_FREQ );
+ if ( ret < 0 )
+ {
+ printf("Couldnt set freq %d\n", CENTER_FREQ);
+ return -1;
+ }
+
+ ret = rtlsdr_set_tuner_gain_mode( dev, 1 );
+ if ( ret < 0 )
+ {
+ printf("Cannot set auto gain mode\n");
+ return -1;
+ }
+
+ ret = rtlsdr_set_agc_mode( dev, 1);
+ if ( ret < 0 )
+ {
+ printf("Cannot set agc mode\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int sdr_close()
+{
+ //close tunner
+ if ( dev != NULL)
+ {
+ rtlsdr_close( dev );
+ dev = NULL;
+ return 0;
+ }
+ return -1;
+}
+
+int sdr_get_samples( uint8_t *buf, int len )
+{
+ int ret, read_num;
+
+ ret = rtlsdr_read_sync( dev, buf, len, &read_num );
+ if (ret < 0)
+ {
+ printf("sync read failed\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+//better to have size size mod olen == 0
+int normalise( uint8_t *ibuf, int ilen, uint8_t *obuf, int olen )
+{
+ int i,j,m;
+ int ppi;
+
+ if ( ilen >= olen )
+ {
+ ppi = ilen / olen;
+ } else {
+ return -1;
+ }
+ m = 0;
+ i = 0;
+ while ( (i < ilen) && (m < olen) )
+ {
+ uint32_t sum=0;
+ for ( j=0; j<ppi; j++ );
+ sum += ibuf[i+j];
+ sum /= ppi;
+ obuf[m] = sum;
+ //printf("%d-", obuf[m] );
+
+ i += ppi;
+ m += 1;
+ }
+
+ return 0;
+}
+
+void sine_table(int size)
+{
+ int i;
+ double d;
+ LOG2_N_WAVE = size;
+ N_WAVE = 1 << LOG2_N_WAVE;
+ Sinewave = malloc(sizeof(int16_t) * N_WAVE*3/4);
+ power_table = malloc(sizeof(double) * N_WAVE);
+ for (i=0; i<N_WAVE*3/4; i++)
+ {
+ d = (double)i * 2.0 * M_PI / N_WAVE;
+ Sinewave[i] = (int)round(32767*sin(d));
+ }
+}
+
+int16_t FIX_MPY(int16_t a, int16_t b)
+/* fixed point multiply and scale */
+{
+ int c = ((int)a * (int)b) >> 14;
+ b = c & 0x01;
+ return (c >> 1) + b;
+}
+
+int32_t real_conj(int16_t real, int16_t imag)
+/* real(n * conj(n)) */
+{
+ return ((int32_t)real*(int32_t)real + (int32_t)imag*(int32_t)imag);
+}
+
+int fix_fft(int16_t iq[], int m)
+/* interleaved iq[], 0 <= n < 2**m, changes in place */
+{
+ int mr, nn, i, j, l, k, istep, n, shift;
+ int16_t qr, qi, tr, ti, wr, wi;
+ n = 1 << m;
+ if (n > N_WAVE)
+ {return -1;}
+ mr = 0;
+ nn = n - 1;
+ /* decimation in time - re-order data */
+ for (m=1; m<=nn; ++m) {
+ l = n;
+ do
+ {l >>= 1;}
+ while (mr+l > nn);
+ mr = (mr & (l-1)) + l;
+ if (mr <= m)
+ {continue;}
+ // real = 2*m, imag = 2*m+1
+ tr = iq[2*m];
+ iq[2*m] = iq[2*mr];
+ iq[2*mr] = tr;
+ ti = iq[2*m+1];
+ iq[2*m+1] = iq[2*mr+1];
+ iq[2*mr+1] = ti;
+ }
+ l = 1;
+ k = LOG2_N_WAVE-1;
+ while (l < n) {
+ shift = 1;
+ istep = l << 1;
+ for (m=0; m<l; ++m) {
+ j = m << k;
+ wr = Sinewave[j+N_WAVE/4];
+ wi = -Sinewave[j];
+ if (shift) {
+ wr >>= 1; wi >>= 1;}
+ for (i=m; i<n; i+=istep) {
+ j = i + l;
+ tr = FIX_MPY(wr,iq[2*j]) - FIX_MPY(wi,iq[2*j+1]);
+ ti = FIX_MPY(wr,iq[2*j+1]) + FIX_MPY(wi,iq[2*j]);
+ qr = iq[2*i];
+ qi = iq[2*i+1];
+ if (shift) {
+ qr >>= 1; qi >>= 1;}
+ iq[2*j] = qr - tr;
+ iq[2*j+1] = qi - ti;
+ iq[2*i] = qr + tr;
+ iq[2*i+1] = qi + ti;
+ }
+ }
+ --k;
+ l = istep;
+ }
+ return 0;
+}
+
+//fftize
+int simple_fft( uint8_t *buf, int len )
+{
+ int i,j;
+ uint16_t p;
+ int fft_len;
+
+ for (i=0; i<len; i++)
+ {
+ buf[i] = buf[i] * PRESCALE;
+ }
+
+ fix_fft( (uint16_t *)buf, FFT_LEVEL );
+
+ for (i=0; i<FFT_SIZE; i++)
+ {
+ //buf1[i] = rtl_out.buf[i];
+ //p = buf1[i] * buf1[i];
+ j = i*2;
+ p = (int16_t)real_conj(buf[j], buf[j + 1]);
+ buf[i] += p;
+ }
+
+ fft_len = FFT_SIZE / 2;
+ for (i=0; i<fft_len; i++)
+ {
+ buf[i] = (int)log10(POSTSCALE * (float)buf[i+fft_len]);
+ buf[i+fft_len] = (int)log10(POSTSCALE * (float)buf[i]);
+ }
+
+ return 0;
+}
int main()
{
+ int i,j;
+ uint8_t *buf, *sample_buf;
+ int buf_len, sample_len;
+ uint32_t dev_num;
+
+ tui_t *t = NULL;
+ tui_waterfall_t *w = NULL;
+
+ if ( sdr_init() == -1 )
+ {
+ goto main_exit;
+ }
+
+ sine_table( FFT_LEVEL );
+
+
+ //printf("%x\n",t);
+ //open GUI
+ if ( tui_init( &t ) == -1 )
+ {
+ printf("Cannot set tui\n");
+ return 1;
+ }
+
+ //printf("%x\n",t);
+ if ( tui_waterfall( &t, &w ) == -1 )
+ {
+ printf("Cannot set waterfall\n");
+ return 1;
+ }
+
+ if ( tui_waterfall_update( t ) == -1)
+ {
+ printf("Cannot update waterfall size\n");
+ return -1;
+ }
+
+ dev_num = rtlsdr_get_device_count();
+ if ( dev_num < 1 )
+ {
+ printf( "Cannot find any device" );
+ goto main_exit;
+ }
+
+
+
+ buf_len = sizeof(char)*w->w;
+ buf = malloc( buf_len );
+
+ sample_len = BUF_LENGHT;
+ sample_buf = malloc( sample_len );
+
+ srand(0); //fake seed
+ for ( i=0; i<20;i++ )
+ {
+ //for (j=0; j<buf_len; j++)
+ // sample_buf[j] = (uint8_t)((rand()&0xff));
+
+ //read some samples
+ sdr_get_samples( sample_buf, sample_len );
+
+ //do fft
+ //simple_fft( sample_buf, sample_len/2 );
+
+ //prepare to show on the screen
+ if (normalise( sample_buf, sample_len, buf, buf_len ) == -1)
+ {
+ printf("Cannot normalise\n");
+ }
+ tui_waterfall_data( t, buf_len, buf );
+ //printf("\n\b");
+ sleep(1);
+ }
+
+main_exit:
+ //close gui, restore terminal mode
+ tui_close( t );
+ sdr_close();
+
return 0;
} \ No newline at end of file