podwójne buforowanie i dane i widmo

0

Witam!! Mam problem, mianowicie musze użyć podwójnego buforowania w celu dostarczenia danych do fukcji obliczającej widmo sygnału, z którego pochodzą dane. Funkcją obliczającą jest DFT (dyskretna transformata Fouriera). Proszę o jakiś fragment kodu (C++, Delphi), bo nie za bardzo wiem jak sie za to buforowanie zabrać. Pozdrawiam!!

0

A w czym problem ? :-)
Czy chodzi o STFFT?

0

O STFT raczej, ale bardziej interesuje mnie zadanie wypełnienia podwójnego buforu, nastepnie przesłania cześci danych z niego do funkcji obliczającej i tak na zmiane.

0
krwawy_zniwiarz napisał(a)

...j i tak na zmiane.
na zmianę z czym?
<font size="2">FIFO?</span>

0

mianowicie musze użyć podwójnego buforowania w celu dostarczenia danych do fukcji obliczającej widmo sygnału,

Pytanie zbyt ogólne żeby na nie sensownie odpowiedzieć. Czym jest źródło danych? Chodzi o wielowątkowość...?

Jednym słowem - szczegóły.

0

Jeśli chodzi o ta zmianę to bufor ma się zapełnic do połowy (50%) i ta zapełniona część ma zostać przesłana do funkcji obliczającej, a ta druga połówka w tym samym czasie ma sie zapełniać. Po czym ta druga połówka jest obliczana, a druga zapełniana. Źródłem danych jest karta, tutaj link: http://www.elmark.com.pl/index.php?id=17&idw=133

0

A jak gadasz z kartą? Poprzez porty czy jakiś driver? Odbierasz po próbce czy blokami? Czy w czasie gromadzenia ewentualnego bloku twój program działa czy też czeka na zakończenie? Czy...

Więc jak?

0

Poprzez port PCI i próbkami. Mam też jakiś testowy programik, ale za bardzo nie obczajam jego kodu.
Zapomniałem dodać, ze dopiero zaczynam tworzyć ten programik, a jeżeli chodzi o odbieranie danych to próbki będą bardziej odpowiednie niż bloki (zbiór próbek) do wyświetlenia widma.

OTO TEN KOD:

unit AIUnit;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
OleCtrls, StdCtrls, DAQAILib_TLB, Buttons, ExtCtrls, Variants;

type
TForm1 = class(TForm)
GroupBox1: TGroupBox;
Label1: TLabel;
Label2: TLabel;
cmdExit: TBitBtn;
GroupBox8: TGroupBox;
lstReading: TListBox;
cmdAcquireStart: TButton;
cmdAcquireStop: TButton;
cmdStatus: TButton;
txtStatus: TEdit;
txtDeviceNum: TEdit;
txtDeviceName: TEdit;
cmdSelectDevice: TButton;
GroupBox10: TGroupBox;
Label5: TLabel;
cmbStartChannel: TComboBox;
Label6: TLabel;
cmbNumChan: TComboBox;
Label3: TLabel;
cmbInputRange: TComboBox;
chkOverAllGain: TCheckBox;
cmdGainList: TButton;
Label4: TLabel;
cmbDataType: TComboBox;
Label12: TLabel;
cmbTransferMode: TComboBox;
Label13: TLabel;
cmbTrigSource: TComboBox;
Label14: TLabel;
cmbClockSource: TComboBox;
Label15: TLabel;
txtSampleRate: TEdit;
Label7: TLabel;
Label8: TLabel;
txtNumOfSample: TEdit;
GroupBox6: TGroupBox;
Label9: TLabel;
chkFIFOEnabled: TCheckBox;
txtFIFOSize: TEdit;
chkEventEnabled: TCheckBox;
chkCyclicMode: TCheckBox;
ScanTimer: TTimer;
cmdAutoGet: TButton;
cmdStopAutoGet: TButton;
GroupBox2: TGroupBox;
Label11: TLabel;
txtErrorCode: TEdit;
txtErrorMessage: TEdit;
Label10: TLabel;
DAQAI1: TDAQAI;
ErrorTimer: TTimer;
procedure chkFIFOEnabledClick(Sender: TObject);
procedure chkOverAllGainClick(Sender: TObject);
procedure cmbDataTypeClick(Sender: TObject);
procedure cmbTransferModeClick(Sender: TObject);
procedure cmdAcquireStartClick(Sender: TObject);
procedure cmdAcquireStopClick(Sender: TObject);
procedure cmdGainListClick(Sender: TObject);
procedure cmdSelectDeviceClick(Sender: TObject);
procedure cmdStatusClick(Sender: TObject);
procedure DAQAI1EventRaw(Sender: TObject; DataCount: Integer;
Data: OleVariant);
procedure DAQAI1EventReal(Sender: TObject; DataCount: Integer;
Data: OleVariant);
procedure DAQAI1Terminated(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure txtDeviceNumChange(Sender: TObject);
procedure txtNumOfSampleChange(Sender: TObject);
procedure txtSampleRateChange(Sender: TObject);
procedure ScanTimerTimer(Sender: TObject);
procedure chkCyclicModeClick(Sender: TObject);
procedure chkEventEnabledClick(Sender: TObject);
procedure cmdAutoGetClick(Sender: TObject);
procedure cmdStopAutoGetClick(Sender: TObject);
procedure cmbClockSourceChange(Sender: TObject);
procedure cmbTrigSourceChange(Sender: TObject);
procedure cmbStartChannelChange(Sender: TObject);
procedure cmbNumChanChange(Sender: TObject);
procedure ErrorTimerTimer(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
bRet : Boolean;

implementation

uses GainUnit;

{$R *.DFM}

procedure TForm1.chkFIFOEnabledClick(Sender: TObject);
begin
if chkFIFOEnabled.State = cbChecked then
begin
txtFIFOSize.Enabled := True;
DAQAI1.FIFOEnabled := True;
txtFIFOSize.Text := IntToStr(DAQAI1.FIFOSize);
end
else
begin
txtFIFOSize.Enabled := False;
DAQAI1.FIFOEnabled := False;
txtFIFOSize.Text := '0';
end;
end;

procedure TForm1.chkOverAllGainClick(Sender: TObject);
begin
if chkOverAllGain.State = cbChecked then
begin
cmbInputRange.Enabled := True;
cmdGainList.Enabled := False;
DAQAI1.InputRangeMode := adOverallRange;
end
else
begin
cmbInputRange.Enabled := False;
cmdGainList.Enabled := True;
DAQAI1.InputRangeMode := adDifferentRange;
{Set gain code list}
end;
end;

procedure TForm1.cmbDataTypeClick(Sender: TObject);
begin
DAQAI1.DataType := cmbDataType.ItemIndex;
end;

procedure TForm1.cmbTransferModeClick(Sender: TObject);
begin
DAQAI1.TransferMode := cmbTransferMode.ItemIndex;
end;

procedure TForm1.cmdAcquireStartClick(Sender: TObject);
var
i : integer;
begin
lstReading.Clear;

if DAQAI1.OpenDevice then
begin
ShowMessage(DAQAI1.ErrorMessage);
Exit;
end;

if DAQAI1.InputRangeMode = adDifferentRange then
begin
gGainCodeList := VarArrayCreate([0, gNumOfChan -1], varSmallint);
for i := 0 to gNumOfChan -1 do
gGainCodeList[i] := gGainCodeSave[i];
DAQAI1.InputRangeList := gGainCodeList;
end
else
begin
DAQAI1.OverallInputRange := cmbInputRange.ItemIndex;
if DAQAI1.OverallInputRange < 0 then
DAQAI1.OverallInputRange := 0;
end;

{Start getting data}
bRet := DAQAI1.AcquireStart;
if bRet then
begin
ShowMessage(DAQAI1.ErrorMessage);
Exit;
end;

GroupBox10.Enabled := False;

cmdAcquireStart.Enabled := False;
cmdAcquireStop.Enabled := True;
cmdExit.Enabled := False;
cmdSelectDevice.Enabled := False;
cmdAutoGet.Enabled := True;
ErrorTimer.Enabled := True;
end;

procedure TForm1.cmdAcquireStopClick(Sender: TObject);
begin
GroupBox10.Enabled := True;
cmdAcquireStart.Enabled := True;
cmdAcquireStop.Enabled := False;
cmdExit.Enabled := True;
cmdSelectDevice.Enabled := True;
cmdAutoGet.Enabled := False;
ErrorTimer.Enabled := False;

{Stop get data}
bRet := DAQAI1.AcquireStop;
if bRet then
begin
ShowMessage(DAQAI1.ErrorMessage);
Exit;
end;

{Close device}
bRet := DAQAI1.CloseDevice;
if bRet then
begin
ShowMessage(DAQAI1.ErrorMessage);
Exit;
end;
end;

procedure TForm1.cmdGainListClick(Sender: TObject);
begin
frmGainList.Show;
end;

procedure TForm1.cmdSelectDeviceClick(Sender: TObject);
var
i : Integer;
j : Integer;
strGain : WideString;
begin
DAQAI1.SelectDevice;

txtDeviceNum.Text := IntToStr(DAQAI1.DeviceNumber);
txtDeviceName.Text := DAQAI1.DeviceName;

cmbInputRange.Clear;
cmbStartChannel.Clear;
cmbNumChan.Clear;

gNumOfInputRange := 0;
gNumOfChan := 0;

{Open device}
if DAQAI1.OpenDevice then
begin
ShowMessage(DAQAI1.ErrorMessage);
Exit;
end;

{Get input range list}
SetLength(strGain, 30);
bRet := DAQAI1.GetFirstInputRange(strGain);
i := 0;
while bRet = False do
begin
gInputRangeList[i] := strGain;
cmbInputRange.Items.Add(gInputRangeList[i]);
i := i + 1;
bRet := DAQAI1.GetNextInputRange(strGain);
end;

If i <> 0 then
begin
cmbInputRange.ItemIndex := 0;
gNumOfInputRange := i;
end;

{Get Max. channel number}
if DAQAI1.MaxDifferentialChannel > DAQAI1.MaxSingleEndedChannel then
i := DAQAI1.MaxDifferentialChannel
else
i := DAQAI1.MaxSingleEndedChannel;

if i = 0 then
begin
ShowMessage('Function Not Supported');
DAQAI1.CloseDevice;
Exit;
end;

gNumOfChan := i;

for j := 0 to i - 1 do
begin
cmbStartChannel.Items.Add (IntToStr(j));
cmbNumChan.Items.Add (IntToStr(j + 1));
gGainCodeSave[j] := 0;
end;
cmbStartChannel.ItemIndex := 0;
cmbNumChan.ItemIndex := 0;
DAQAI1.StartChannel := 0;
DAQAI1.NumberOfChannels := 1;
DAQAI1.CloseDevice;
end;

procedure TForm1.cmdStatusClick(Sender: TObject);
begin
txtStatus.Text := IntToStr(DAQAI1.AcquireStatus);
end;

procedure TForm1.DAQAI1EventRaw(Sender: TObject; DataCount: Integer;
Data: OleVariant);
var
i : LongInt;
j : LongInt;
begin
lstReading.Clear;

if DataCount > 10 then
j := 10
else
j := DataCount;

for i := 0 to j - 1 do {DataCount - 1}
lstReading.Items.Add (IntToStr(Data[i]));
end;

procedure TForm1.DAQAI1EventReal(Sender: TObject; DataCount: Integer;
Data: OleVariant);
var
i : LongInt;
j : LongInt;
begin
lstReading.Clear;

if DataCount > 10 then
j := 10
else
j := DataCount;

for i := 0 to j - 1 do {DataCount - 1}
lstReading.Items.Add (FormatFloat('0.000000', Data[i]));
end;

procedure TForm1.DAQAI1Terminated(Sender: TObject);
var
UserData : OleVariant;
i : Integer;
begin
ScanTimer.Enabled := False;
ErrorTimer.Enabled := False;
GroupBox10.Enabled := True;
cmdAcquireStart.Enabled := True;
cmdAcquireStop.Enabled := False;
cmdExit.Enabled := True;
cmdAutoGet.Enabled := False;
cmdStopAutoGet.Enabled := False;
cmdSelectDevice.Enabled := True;

lstReading.Clear;

if DAQAI1.DataType = adRaw then
begin
UserData := VarArrayCreate([0, 9], varSmallint);
DAQAI1.GetBufferData(0, 10, UserData);
for i := 0 to 9 do
lstReading.Items.Add (IntToStr(UserData[i]));
end
else
begin
UserData := VarArrayCreate([0, 9], varSingle);
DAQAI1.GetBufferData(0, 10, UserData);
for i := 0 to 9 do
lstReading.Items.Add (FormatFloat('0.000000', UserData[i]));
end;

{Stop get data}
DAQAI1.AcquireStop;
{Close device}
DAQAI1.CloseDevice;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
{Select default device}
cmdSelectDevice.Click();

{Setting initial value}
txtDeviceNum.Text := IntToStr(DAQAI1.DeviceNumber);
txtDeviceName.Text := DAQAI1.DeviceName;
cmbDataType.ItemIndex := DAQAI1.DataType;
cmbStartChannel.ItemIndex := DAQAI1.StartChannel;
cmbNumChan.ItemIndex := DAQAI1.NumberOfChannels - 1;
cmbTransferMode.ItemIndex := DAQAI1.TransferMode;
cmbClockSource.ItemIndex := DAQAI1.ClockSource;
if DAQAI1.ExtTrigger then
cmbTrigSource.ItemIndex := 1
else
cmbTrigSource.ItemIndex := 0;
DAQAI1.SampleRate := 100;
DAQAI1.NumberOfSamples := 100;
lstReading.Clear;
end;

procedure TForm1.txtDeviceNumChange(Sender: TObject);
begin
DAQAI1.DeviceNumber := StrToInt(txtDeviceNum.Text);
txtDeviceName.Text := DAQAI1.DeviceName;
end;

procedure TForm1.txtNumOfSampleChange(Sender: TObject);
begin
DAQAI1.NumberOfSamples := StrToInt(txtNumOfSample.Text);
end;

procedure TForm1.txtSampleRateChange(Sender: TObject);
begin
DAQAI1.SampleRate := StrToInt(txtSampleRate.Text);
end;

procedure TForm1.ScanTimerTimer(Sender: TObject);
var
UserData : OleVariant;
i : Integer;
begin
lstReading.Clear;

if DAQAI1.DataType = adRaw then
begin
UserData := VarArrayCreate([0, 9], varSmallint);
DAQAI1.GetBufferData(0, 10, UserData);
for i := 0 to 9 do
lstReading.Items.Add (IntToStr(UserData[i]));
end
else
begin
UserData := VarArrayCreate([0, 9], varSingle);
DAQAI1.GetBufferData(0, 10, UserData);
for i := 0 to 9 do
lstReading.Items.Add (FormatFloat('0.000000', UserData[i]));
end;
end;

procedure TForm1.chkCyclicModeClick(Sender: TObject);
begin
if chkCyclicMode.State = cbChecked then
DAQAI1.CyclicMode := True
else
DAQAI1.CyclicMode := False;
end;

procedure TForm1.chkEventEnabledClick(Sender: TObject);
begin
if chkEventEnabled.State = cbChecked then
DAQAI1.EventEnabled := True
else
DAQAI1.EventEnabled := False;
end;

procedure TForm1.cmdAutoGetClick(Sender: TObject);
begin
ScanTimer.Enabled := True;
cmdAcquireStop.Enabled := False;
cmdAutoGet.Enabled := False;
cmdStopAutoGet.Enabled := True;
end;

procedure TForm1.cmdStopAutoGetClick(Sender: TObject);
begin
ScanTimer.Enabled := False;
cmdAcquireStop.Enabled := True;
cmdAutoGet.Enabled := True;
cmdStopAutoGet.Enabled := False;
end;

procedure TForm1.cmbClockSourceChange(Sender: TObject);
begin
DAQAI1.ClockSource := cmbClockSource.ItemIndex;
end;

procedure TForm1.cmbTrigSourceChange(Sender: TObject);
begin
if cmbTrigSource.ItemIndex = 1 then
DAQAI1.ExtTrigger := True;
end;

procedure TForm1.cmbStartChannelChange(Sender: TObject);
var
i : integer;
num : integer;
begin
cmbNumChan.Clear;
num := gNumOfChan - cmbStartChannel.ItemIndex;
for i := 1 to num do
cmbNumChan.Items.Add (IntToStr(i));
cmbNumChan.ItemIndex := 0;
DAQAI1.NumberOfChannels := 1;
DAQAI1.StartChannel := cmbStartChannel.ItemIndex;
end;

procedure TForm1.cmbNumChanChange(Sender: TObject);
begin
DAQAI1.NumberOfChannels := cmbNumChan.ItemIndex + 1;
end;

procedure TForm1.ErrorTimerTimer(Sender: TObject);
begin
txtErrorCode.Text := IntToStr(DAQAI1.ErrorCode);
txtErrorMessage.Text := DAQAI1.ErrorMessage;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
ScanTimer.Enabled := False;
ErrorTimer.Enabled := False;
DAQAI1.AcquireStop;
DAQAI1.CloseDevice;
end;

end.

0

Jak próbkami przecież ta karta ma wbudowane FIFO ? ;) Opisz komunikację z kartą. Windows?

Ogólnie wygląda to tak, że jak karta "wypluje" bufor z danymi kopiujesz go do przygotowanego wcześniej bufora programowego. Nie wiem jakie jest to DFT ale pewnie trzeba będzie w trakcie przekonwertować 16 bitowe sample na float lub double. Rozmiar bufora oczywiście musi pomieścić wszystkie sample z bufora karty.

0

swapuj wskaznik?

0

Standardowo Windows nie ma sterowników pod tą kartę, ze strony producenta można pobrać sterowniki, biblioteki do programowania i programik (Device Manager), dzięki któremu wszystko jest widoczne przez system.

Mniej więcej czaje co masz na myśli, ale nie wiem jak to zrobić.

Jeden koles mi mówił, ze można również użyć FFT, ale ponoć DFT jest bardziej odpowiednie.

Tutaj link z DFT(appendix A) i FFT(appendix B): http://local.wasp.uwa.edu.au/~pbourke/other/dft/index.html

0

DFT vs FFT
user image
user image
wniosek? zapomnij o DFT

Sam musisz się chyba przegryźć przez dokumentację i sterownik.
Post jest w dziale C/C++ a dałeś kawałek w Delphi, ciekawsze byłoby popatrzeć w PoDAQAILib_TLB.
Dla C jest pewnie jakieś PoDAQAILib_TLB.H
Trzeba to jakoś otworzyć, ustalić parametry pracy (wzmocnienie, kanały, wyzwalanie, częstotliwość), wystartować i zależnie od tego co w oprogramowaniu dał producent jakoś "podkradać" próbki.

O a co z filtrem Nyquist'a?

0

Biblioteki mam i w nich nic nie trzeba kombinować, je sie instaluje i później importuje do Delphi lub C++. Co znaczy jakoś "podkradac" próbki??

0

:-D Inaczej. Jest gdzieś dostępny w sieci help to tej biblioteki?

0

Rozumiem, że szkielet obsługujący kartę masz zrobiony? Zasadniczo to tam masz zdarzenie OnEventRaw i tu masz dostęp do danych. Zresztą w tym kodzie co znalazłeś jest:

procedure TForm1.DAQAI1EventRaw(Sender: TObject; DataCount: Integer; Data: OleVariant);
var
   i : LongInt;
   j : LongInt;
begin
   lstReading.Clear;

   if DataCount > 10 then
      j := 10
   else
      j := DataCount;

   for i := 0 to j - 1 do {DataCount - 1}
      lstReading.Items.Add (IntToStr(Data[i]));
end;

A z tym drugim buforem chodzi (pewnie) o to, że musisz w nim przygotować dane dla DFT/FFT. Zapewne potrzebny będzie też bufor wyjściowy.

0

Które wskaźniki mam zamienić??

1 użytkowników online, w tym zalogowanych: 0, gości: 1