
Ярославский государственный университет им. П.Г.Демидова На правах рукописи БАШМАКОВ МИХАИЛ ВЯЧЕСЛАВОВИЧ СТАТИСТИЧЕСКИЕ ХАРАКТЕРИСТИКИ ДИСКРЕТНЫХ СФС В УСЛОВИЯХ КОМБИНИРОВАННЫХ ВОЗДЕЙСТВИЙ ...
-- [ Страница 3 ] --} u1_t -= T1;
u2_t -= T2;
v1 -= dV1;
} return S;
} // вычисление ПРВ на следующем шаге в точке (u1,u2) double TModule::W_next(double u1, double u2) { double S = 0, S1 = 0, S2 = 0;
int i;
for(i = 2;
i < N;
i += 2) S1 += KW(u1, u2, i2u2(i));
for(i = 1;
i < N;
i += 2) S2 += KW(u1, u2, i2u2(i));
S = 2*KW(u1, u2, -M_PI);
// за счет периодичности первый и последний S += 2*S1 + 4*S2;
// совпадают, хотя этот вопрос до конца не ясен. S *= 2*M_PI/3 / N;
// пока оставим это на совесть точности счета. S *= qW;
// в случае чего, просто увеличим ее return S;
} TModule::makeNextW() { double u1, u2;
int result = 0;
// принудительная нормировка, // чтобы уменьшить влияние точности счета и утечки ПРВ if(normalize) donormalize();
make_rk();
// расчитать зависящие только от k величины - 196 for(int i2 = 0;
i2 < N;
i2++) { char s[32];
dllsprintf(s, "%.1f %%", (double)i2*100.0/N);
showMessage(s);
if( isEscPressed() ) { result = 1;
break;
} u2 = i2u2(i2);
for(int i1 = 0;
i1 < N1;
i1++) { u1 = i2u1(i1);
pW2next[i1+N1*i2] = W_next(u1, u2);
} } if( result == 0 ) // если не было отмены memcpy(pW2, pW2next, N1*N*sizeof(double));
// скопировать в основное место хранения showMessage("");
return result;
} // получение одномерной ПРВ из двухмерной // для простоты расчет ведется по правилу прямоугольника // i2 - соответствует u2, а т.к. u2=x1, то и x1 double TModule::W(int i2) { double S = 0;
for(int i = 0;
i < N1;
i++) S += pW2[i+N1*i2];
S *= 2*a/N1;
return S;
} // нормировка на 1 void TModule::donormalize() { int i, M = N1*N;
double S = 0;
for(i = 0;
i < M;
i++) S += pW2[i];
S *= 2*a*2*M_PI/M;
for(i = 0;
i < M;
i++) pW2[i] /= S;
} // расчет 1-мерной ПРВ из 2-х мерной ПРВ // т.к. x1=u2, то для получения W(x)=W(x1) достаточно // проинтегрировать W2(u1,u2) по u1 void TModule::calcPRV() { for(int i = 0;
i < N;
i++) pW[i] = W(i);
// вывести на экран характеристики ICalculate *pcalc = (ICalculate*)queryInterface(ID_ICalculate);
pcalc->getstatistics();
IShowInfo *pinfo = (IShowInfo*)queryInterface(ID_IShowInfo);
pinfo->showstatistics2();
pinfo->showstep();
} // значение пары (x1,x2) переводится в (u1,u2) - 197 // при этом (u1,u2) приводятся в первую полосу // (справедливо, если считать что помеха не действует, полезный сигнал не ЧМ) void TModule::x2u(double x1, double x2, double& u1, double& u2) { double nume = prm.gamma*x2 - cprm.myu*prm.d*prm.gamma + prm.K*prm.gamma*prm.gamma*sin(x1) - x1*(prm.gamma + prm.d*prm.gamma - prm.d);
double denu = prm.d*(prm.d-prm.gamma)*(1-prm.gamma);
if( denu ) u1 = nume/denu;
else u1 = 0;
// не должно встретиться, на всякий случай, чтобы не вылетала u2 = x1;
// приведение к первой полосе while(u2 >= M_PI) { u2 += T2;
// T2=-2pi u1 += T1;
} while(u2 < -M_PI) { u2 -= T2;
// T2=-2pi u1 -= T1;
} } // приближение дельта-функции гауссовым распределением // (a,b) - точка, для которой вычисляется вероятность double TModule::gauss_delta(double a, double b) { return 1.0/(2*M_PI*deltawidth) * exp( -(a*a + b*b)/(2*deltawidth) );
} // расчет величин, зависящих только от k // функция вызывается один раз на итерацию void TModule::make_rk() { double r;
// связано с ЧМ полезного сигнала /*r = prm.beta_m*( sin(2*prm.omega_m+modulat_phase) - (1+prm.d)*sin(prm.omega_m+modulat_phase) + prm.d*sin(modulat_phase) );
*/ r = prm.beta_m*( g_mod(2) - (1+prm.d)*g_mod(1) + prm.d*g_mod(0) );
/*r = prm.beta_m*( sin(prm.omega_m*(k_step+2)) - (1+prm.d)*sin(prm.omega_m*(k_step+1)) + prm.d*sin(prm.omega_m*k_step) );
*/ = r*prm.gamma/prm.d;
= r*prm.gamma*prm.gamma/(prm.gamma-prm.d)/(prm.gamma-1.0)/prm.d;
rk1 rk // переменная связана с ЧМ помехи (заодно и все остальное добавлено) dist_k = dist_phase + prm.beta_m1*sin(modulat_phase1) - prm.beta*sin(modulat_phase1);
// приводить к периоду (-pi,pi) не имеет смысла, т.к. количество итераций // невелико и точности синуса хватит dist_phase += prm.beta1;
dist_phase2 += prm.beta2;
modulat_phase = to2pi(modulat_phase+prm.omega_m);
modulat_phase1 += prm.omega_m1;
//k_step++;
// ЧТ-модуляция (обязательно после изменения modulat_phase) mod_FT[0] = mod_FT[1];
mod_FT[1] = mod_FT[2];
mod_FT[2] += (modulat_phase < 0 ? 1 :
-1);
} - 198 // закон модуляции, relative может принимать только // значения 0,1,2 (при других ЧТ даст не правильный результат) inline double TModule::g_mod(int relative) { switch( prm.mod_type ) { case MOD_FM: return sin(modulat_phase+prm.omega_m*relative);
case MOD_PT: /* [-pi,0) означает 1, [0,pi] означает -1 */ return to2pi(modulat_phase+prm.omega_m*relative) < 0 ? 1 :
-1;
case MOD_FT: return mod_FT[relative];
} return 0;
} // установка начальной 2-мерной ПРВ void TModule::cond_init() { double u1, u2;
int i, j, k;
dist_phase = prm.teta1;
dist_phase2 = prm.teta2;
modulat_phase = prm.teta_m;
modulat_phase1 = prm.teta_m1;
//k_step = 0;
// переменные для ЧТ (в отличие от других модулей, здесь рассматривается на шаг позже) mod_FT[0] = 0;
mod_FT[1] = (to2pi(modulat_phase+prm.omega_m) < 0 ? 1 :
-1);
mod_FT[2] = mod_FT[1]+(to2pi(modulat_phase+2*prm.omega_m) < 0 ? 1 :
-1);
// if( initcond==0 || nPoints<1 ) { // начальные условия, как у шахтарина /* начальные условия по шахтарину пока не реализованы */ } else if(initcond==3) { // равномерное по (u1,u2) for(i = 0;
i < N1;
i++) for(j = 0;
j < N;
j++) pW2[i+N1*j] = 1 / (2*a*2*M_PI);
// т.е. 1 разделить на площадь } else { /* начальные условия в виде набора гауссовых распределений */ for(i = 0;
i < N1;
i++) { u1 = i2u1(i);
for(j = 0;
j < N;
j++) { u2 = i2u2(j);
double dens = 0;
for(k = 0;
k < nPoints;
k++) { // свести несколько периодов по u2 в одну точку, чтобы // не было утечки. а также чтобы привести в полосу преобразованные // из (x1,x2) числа for(int v = -2;
v <= 2;
v++) dens += gauss_delta(u1-(aU[k].u1+T1*v), u2-(aU[k].u2+T2*v));
} pW2[i+N1*j] = dens/nPoints;
} } } } TModule *pmodule = 0;
void main_exec(TPluginMessage& msg) { switch(msg.msg_num) { - 199 case PMSG_Init: pmodule = new TModule;
if(!pmodule || pmodule->allocbuffers()) { msg.result = 2;
return;
} break;
delete pmodule;
pmodule = 0;
break;
case PMSG_Stop:
case PMSG_Precalc: pmodule->cond_init();
break;
case PMSG_NextW: if(pmodule->makeNextW()) { msg.result = 0;
return;
} break;
case PMSG_Calcprv: pmodule->calcPRV();
break;
case PMSG_Limit: { TPluginLimit *pl = (TPluginLimit*)msg.info;
pl->pW2 = pmodule->pW2;
pl->a_min = -pmodule->a;
pl->a_max = pmodule->a;
pl->b_min = -M_PI;
pl->b_max = M_PI;
pl->Na = pmodule->N1;
pl->Nb = pmodule->N;
pl->pW = pmodule->pW;
pl->x_min = -M_PI;
pl->x_max = M_PI;
pl->Nx = pmodule->N;
pl->color = WHITE;
pl->periodic = 1;
} break;
case PMSG_Version: msg.info = MODULE_VERSION;
break;
default: } msg.result = 1;
} return;
- 200 Приложение /***********************************************************/ /* Фрагмент программы вычисления среднего времени до срыва */ /* слежения в дискретной СФС 2-го порядка */ /* Автор: Башмаков М.В., 2000-2001 год */ /***********************************************************/ #include #include #include #include #include #include
// способ установки начальных условий: // 1-в виде (x1,x2) // 2-в виде (u1,u2) static double org10, org20;
// начальные условия static double N1_factor = 1;
// N*N1_factor - количество разбиений одного периода по горизонтали static int fOutput = 0;
// 0-рисовать (и сохранять) график среднего, // 1-момента 2-го порядка struct TPairU { double u1, u2;
};
static TPairU aU;
// пересчитанные значения (x1,x2) в (u1,u2)>
// int N1;
// количество разбиений по u1 double a;
// длина в одну сторону по u1 double *pD, *pDnext;
// указатели на массивы с текущим и следующим D(u1,u2) double *pM;
// среднее время до срыва в зависимости от u2 double i2u1_A, i2u1_B, i2u2_A, i2u2_B;
// для убыстрения i2u1 и i2u2 double u1toi_A, u1toi_B, u2toi_A, u2toi_B;
// для u1toi и u2toi double T1, T2;
// период по координате u1 и u2 // double qU1, qU2, qSIN, qC, qDIV, qQ;
double delta, delta1;
// шаг интегрирования double u02;
// стационарная точка // int k_step;
// номер текущей итерации double sum_skip;
// sum(i*d(i)) double sqr_skip;
// sum(i^2*d(i)) double sum_di;
// sum(d(i)) // // private methods void get_prm();
void free_prm();
void prepareConstants();
int allocbuffers();
void freebuffers();
// protected: double i2u1(int i) { return i2u1_A*i+i2u1_B;
} // перевод индекса в u1 double i2u2(int i) { return i2u2_A*i+i2u2_B;
} // перевод индекса в u2 int u1toi(double u1) { return u1toi_A*u1+u1toi_B;
} // u1 -> индекс - 201 int u2toi(double u2) { return u2toi_A*u2+u2toi_B;
} // u2 -> индекс2 void x2u(double x1, double x2, double& u1, double& u2);
double u2y2(double u1, double u2);
// преобразование (u1,u2) в y2, y1=u1 double Q(double v2, double u1, double u2);
double D_next(int i, int j);
double D0(int i, int j);
public: void cond_init();
void calcSkip();
makeNextD();
// 1-если отмена // public: TModule();
~TModule();
// };
TModule::TModule() { pD = pDnext = 0;
pM = 0;
get_prm();
prepareConstants();
} TModule::~TModule() { free_prm();
freebuffers();
} TModule::allocbuffers() { freebuffers();
pD = new double[N1*N];
pDnext = new double[N1*N];
pM = new double[N];
if( !pD || !pDnext || !pM ) { freebuffers();
return 1;
} return 0;
} void TModule::freebuffers() { delete[] pD;
delete[] pDnext;
delete[] pM;
pD = pDnext = 0;
pM = 0;
} // загрузка параметров модуля из ini-файла void TModule::get_prm() { IStore *pstore = getStore();
pstore->pushSubtitle("skipii.");
pstore->get("initcond", initcond);
pstore->get("n1_factor", N1_factor);
pstore->get("org10", org10);
pstore->get("org20", org20);
pstore->get("output", fOutput);
switch(initcond) { - 202 // набор (x1,x2) case 1: x2u(org10, org20, aU.u1, aU.u2);
break;
// набор (u1,u2) case 2: aU.u1 = org10;
aU.u2 = org20;
break;
} pstore->popSubtitle();
} // сохранение параметров модуля в ini-файле и освобождение ресурсов void TModule::free_prm() { IStore *pstore = getStore();
pstore->pushSubtitle("skipii.");
pstore->set("initcond", initcond);
pstore->set("n1_factor", N1_factor);
pstore->set("org10", org10);
pstore->set("org20", org20);
pstore->set("output", fOutput);
pstore->popSubtitle();
} // расчет различных констант void TModule::prepareConstants() { N1 = N*N1_factor;
//N*(1+2*N_Sk)*N1_factor;
T1 = 2*M_PI/(prm.gamma-prm.d);
T2 = -2*M_PI;
a = (0.5+N_Sk)*T1;
// delta1 = 2.0*a/N1;
delta = 4.0*M_PI/N;
u02 = asin(cprm.myu*prm.d / prm.K);
// точка равновесия // коэффициенты для пересчета индекса массив в числовое значение и обратно i2u1_A = 2.0*a/N1;
i2u1_B = -a;
i2u2_A = 4.0*M_PI/N;
i2u2_B = -2*M_PI + u02;
u1toi_A = N1/(2.0*a);
u1toi_B = N1/2.0;
u2toi_A = N/(4.0*M_PI);
u2toi_B = N/2.0 - N*u02/(4*M_PI);
// коэффициенты под знаком экспоненты qU1 = -prm.d*(prm.gamma - prm.d)*(prm.gamma - 1)/prm.gamma;
qU2 = -(1 + prm.d - prm.d/prm.gamma);
qSIN = prm.K*prm.gamma;
qC = -prm.d*cprm.myu;
// qDIV = -1/(2*cprm.sqr_c*prm.gamma*prm.gamma);
qQ = 1/sqrt(2*M_PI*cprm.sqr_c*prm.gamma*prm.gamma);
} // Вероятность перехода double TModule::Q(double v2, double u1, double u2) { return qQ*exp( qDIV * sqr(v2 + qU1*u1 + qU2*u2 + qSIN*sin(u2) + qC) );
} // Итерация для точки (u1,u2) // Соответствие аргументов: i->u1, j->u2 double TModule::D_next(int i, int j) { double u1 = i2u1(i), u2 = i2u2(j);
double v1 = prm.d/prm.gamma*u1 - u2/prm.gamma + cprm.myu;
int m = u1toi(v1);
- 203 if( m<0 || m>=N1 ) return 0;
double S = 0;
for( int k = 0;
k < N;
k++ ) S += Q(i2u2(k), u1, u2)*pD[m + N1*k];
S *= delta;
return S;
} // Распределение на первом шаге для точки (u1,u2) // Соответствие аргументов: i->u1, j->u2 double TModule::D0(int i, int j) { double u1 = i2u1(i), u2 = i2u2(j);
double S = 0;
for( int k = 0;
k < N;
k++ ) S += Q(i2u2(k), u1, u2);
S *= delta;
return 1 - S;
} TModule::makeNextD() { int result = 0;
for(int i2 = 0;
i2 < N;
i2++) { if( (i2 & 15) == 0 ) { char s[32];
dllsprintf(s, "%.1f %%", (double)i2*100.0/N);
showMessage(s);
if( isEscPressed() ) { result = 1;
break;
} } for(int i1 = 0;
i1 < N1;
i1++) pDnext[i1 + N1*i2] = D_next(i1, i2);
} if( result == 0 ) // если не было отмены memcpy(pD, pDnext, N1*N*sizeof(double));
// скопировать в основное место хранения showMessage("");
return result;
} // расчет среднего времени до срыва на текущей итерации void TModule::calcSkip() { // расчет статистики int i = u1toi(aU.u1), j = u2toi(aU.u2);
double Di = pD[i + N1*j];
sum_skip += k_step * Di;
sqr_skip += k_step*k_step * Di;
sum_di += Di;
// теперь тоже самое для массива for( j = 0;
j < N;
j++ ) { if( fOutput == 0 ) pM[j] += k_step * pD[i + N1*j];
else pM[j] += k_step * k_step * pD[i + N1*j];
} // вывести на экран характеристики ICalculate *pcalc = (ICalculate*)queryInterface(ID_ICalculate);
- 204 pcalc->setstatistics(sum_skip, sqr_skip - sum_skip*sum_skip, sum_di);
IShowInfo *pinfo = (IShowInfo*)queryInterface(ID_IShowInfo);
pinfo->showstatistics();
pinfo->showstatitem(3, "d(i)", Di);
// char s[32];
dllsprintf(s, "Step: %d", k_step);
pinfo->showstep(s);
// k_step++;
} // значение пары (x1,x2) переводится в (u1,u2) // при этом (u1,u2) приводятся в первую полосу void TModule::x2u(double x1, double x2, double& u1, double& u2) { double nume = prm.gamma*x2 - cprm.myu*prm.d*prm.gamma + prm.K*prm.gamma*prm.gamma*sin(x1) - x1*(prm.gamma + prm.d*prm.gamma - prm.d);
double denu = prm.d*(prm.d-prm.gamma)*(1-prm.gamma);
if( denu ) u1 = nume/denu;
else u1 = 0;
// не должно встретиться, на всякий случай, чтобы не вылетала u2 = x1;
// приведение к первой полосе while(u2 >= M_PI) { u2 += T2;
// T2=-2pi u1 += T1;
} while(u2 < -M_PI) { u2 -= T2;
// T2=-2pi u1 -= T1;
} } // установка начальных ПРВ void TModule::cond_init() { int i, j;
k_step = 1;
sum_skip = 0;
sqr_skip = 0;
sum_di = 0;
for( j = 0;
j < N;
j++ ) pM[j] = 0;
// распределение для первой итерации for( i = 0;
i < N1;
i++ ) for( j = 0;
j < N;
j++ ) pD[i + N1*j] = D0(i, j);
} TModule *pmodule = 0;
void main_exec(TPluginMessage& msg) { switch(msg.msg_num) { case PMSG_Init: pmodule = new TModule;
if( !pmodule || pmodule->allocbuffers() ) { msg.result = 2;
return;
} break;
- 205 case PMSG_Stop: delete pmodule;
pmodule = 0;
break;
case PMSG_Precalc: pmodule->cond_init();
break;
case PMSG_NextW: if(pmodule->makeNextD()) { msg.result = 0;
return;
} break;
case PMSG_Calcprv: pmodule->calcSkip();
break;
case PMSG_Limit: { TPluginLimit *pl = (TPluginLimit*)msg.info;
pl->pW2 = pmodule->pD;
pl->a_min = -pmodule->a;
pl->a_max = pmodule->a;
pl->b_min = -2*M_PI+pmodule->u02;
pl->b_max = 2*M_PI+pmodule->u02;
pl->Na = pmodule->N1;
pl->Nb = pmodule->N;
pl->pW = pmodule->pM;
pl->x_min = -2*M_PI+pmodule->u02;
pl->x_max = 2*M_PI+pmodule->u02;
pl->Nx = pmodule->N;
pl->color = LIGHTGREEN;
pl->periodic = 0;
} break;
case PMSG_Version: msg.info = MODULE_VERSION;
break;
default: } msg.result = 1;
} return;
- 206 Приложение Фрагмент управляющей программы для ЦСП ADSPЦ2181, реализующей цифровую СФС 1Цго или 2Цго порядков с квадратурным фазовым детектором.
start: dis ints;
mstat = b#1010000;
call init_codec;
call stack_init;
m5 m7 m1 m0 m3 = = = = = 1;
0;
1;
0;
-1;
i7 = 0x3fe8;
l7 = 0;
ar = pm(i7, m5);
i7 = 0x28;
pm(i7, m5) = ar;
call define_control;
call init_proc;
ifc = b#00000011111111;
nop;
imask = WORK_IMASK;
ena ints;
{ инициализация пользовательских данных } { сбросить ожидающие прерывания } mainloop: idle;
call showMode;
check_var(CHAR_WAITING_FLAG);
if eq call onControlData;
{ проверка команды от компьютера } check_var(fTransfering);
{ переход к передачи следующего байта } if ne call onTransfering;
check_var(fStoreDone);
if ne call onSendArray;
{ передача массива } check_var(fQuit);
{ выход в монитор } if eq jump mainloop;
{ выход в монитор } ax1 = dm(fQuit);
call putByte;
{ подтвердить выход в монитор } imask = WAIT_IMASK;
jump waitTransfer;
{ обработчик прерывания поступления новых отчетов } onNewSample: ena sec_reg;
{ извлечение пришедших данных и помещение новых } ax0 = dm(out_left);
- 207 dm(tx_buf+1) = ax0;
ax0 = dm(out_right);
dm(tx_buf+2) = ax0;
check_var(f_int_oscil);
{ искусственное формирование сигнала? } if ne jump int_oscillator;
ena ar_sat;
ax0 = dm(rx_buf+1);
{ левый канал } ay1 = dm(prm_ldrift);
{ компенсациа дрейфа нула } ar = ax0 - ay1;
dm(in_left) = ar;
ax0 = dm(rx_buf+2);
{ правый канал } ay1 = dm(prm_rdrift);
ar = ax0 - ay1;
dm(in_right) = ar;
dis ar_sat;
check_var(f_use_sqrs);
if ne jump SqrMaker;
onNewSample1: rti;
call main_process;
{ вызов главной процедуры обработки } { внутренний генератор квадратур } int_oscillator: add_vars(in_seq, prm_div_oscil);
add_vars(mod_seq, prm_mod_div_oscil);
{ фаза модулирующей функции } ax1 = dm(mod_seq);
call sin;
my0 = 20861;
{ 20861=(2^16)/pi } mr = ar * my0(SS);
ax1 = mr1;
prop_mult(prm_mod_beta, num_100);
dm(cur_mod_func) = ay0;
{ beta*sin(omega*k) } ar = dm(in_seq);
ay1 = dm(cur_mod_func);
ar = ar + ay1;
ax1 = ar;
call sin;
dm(in_left) = ar;
call cos;
dm(in_right) = ar;
jump onNewSample1;
{ формирование квадратур } SqrMaker: dis m_mode;
{ включить fractional режим MAC } add_vars(sqr_phase, sqr_phase_add);
{ фаза сигнала подставки } ax1 = dm(sqr_phase);
call sin;
my0 = dm(in_left);
mr = ar*my0(SS);
dm(s_sqr) = mr1;
call cos;
my0 = dm(in_left);
mr = ar*my0(SS);
- 208 dm(c_sqr) = mr1;
i7 = ^fir_coefs;
l7 = %fir_coefs;
l2 = FIR_LEVEL;
{ фильтрация S-канала } i2 = dm(s_ptr);
ar = dm(s_sqr);
dm(i2,m1) = ar;
dm(s_ptr) = i2;
mr = 0, my0 = pm(i7,m5), mx0 = dm(i2,m1);
cntr = FIR_LEVEL-1;
do s_fir until ce;
mr = mr + mx0*my0(SS), my0 = pm(i7,m5), mx0 = dm(i2,m1);
mr = mr + mx0*my0(RND);
if mv sat mr;
mx0 = mr1;
my0 = -1;
mr = mx0*my0(SS);
dm(in_left) = mr0;
{ фильтрация С-канала } i2 = dm(c_ptr);
ar = dm(c_sqr);
dm(i2,m1) = ar;
dm(c_ptr) = i2;
mr = 0, my0 = pm(i7,m5), mx0 = dm(i2,m1);
cntr = FIR_LEVEL-1;
do c_fir until ce;
mr = mr + mx0*my0(SS), my0 = pm(i7,m5), mx0 = dm(i2,m1);
mr = mr + mx0*my0(RND);
if mv sat mr;
mx0 = mr1;
my0 = 1;
{За счет fractional mode идет умножение на 2} mr = mx0*my0(SS);
dm(in_right) = mr0;
ena m_mode;
{ включить integer режим MAC } jump onNewSample1;
s_fir:
c_fir:
{ обработка нажатия кнопки IRQE } onIRQE: ar = dm(f_demodul);
ar = ar xor 1;
dm(f_demodul) = ar;
call showMode;
rti;
{ обработка принятых с компьютера команд } onControlData: call getByte;
check_var(fArgExpect);
if ne jump onGetParam;
ay1 = CMD_SETARGUMENT;
ar = ax1 and ay1;
{ проверка на команду установки аргумента } - 209 if ne jump onExpectParam;
ay1 = CMD_GETPARAMS;
{ команда отправить текущие параметры } ar = ax1 - ay1;
if eq jump sendParams;
ay1 = CMD_SETPARAMS;
{ команда установить новые параметры } ar = ax1 - ay1;
if eq jump setParams;
ay1 = 0x40;
ar = ax1 - ay1;
{ проверить диапазон кода команды: 0x40-0x7F} if lt jump uc_error;
none = ar - ay1;
if ge jump uc_error;
ay1 = ^user_com;
ar = ar + ay1;
i4 = ar;
l4 = 0;
ay1 = pm(i4, m5);
i4 = ay1;
jump (i4);
{ определить адрес команды из таблицы по коду } { переход на процедуру пользователя или uc_error } onExpectParam: ay1 = CMD_SETARGUMENT-1;
ar = ax1 and ay1;
{ теперь в ar номер аргумента } ax1 = ar;
ay1 = MAX_ARGUMENTS;
{ сравнить на допустимые пределы } ar = ax1 - ay1;
if ge rts;
dm(nArgExpect) = ax1;
ay1 = 2;
dm(fArgExpect) = ay1;
rts;
{ установить признак ожидания двух байт } onGetParam: ar = dm(nArgExpect);
ay1 = ^arguments;
ar = ar + ay1;
i1 = ar;
l1 = 0;
dec_var(fArgExpect);
if eq jump second_byte;
dm(i1, m0) = ax1;
rts;
{ адрес ячейки с параметром } second_byte: ar = dm(i1, m0);
sr = lshift ar by 8(lo);
ay1 = 0xff;
ar = ax1 and ay1;
ay1 = ar;
ar = sr0 or ay1;
dm(i1, m0) = ar;
rts;
- 210 { отправление компьютеру текущих параметров } sendParams: ax1 = RECEIVED_PARAMS;
call putByte;
ax1 = PARAM_COUNT;
call putWord;
i1 = ^prm_s1;
l1 = 0;
cntr = PARAM_COUNT;
do sendParams1 until ce;
ax1 = dm(i1, m1);
call putWord;
sendParams1: nop;
rts;
{ установка принятых с компьютера параметров } setParams: l1 = 0;
ax0 = ^prm_s1;
ax1 = ^arguments;
cntr = PARAM_COUNT;
do setParams1 until ce;
i1 = ax1;
ar = dm(i1,m1);
ax1 = i1;
i1 = ax0;
dm(i1,m1) = ar;
setParams1: ax0 = i1;
{ проверка размеров массива } check_var(prm_arraysize);
if eq jump setParams3;
{ нулевой размер } cmp_var(prm_arraysize, ARRAY_SIZE);
if not ac jump setParams2;
set_var(prm_arraysize, ARRAY_SIZE);
jump setParams2;
setParams3: set_var(prm_arraysize, 1);
setParams2: call param_update;
ax1 = ACCEPT_PARAMS;
jump putByte;
{ передача ожидающих своей очереди байтов на компьютер } onTransfering: check_var(CHAR_SEND_DONE_FLAG);
if eq rts;
stack_push4(ax0, ax1, sr0, sr1);
push_imask;
imask = WAIT_IMASK;
trans3: i4 = dm(pctrl_read);
{ считать указатель на текущий символ в буфере } l4 = %control_buf;
ax1 = dm(i4, m5);
dm(pctrl_read) = i4;
- 211 cmp_var(pctrl_write, i4);
{ проверить окончание отложенных символов } if ne jump trans1;
dm(fTransfering) = m7;
{ m7=0 } trans1: i4 = dm(PTR_TO_OUT_CHAR);
call (i4);
check_var(CHAR_SEND_DONE_FLAG);
{ дождаться окончания передачи } if eq jump trans2;
check_var(fTransfering);
if ne jump trans3;
{ передать весь буфер } trans2:
pop_imask;
stack_pop4(ax0, ax1, sr0, sr1);
rts;
{ дождаться физического окончания передачи на компьютер команд, при этом прекратить обработку отсчетов } waitTransfer: check_var(fTransfering);
{ дождаться окончания передачи } if eq jump waitTransfer2;
call onTransfering;
jump waitTransfer;
waitTransfer2: check_var(CHAR_SEND_DONE_FLAG);
if eq jump waitTransfer2;
rts;
{ передача пользователю массива, обработка отсчетов временно прекращена } onSendArray: push_imask;
imask = WAIT_IMASK;
ax1 = dm(fStoreDone);
call putByte;
ax1 = dm(prm_arraysize);
call putWord;
{ отправка данных } af = pass 0;
{ будет содержать контрольную сумму } i1 = ^array;
l1 = 0;
cntr = dm(prm_arraysize);
do sendArray2 until ce;
ax1 = dm(i1, m1);
call putWord;
sendArray2: af = ax1 + af;
{ контрольная сумма } ar = pass af;
ax1 = ar;
call putWord;
dm(fStoreDone) = m7;
dm(fStore) = m7;
{ разрешить вновь набирать массивы } pop_imask;
rts;
- 212 { режим работы: демодуляция или повторение сигнала с АЦП } showMode: check_var(f_demodul);
if ne set fl1;
{ зажечь светодиод } if eq reset fl1;
{ потушить } rts;
{ получение пришедшего байта, выходные данные: ax1 } getByte: stack_push(ax0);
i4 = dm(PTR_TO_GET_CHAR);
call (i4);
if ge jump getByte1;
ax1 = 0;
{ если был timeout, возвратить 0 } getByte1: stack_pop(ax0);
rts;
{ отправление байта из ax1 (8 бит) } putByte: stack_push(ax0);
i4 = dm(pctrl_write);
modify(i4, m5);
cmp_var(pctrl_read, i4);
if ne jump putbyte_2;
ax0 = i4;
{ i4 портится в onTransfering } putbyte_1: call onTransfering;
cmp_var(pctrl_read, ax0);
{ ожидать отправления одного символа } if eq jump putbyte_1;
putbyte_2: i4 = dm(pctrl_write);
l4 = %control_buf;
dm(i4, m5) = ax1;
dm(pctrl_write) = i4;
dm(fTransfering) = m5;
{ m5=1 } stack_pop(ax0);
rts;
{ отправление слова из ax1 } putWord: stack_push3(sr0, sr1, ax1);
sr0 = ax1;
sr = lshift sr0 by 8(lo);
ax1 = sr1;
call putByte;
stack_pop3(sr0, sr1, ax1);
call putByte;
rts;
{ отправление двойного слова из ax1 } putWideWord: stack_push2(sr0, sr1);
ar = ax1;
- 213 sr = ashift ar by -16(hi);
ax1 = sr1;
call putWord;
ax1 = sr0;
call putWord;
stack_pop2(sr0, sr1);
rts;
{ теперь sr1 содержит знаковый бит } { отправление двойного слова из ax1:ax0 } putDWord: stack_push(ax1);
call putWord;
ax1 = ax0;
call putWord;
stack_pop(ax1);
rts;
{ установка пользовательских подпрограмм }.macro set_command(%0,%1);
{ параметры: код команды, адрес процедуры} i4 = ^user_com - 0x40 + %0;
ay1 = ^%1;
pm(i4, m5) = ay1;
.endmacro;
define_control: i4 = ^user_com;
{ заполнить таблицу команд по умолчанию } l4 = 0;
ay1 = ^uc_error;
cntr = %user_com;
do zero_control1 until ce;
zero_control1: pm(i4, m5) = ay1;
set_command(0x74, uc_test);
{ проверка соединениа 't'} set_command(0x7a, uc_quit);
{ выход в монитор 'z' } set_command(0x61, uc_average);
{ средние значениа 'a' } set_command(0x76, uc_variance);
{ дисперсиа 'v' } set_command(0x70, uc_npoints);
{ количество обработанных точек 'p' } set_command(0x65, uc_errorstat);
{ статистика фазовой ошибки 'e' } set_command(0x73, uc_somenumber);
{ некоторое число 's' } set_command(0x78, uc_storephase);
{ массив с фазой 'x' } set_command(0x6C, uc_storeleft);
{ массив с левого канала 'l' } set_command(0x72, uc_storeright);
{ массив с правого канала 'r' } set_command(0x66, uc_storefilter);
{ набрать массив с фильтра 'f' } set_command(0x64, uc_probability);
{ формирование ПРВ ошибки '' } set_command(0x68, uc_storeboth);
{ отчеты лев. и прав. каналов 'h' } set_command(0x6f, uc_filterprob);
{ ПРВ с выхода ФНЧ 'o' } rts;
{ вставка отсчета из ax1 в массив } store_sample: dm(i0,m1) = ax1;
ay1 = ^array;
ar = i0;
ar = ar - ay1;
- 214 ay1 = dm(prm_arraysize);
ar = ar - ay1;
if ne rts;
{ еще не набран до конца } ay1 = ARRAY_SIGNED;
{ отсчеты - знаковые величины } dm(fStoreDone) = ay1;
dm(fStore) = m3;
rts;
{ обработка отсчета из ax1 для определения ПРВ } store_probabil: ar = ax1 + 0x8000;
{ чтобы получить беззнаковое число} my0 = ar;
mx0 = dm(prm_arraysize);
mr = mx0*my0(UU);
{ теперь в mr1 индекс элемента массива } ay1 = ^array;
ar = mr1 + ay1;
i0 = ar;
ar = dm(i0, m0);
ar = ar + 1;
if ne jump no_probover;
ar = 65535;
no_probover: dm(i0, m0) = ar;
inc_var(probabil_seq);
if ne rts;
{ расчет закончен } dm(fStore) = m3;
ay1 = ARRAY_UNSIGNED;
dm(fStoreDone) = ay1;
rts;
{ увеличить число попаданий в интервал } { процедура инициализации, вызывается перед запуском основного цикла } init_proc: prepare_stat(stat_left);
prepare_stat(stat_right);
prepare_stat(stat_error);
param_update: copy_var(delay_prev, prm_prevdelay);
copy_var(prev_sum_value, prm_prevfilter);
check_var(f_int_oscil);
if ne rts;
dm(in_seq) = m7;
rts;
{ основная процедура обработки сигнала } main_process: check_var(fWaitSignal);
if eq jump nowait_signal;
{ проверка наличия сигнала на входе } wait_signal: ax1 = dm(in_left);
ar = abs ax1;
ay1 = dm(prm_gesteresis);
ar = ax1 - ay1;
- 215 if lt rts;
dm(fWaitSignal) = m7;
{ сбор статистической информации о входных отчетах } nowait_signal: ax1 = dm(in_left);
add_stat(stat_left);
ax1 = dm(in_right);
add_stat(stat_right);
inc_var(n_cur);
if ne jump skip_avg1;
{ количество обработанных точек } { статистика набрана, рассчитать соответствующие величины } inc_var(n_cur_times);
{ число переполнений n_cur } { рассчитать дисперсию и среднее } calc_stat(stat_left);
calc_stat(stat_right);
skip_avg1: cmp_var(fStore, STORE_LEFT);
ax1 = dm(in_left);
if eq call store_sample;
cmp_var(fStore, STORE_RIGHT);
ax1 = dm(in_right);
if eq call store_sample;
cmp_var(fStore, STORE_BOTH);
if ne jump skip_store;
ax1 = dm(in_left);
call store_sample;
ax1 = dm(in_right);
call store_sample;
skip_store: check_var(f_demodul);
if ne jump demodulator;
copy_var(out_left, in_left);
copy_var(out_right, in_right);
rts;
{ копировать со входа на выход } { набирать массив } { непосредственно обработка сигнала (демодуляция) } demodulator: ax1 = dm(delay_prev);
call sin;
{ выход функционального преобразователя 2 } my0 = dm(in_right);
mr = ar*my0(SS);
ay0 = mr1;
dm(mult2) = ay0;
{ выход перемножителя 2 } ax1 = dm(delay_prev);
{ хота ax1 и не должно измениться } call cos;
{ выход функционального преобразователя 1 } my0 = dm(in_left);
mr = ar*my0(SS);
dm(mult1) = mr1;
{ выход перемножителя 1 } ar = mr1 - ay0;
- 216 dm(phase_error) = ar;
dm(demodulated) = ar;
{ фазовая ошибка } ax1 = ar;
{ умножим на S = S1/S2 } prop_mult(prm_s1, prm_s2);
{ результат макроса в ay0 } dm(before_filter) = ay0;
dm(filter_output) = ay0;
{ фильтр в цепи управлениа } check_var(f_usefilter);
if eq jump skip_filter;
ax1 = dm(before_filter);
prop_mult(prm_m1, prm_m2);
{ умножение на M1/M2 } ax1 = dm(prev_sum_value);
ar = ax1 + ay0;
dm(filter_output) = ar;
dm(demodulated) = ar;
ay0 = dm(before_filter);
ar = ax1 + ay0;
dm(prev_sum_value) = ar;
{ накопление в сумматоре фильтра } skip_filter: ar = dm(delay_prev);
ay0 = dm(filter_output);
ar = ar + ay0;
dm(delay_prev) = ar;
{ накопление в сум. "ЧАСТОТА-ФАЗА" } { отправить сигнал на ЦАП } ar = dm(demodulated);
my0 = dm(prm_normalize);
mr = ar*my0(SS);
{ нормировка дла увеличениа громкости } dm(out_left) = mr0;
{ моно-звучание } dm(out_right) = mr0;
{ сохранить ошибку в массиве } ax1 = dm(phase_error);
cmp_var(fStore, STORE_PHASE);
if eq call store_sample;
cmp_var(fStore, STORE_PROBABILITY);
if eq call store_probabil;
ax1 = dm(filter_output);
cmp_var(fStore, STORE_FILTER);
if eq call store_sample;
cmp_var(fStore, STORE_FILTERPROB);
if eq call store_probabil;
{ набрать статистику } ax1 = dm(demodulated);
check_var(f_stat_filter);
if ne jump make_stat;
ax1 = dm(phase_error);
make_stat: add_stat(stat_error);
check_var(n_cur);
if ne rts;
{ если не до конца набрана, выход } calc_stat(stat_error);
rts;
Pages: | 1 | 2 | 3 |
Книги, научные публикации