среда, 25 марта 2015 г.

Открыл API доступа к RTL-SDR чипу DVB-тюнера под Delphi

Перевел и открыл API 'API_RTL_SDR.pas' http://sourceforge.net/projects/guiforrrtlpower/files/src/API_RTL_SDR%20for%20Delphi.zip/download прямого доступа к отсчетам сигнала под Delphi. Инициализация-деинициализация автоматом, просто подключите модуль в USES. Для расчета спектра использована библиотека 'FFTR.DLL' моей разработки (в комплекте).



Пример использования:
uses API_RTL_SDR, TypInfo, math;

const
    BufSize = 4096; // количество точек FFT
    //#define BUF_LENGTH (16 * 16384)
    BUF_LENGTH = (16 * 16384);
var i, outi, gain, h, hwnd: integer;
    tp: rtlsdr_tuner;
    buf: array[0..BUF_LENGTH] of byte;
    fDataBuf: array of single;
    flag: boolean = false;
    onoff: boolean = false;
    ThreadID: dword;
    step: double;
    f, df: longword;

    fftio:function(var buf: array of single;
                   nf: integer;
                   directfft: Boolean
                   ): pansichar; stdcall; LibHandle: THandle;

function LinkProc(h: thandle; ProcName: string):Pointer;
begin
 result:= GetProcAddress(h, PChar(ProcName))
end;


function read(
     buf: pansichar;
     size: integer;
     ctx: Pointer): longword;
begin

end;

procedure TTH;
var k: integer;
    d: double;
begin
{ if onoff then begin
  onoff:= false;
  rtlsdr_wait_async(dev,
                    @read,
                    nil);
 end;
   }

 while not FLAG do begin
  h:= rtlsdr_read_sync(dev, @buf, outi, @i);
  if (i < outi)or (h=-1) then begin
   flag:= true;
   form1.button1.Enabled:= true;
  end;

  // подчищаем
  setlength(fDataBuf, 0);
  for k:= 0 to length(buf)-1 do begin
   setlength(fDataBuf, length(fDataBuf)+1);
   fDataBuf[length(fDataBuf)-1]:= buf[k];
  end;
  // прямое БПФ
  fftio(fDataBuf, BufSize, true);
  for k:= 0 to BufSize div 2 -1 do begin // отсекаем зеркалку
    d:= 20*log10(abs(fDataBuf[k]) + 0.000001);
    form1.Series1.XValue[k]:= f - (df/2) + k*step;
    form1.Series1.YValue[k]:= d;
  end;


 end;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
 button1.Enabled:= false;
 flag:= false;
 i:= 0;
 outi:= BUF_LENGTH;

 onoff:= true;
 //создаем параллельный поток
 hwnd:= CreateThread(nil, 0, @TTH, nil, 0, ThreadID);
end;


procedure TForm1.Button2Click(Sender: TObject);
begin
 TerminateThread(hwnd, 0);
 button1.Enabled:= true;
 flag:= false;
 onoff:= false;
end;



procedure TForm1.Button3Click(Sender: TObject);
var s: string;
begin
 dongle_count:= rtlsdr_get_device_count();
 memo1.Lines.Add(format('Кол-во донглов RTL в ОС: %d', [dongle_count]));

 for i:= 0 to dongle_count-1 do begin
  memo1.Lines.Add('Имя: '+ rtlsdr_get_device_name(i));
  rtlsdr_get_device_usb_strings(i,
                                          @manufact,
                                          @product,
                                          @serial);
  memo1.Lines.Add('Производитель: ' + string(manufact) + #13#10 +
                  'Продукт: ' + string(product) + #13#10 +
                  'Серийник: ' + string(serial));
 end;

 // пробуем открыть 0-й
 if dongle_count >0 then begin
  i:= rtlsdr_open(@dev, 0);
  if i <> -1 then begin
   // чип
   tp:= rtlsdr_get_tuner_type(dev);
   Memo1.Lines.Add('Чип: ' + GetEnumName(TypeInfo(rtlsdr_tuner), integer(tp))+ #13#10);

   // задаем центральную частоту для сканирования, Hz
   i:= rtlsdr_set_center_freq(dev, 446000000);
   // реальная настройка
   f:= rtlsdr_get_center_freq(dev);
   Memo1.Lines.Add('Центральная частота: ' + inttostr(f) + ' Hz');

   // задаем полосу 225 kHz
   // enable:
   // 225001 - 300000 Hz
   // 900001 - 3200000 Hz

   rtlsdr_set_sample_rate(dev, 3200000);
   // реальная полоса
   df:= rtlsdr_get_sample_rate(dev);
   Memo1.Lines.Add('Полоса: ' + inttostr(df) + ' Hz');

   // доступные коэффициенты усиления
   s:= '';
   Memo1.Lines.Add('Доступные коэффициенты усиления, дБ:');
   gain:= rtlsdr_get_tuner_gains(dev, @masint);
   for i:= 0 to gain-1 do
    s:= s + format('%.1f ', [masint[i]/10]);
   Memo1.Lines.Add(s+ #13#10);

   // задаем коэфф-т усиления 14.4 дБ = 144 (*10)
   rtlsdr_set_tuner_gain_mode(dev, 125);

   // задаем смещение частоты синтезатора в PPM
   rtlsdr_set_freq_correction(dev, 0);
   // реальное значение смещения PPM
   Memo1.Lines.Add('PPM: ' + inttostr(rtlsdr_get_freq_correction(dev)));

   // сброс буфера
   rtlsdr_reset_buffer(dev);

   // шаг по частоте, Hz
   step:= 2*df/BufSize;
   Memo1.Lines.Add('Шаг по частоте, Hz: ' + format('%f', [step]));
   Memo1.Lines.Add('Кол-во точек FFT: ' + format('%d', [BufSize]));
   button1.OnClick(nil);
  end;
 end;
end;



procedure TForm1.FormCreate(Sender: TObject);
var k: integer;
begin
 decimalseparator:= '.';

 for k:= 0 to BufSize div 2 - 1 do
  series1.AddXY(0,0, '', clred);

 // подключаем DLL FFT
 LibHandle:= LoadLibrary('FFTR.dll');
 if LibHandle<>0 then
  fftio:= LinkProc(LibHandle, 'fftio');

 button3.OnClick(nil);
end;


procedure TForm1.FormDestroy(Sender: TObject);
begin
 if hwnd<>0 then TerminateThread(hwnd, 0);
 if LibHandle<>0 then freelibrary(LibHandle)
end;


Тематические ссылки
  1. Анонс нашего проекта на официальном ресурсе RTL-SDR
  2. Открыл API доступа к RTL-SDR чипу DVB-тюнера под Delphi
  3. Панорамный анализатор спектра из DVB-T тюнера
  4. Обновление 'RTL-SDR Panoramic Spectrum Analyzer' 
  5. Панорамный анализатор спектра с прямым доступом к чипу RTL-SDR 
  6. Ресурсы проекта панорамного FFT анализатора и циклической записи/воспроизведения выборок в файл на SourceForge
  7. Циклическая запись/воспроизведение в панорамном FFT анализаторе с прямым доступом к чипу
скачать

2 комментария:

  1. Проведено обновление архива новым модифицированными драйвером RTL-SDR (выше помехоустойчивость на частотах ниже 14 МГц). Ссылка прежняя.

    ОтветитьУдалить
  2. Знаете-ли вы, что RTL-SDR в режиме анализатора спектра можно использовать в качестве детектора обнаружения разряда в диэлектрике, при пробое газовой среды электросетевого оборудования, в частности в оборудовании, таком как - генераторы, двигатели? Ведь, если вспомнить физику, то искра обладает довольно широким спектром, который вполне себе слышен на СВ, КВ и УКВ на обычные бытовые приемники. Тут же спектр и временные параметры пробоя можно вполне себе бюджетно оцифровать )

    ОтветитьУдалить

В комментариях уважайте собеседника, внимательно читайте посты и не додумывайте. Просьбы и предложения из разряда: «можно ваш Skype/Viber/телефон», «напишите мне в vk/FB», а также другие им подобные — игнорируются. Выход новых версий ПО, внешняя ссылка, переставшая работать с течением времени и т.п. не является основанием для претензий. Желающие спокойно подискутировать и высказаться — Welcome. Желающие спонсировать блог — Donate. Нарушение этих простых правил ведет к бану и удалению комментариев без предупреждения.