Книги, научные публикации Pages:     | 1 | 2 | 3 |

Ярославский государственный университет им. П.Г.Демидова На правах рукописи БАШМАКОВ МИХАИЛ ВЯЧЕСЛАВОВИЧ СТАТИСТИЧЕСКИЕ ХАРАКТЕРИСТИКИ ДИСКРЕТНЫХ СФС В УСЛОВИЯХ КОМБИНИРОВАННЫХ ВОЗДЕЙСТВИЙ ...

-- [ Страница 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 "..\common\plugmain.h" #define MODULE_VERSION "* SkipII, version 1.0.0 *" static int initcond = 0;

// способ установки начальных условий: // 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 |    Книги, научные публикации