//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <math.h>
#include "Unit1.h"
#include "Zadc_int.h" // Заголовочный файл интерфейса библиотеки Zadc.dll
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
#define MAX_TYPE_DSP 30 // Максимальное поддерживаемое кол-во типов устройств
// Глобальные переменные
long typeDevice; // Тип устройства
long numberDSP; // Порядковый номер устройства
bool deviceOpened; // Устройство открыто
bool deviceError; // Ошибка устройства
bool deviceStarted; // Устройство проинициализировано и запущено
long numChannelsDAC; // Кол-во включенных каналов ЦАП
long numWordsDAC; // Кол-во слов (по два байта) в одном отсчете ЦАП
short *pBuffer16DAC; // Указатель на начало буфера драйвера для ЦАП с разрядностью не более 16 бит
long *pBuffer32DAC; // Указатель на начало буфера драйвера для ЦАП с разрядностью более 16 бит
long sizeBufferDAC; // Размер буфера драйвера в словах
long sizeInterruptBufferDAC; // Размер буфера прерывания в словах
long sizePacketDAC; // Кол-во отсчетов обрабатываемых за один раз
long sleepTime; // Время ожидания в цикле (мс)
long responseTime; // Время реакции в цикле (мс). Должно быть больше времени ожидания
long pointerDriverDAC; // Указатель драйвера на текущий элемент заполнения буфера драйвера
long pointerDriverDAC_old; // Предыдущее значение указателя драйвера на буфер драйвера
long pointerCycleDAC; // Указатель цикла обработки на текущий элемент заполнения буфера драйвера
double freqDAC; // Частота дискретизации ЦАП
double attenDAC0; // Коэф. затухания по первому каналу ЦАП
double resolutionDAC; // Вес младшего разряда ЦАП
double currentSinusTime; // Аргумент функции синус
double deltaSinusTime; // Значение инкремента аргумента функции синус
double volt0; // Мгновенное текущее значение, записываемое в ЦАП (код)
double amplitudeSin; // Коэф. преобразования амплитуды синуса
double freqSin; // Частота синуса (Гц)
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
OpenDevice();
}
//---------------------------------------------------------------------------
__fastcall TForm1::~TForm1(void)
{
CloseDevice();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
if(deviceError)
this->Close();
else
ProcessDevice();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OpenDevice(void)
{
long Err; // Код ошибки
long enable; // Поддерживается / не поддерживается
long i, size; // Счетчик цикла
sleepTime = 50; // Время ожидания в цикле генерации синуса (мс)
responseTime = 250; // Время опережения (время реакции) (мс)
amplitudeSin = 0.1; // Амплитуда синуса 100 мВ (СКЗ = 70.71 мВ)
freqSin = 10; // Частота синуса 10 Гц
attenDAC0 = 0.1; // Значение аттенюатора зададим 0.1 (для лучшего соотношения сигнал/шум)
numberDSP = 0; // Здесь задан первый порядковый номер устройства
deviceOpened = FALSE;
deviceError = FALSE;
deviceStarted = FALSE;
pBuffer16DAC = NULL;
pBuffer32DAC = NULL;
pointerDriverDAC = 0;
pointerDriverDAC_old = 0;
pointerCycleDAC = 0;
// Цикл подключения к первому поддерживаемому устройству
for(typeDevice=0; typeDevice < MAX_TYPE_DSP; typeDevice++)
{
// подключиться к драйверу (обязательно)
Err = ZOpen(typeDevice, numberDSP);
if(Err == 0)
{
// Проверить поддерживается ли ЦАП
Err = ZGetEnableDAC(typeDevice, numberDSP, &enable);
if(Err == 0 && enable != 0)
break;
else
Err = ZClose(typeDevice, numberDSP);
}
}
if(typeDevice >= MAX_TYPE_DSP)
{
MessageDlg("Поддерживаемое устройство не найдено!",
mtInformation, TMsgDlgButtons() << mbOK, 0);
deviceError = TRUE;
return;
}
deviceOpened = TRUE;
// включить первый канал ЦАП
Err = ZSetOutputDAC(typeDevice, numberDSP, 0, 1);
if(Err != 0)
{
MessageDlg("Ошибка в ZSetOutputDAC(), Error = " + IntToHex((int) Err,2),
mtError, TMsgDlgButtons() << mbOK, 0);
deviceError = TRUE;
return;
}
// опросить кол-во включенных каналов ЦАП
// Если включено каналов больше одного, то пример правильно работать не будет
// (синус будет выдаваться на все каналы, причем его реальная частота разделится
// на кол-во включенных каналов)
Err = ZGetNumberOutputDAC(typeDevice, numberDSP, &numChannelsDAC);
if(Err != 0)
{
MessageDlg("Ошибка в ZGetNumberOutputDAC(), Error = " + IntToHex((int) Err,2),
mtError, TMsgDlgButtons() << mbOK, 0);
deviceError = TRUE;
return;
}
// опросить вес младшего разряда ЦАП
Err = ZGetDigitalResolChanDAC(typeDevice, numberDSP, 0, &resolutionDAC);
if(Err != 0)
{
MessageDlg("Ошибка в ZGetDigitalResolChanDAC(), Error = " + IntToHex((int) Err,2),
mtError, TMsgDlgButtons() << mbOK, 0);
deviceError = TRUE;
return;
}
// опросить кол-во слов в одном отсчете ЦАП
Err = ZGetWordsDAC(typeDevice, numberDSP, &numWordsDAC);
if(Err != 0)
{
MessageDlg("Ошибка в ZGetWordsDAC(), Error = " + IntToHex((int) Err,2),
mtError, TMsgDlgButtons() << mbOK, 0);
deviceError = TRUE;
return;
}
// опросить частоту дискретизации ЦАП
Err = ZGetFreqDAC(typeDevice, numberDSP, &freqDAC);
if(Err != 0)
{
MessageDlg("Ошибка в ZGetFreqDAC(), Error = " + IntToHex((int) Err,2),
mtError, TMsgDlgButtons() << mbOK, 0);
deviceError = TRUE;
return;
}
// опросить размер буфера прерывания ЦАП
Err = ZGetInterruptDAC(typeDevice, numberDSP, &sizeInterruptBufferDAC);
if(Err != 0)
{
MessageDlg("Ошибка в ZGetInterruptDAC(), Error = " + IntToHex((int) Err,2),
mtError, TMsgDlgButtons() << mbOK, 0);
deviceError = TRUE;
return;
}
// Установить (опросить) коэф. затухания аттенюатора по первому каналу ЦАП
Err = ZSetAttenDAC(typeDevice, numberDSP, 0, attenDAC0, &attenDAC0);
if(Err != 0)
{
MessageDlg("Ошибка в ZSetAttenDAC(), Error = " + IntToHex((int) Err,2),
mtError, TMsgDlgButtons() << mbOK, 0);
deviceError = TRUE;
return;
}
// Проверка переменных, чтобы избежать деления на 0
if(numWordsDAC < 1 || numWordsDAC > 2 || freqDAC < 1. || attenDAC0 == 0. || resolutionDAC == 0.)
{
MessageDlg("Ошибочные значения параметров ЦАП!",
mtError, TMsgDlgButtons() << mbOK, 0);
deviceError = TRUE;
return;
}
// Запросить буфер ЦАП
Err = ZGetBufferDAC(typeDevice, numberDSP, (void**) &pBuffer16DAC, &sizeBufferDAC);
if(Err != 0)
{
MessageDlg("Ошибка в ZGetBufferDAC(), Error = " + IntToHex((int) Err,2),
mtError, TMsgDlgButtons() << mbOK, 0);
deviceError = TRUE;
return;
}
pBuffer32DAC = (long*) pBuffer16DAC;
// Вычислим размер пакета согласно заданному времени реакции (опережения)
sizePacketDAC = (long) freqDAC * responseTime / 1000;
sizePacketDAC = numWordsDAC*sizePacketDAC;
// Размер пакета должен быть не меньше двух размеров буфера прерывания и не больше половины буфера драйвера
if(sizePacketDAC < 2*sizeInterruptBufferDAC)
sizePacketDAC = 2*sizeInterruptBufferDAC;
if(sizePacketDAC > sizeBufferDAC / 2)
sizePacketDAC = sizeBufferDAC / 2;
// Рассчитаем параметры для генерации синуса
amplitudeSin = amplitudeSin / (resolutionDAC * attenDAC0);
deltaSinusTime = 2.*(4.*atan(1.))*freqSin / freqDAC; // Число Пи = 4.*atan(1.)
currentSinusTime = 0.;
// Запись в буфер драйвера первых двух пакетов
size = 2*sizePacketDAC / numWordsDAC;
if(numWordsDAC == 1)
for(i=0;i<size;i++)
{
volt0 = amplitudeSin * sin(currentSinusTime);
pBuffer16DAC[i] = (short) volt0;
currentSinusTime += deltaSinusTime;
}
else
for(i=0;i<size;i++)
{
volt0 = amplitudeSin * sin(currentSinusTime);
pBuffer32DAC[i] = (long) volt0;
currentSinusTime += deltaSinusTime;
}
pointerCycleDAC = 2*sizePacketDAC;
// Останов ЦАП
Err = ZStopDAC(typeDevice, numberDSP);
// Останов АЦП
Err = ZStopADC(typeDevice, numberDSP);
// Запуск ЦАП
Err = ZStartDAC(typeDevice, numberDSP);
// Запуск АЦП
Err = ZStartADC(typeDevice, numberDSP);
// Задать время ожидания таймера
this->Timer1->Interval = sleepTime;
deviceStarted = TRUE;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CloseDevice(void)
{
deviceStarted = FALSE;
if(!deviceOpened)
return;
// Останов ЦАП
ZStopDAC(typeDevice, numberDSP);
// Останов АЦП
ZStopADC(typeDevice, numberDSP);
// Освободить буфер ЦАП
if(pBuffer16DAC != NULL)
ZRemBufferDAC(typeDevice, numberDSP, (void**) &pBuffer16DAC);
// Отключиться от драйвера (обязательно)
ZClose(typeDevice, numberDSP);
pBuffer16DAC = NULL;
pBuffer32DAC = NULL;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ProcessDevice(void)
{
long Err; // Код ошибки
long i, size; // Счетчик цикла
// Если устройство еще не стартовали и переменные не проинициализированны, то выйти
if(!deviceStarted)
return;
Err = ZGetPointerDAC(typeDevice, numberDSP, &pointerDriverDAC);
if(Err != 0)
{
deviceError = TRUE;
return;
}
// Отобразить указатель цикла обработки на текущий элемент заполнения буфера драйвера
this->Edit1->Text = IntToStr(pointerCycleDAC);
// Отобразить указатель драйвера на текущий элемент заполнения буфера драйвера
this->Edit2->Text = IntToStr(pointerDriverDAC);
// Если опережение записи данных больше чем на один пакет, то перейти в начало цикла и подождать
if(pointerCycleDAC - pointerDriverDAC > sizePacketDAC)
return;
if((pointerDriverDAC > pointerCycleDAC) &&
(sizeBufferDAC - pointerDriverDAC + pointerCycleDAC > sizePacketDAC))
return;
// Обновить предыдущее значение указателя драйвера
pointerDriverDAC_old = pointerDriverDAC;
// Запись в буфер драйвера очередного пакета данных
size = sizePacketDAC;
// Если пакет выходит за границы буфера драйвера, то его нужно разделить на две части
if(pointerCycleDAC + sizePacketDAC > sizeBufferDAC)
size = sizeBufferDAC - pointerCycleDAC;
size = size / numWordsDAC;
if(numWordsDAC == 1)
for(i=0;i<size;i++)
{
volt0 = amplitudeSin * sin(currentSinusTime);
pBuffer16DAC[pointerCycleDAC + i] = (short) volt0;
currentSinusTime += deltaSinusTime;
}
else
for(i=0;i<size;i++)
{
volt0 = amplitudeSin * sin(currentSinusTime);
pBuffer32DAC[pointerCycleDAC/numWordsDAC + i] = (long) volt0;
currentSinusTime += deltaSinusTime;
}
// Передвинуть указатель на отсчет для следующей записи
pointerCycleDAC += numWordsDAC * size;
// Если подошли к концу буфера, то перейти в начало
if(pointerCycleDAC >= sizeBufferDAC)
pointerCycleDAC = 0;
if(size < (sizePacketDAC / numWordsDAC))
{
// Запись в буфер драйвера второй части пакета данных, если пакет пришлось разорвать
size = (sizePacketDAC / numWordsDAC) - size;
if(numWordsDAC == 1)
for(i=0;i<size;i++)
{
volt0 = amplitudeSin * sin(currentSinusTime);
pBuffer16DAC[pointerCycleDAC + i] = (short) volt0;
currentSinusTime += deltaSinusTime;
}
else
for(i=0;i<size;i++)
{
volt0 = amplitudeSin * sin(currentSinusTime);
pBuffer32DAC[pointerCycleDAC/numWordsDAC + i] = (long) volt0;
currentSinusTime += deltaSinusTime;
}
// Передвинуть указатель на отсчет для следующей записи
pointerCycleDAC += numWordsDAC * size;
}
}
//---------------------------------------------------------------------------