Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: SED1335,PIC18F4550 и LCD320x240
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Все остальные микроконтроллеры > PIC
Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9
Ilya_A
Цитата
if( xx >= 255 ) xx = xx - 255; //приводим к int8
тут , как я себе представляю, смысл в том, чтобы хх укладывалось в интервал от 0 до 255, так как сам буфер в 4 раза больше. хх- это координата точки и поскольку момент захвата синхронизации может наступить за пределами этого диапазона, то эта конструкция всё равно установит этот момент в начало.
потому что в цикле начала отрисовки for(x=1;x<255;x++){
лежит другая переменная.

Хоть убейте не догоняю хода вашей мысли.... Зачем xx укладываться от 0 до 255? она же int16, да и буффер размером 1024 байта... Если мы нашли точку синхронизации - надо от нее и рисовать, зачем же ее изменять???

Ну ладно допустим вы хотите чтобы xx лежал от 0 до 255, то все равно ваша конструкция ошибочна: ведь если xx будет больше 512 или 768 то отняв 256 вы не получите требуемого диапазона!

Цитата(andreichk @ Mar 21 2008, 03:53) *
кстати вопрос имею- чем два раза IF лучше одного SWITCH?
это я про синхронизацию

В данном случае разницы нет, но я специально так написал, чтобы затем предложить вам переобозначить значение переменной типа синхронизации (syncA), пусть
SyncA=1 синхронизация по фронту
SyncA=0 синхронизация по спаду

тогда проверку можно будет переписать так:
Код
      if (syncA){
         if(adcA>sync_volume_A) continue;
         else break;
      }else{
         if(adcA<=sync_volume_A+115) continue;
         else break;
      }

А это уже экономия на одной лишней проверке. если учесть что эта операция выполняется на каждой итерации цилкла - получится приличное чилсло тактов процессора.

Цитата
ЗЫ.попробовал ваш код- он работает, но если нет сигнала, то на экране не прорисовывается прямая, как в обычном осциллографе.Как-то не привычно, создаётся впечатление, что что-то не работает.

А в вашем коде она прорисовывалась?

Предлагаю сделать так: Завести переменную, котороая будет зануляться перед каждой попыткой синхронизации, и затем инкрементироваться в цикле. А при превышении n-го количества попыток, тупо отрисовывала текущий сигнал и выходила из цикла.

Следовательно код будет такой:

Код
//!!!SyncA=1  синхронизация по фронту!!!
//!!!SyncA=0  синхронизация по спаду!!!

void curve_A(unsigned int8 y_pos_A); //добавить функцию в прототипы

#define TIMEOUT             10000

void pix_A(unsigned int8 y_pos_A) // рисуем кривую, типа синусоиды и пр.
{  unsigned int16 n=0;
   Output_bit(PLCD_FIFO_RES ,0); //PIN_C0// сброс FIFO в "0"
   Output_bit(PLCD_FIFO_RES ,1); //PIN_C0// и разрешение на считывание
   Output_bit(READ_FIFO_B ,1); //PIN_C1 запрет канала B
   // слабая попытка синхронизации
   do{ Output_bit(READ_FIFO_A ,0);//PIN_C2
      adcA=input_b();
      Output_bit(READ_FIFO_A ,1);//PIN_C2
      if (n++>TIMEOUT) {curve_A(y_pos_A); return;}
   }while( adcA == 0);
   n=0;
   do{ // ещё одна попытка синхронизации
      Output_bit(READ_FIFO_A ,0);//PIN_C2
      adcA=input_b();
      Output_bit(READ_FIFO_A ,1); //PIN_C2
      if (n++>TIMEOUT) {curve_A(y_pos_A); return;}
   }while(input_b()== adcA ); //уже лучше,но всё равно плохо
   //-------------------- синхронизация ---------------------------
   n=0;
   while(1){
      Output_bit(READ_FIFO_A ,0); //PIN_C2. разрешить
      adcA=input_b(); //чтение порта В
      Output_bit(READ_FIFO_A ,1); //PIN_C2.запретить
      adcA = (adcA > 200) ? 200 : adcA; //ограничитель до выбранной величины
      adcA = 255 - adcA; // разворот на 180° по вертикали
      if (n++>TIMEOUT) {curve_A(y_pos_A); return;}
      if (syncA){
         if(adcA>sync_volume_A) continue;
         else break;
      }else{
         if(adcA<=sync_volume_A+115) continue;
         else break;
      }
    }
    curve_A(y_pos_A);
}

//--------------- собственно кривая ---------------------------
void curve_A(unsigned int8 y_pos_A){
   unsigned int8 x, y , yy;
   for(x=1;x<255;x++){
      yy = y;
      Output_bit(READ_FIFO_A ,0); //PIN_C2. разрешить
      adcA=input_b(); //чтение порта В
      Output_bit(READ_FIFO_A ,1); //PIN_C2.запретить
      adcA = (adcA > 200) ? 200 : adcA; //ограничитель до выбранной величины
      y = (255 - adcA) + y_pos_A; // разворот на 180° по вертикали и сдвиг
      if (yy>y) front(x,yy,y); // Рисуем фронт A
      if (yy<y) spad(x,yy,y); // Рисуем спад A
      pixel(x,y,1); // Рисуем вершину A
   }
}


значение TIMEOUT нужно определить опытным путем (я написал для примера) а можно и завести и глобальную переменную под это дело - дабы динамически изменять во время работы
andreichk
вначале буфер был размером в 512 кб и всё как раз там укладывалось,а сделано это было для того, чтобы момент синхронизации попадал в диапазон от 0 до 255, если он наступал за его пределом(экран-то размером 255 пикс. по горизонтали).Это потом я увеличил буфер(сам не знаю зачем)

ОК, последний предложенный код работает, синхронизация в норме, при отстутствии сигнала рисуется прямая линия с мелкими шумовыми вкраплениями.Думаю, что этот момент завершён. Спасибо за помощь
Ilya_A
Цитата(andreichk @ Mar 21 2008, 19:25) *
ОК, последний предложенный код работает, синхронизация в норме, при отстутствии сигнала рисуется прямая линия с мелкими шумовыми вкраплениями.Думаю, что этот момент завершён. Спасибо за помощь


Вери Гуд wink.gif

Удаленная отладка - конечно прикольная вещь, но жутко интересно посмотреть как ваше устройство работает в живую... жаль что не увижу sad.gif

Сам всегда мечтал сделать свой осциллограф - поэтому и заинтересовался вашим постом, но никто не предлагает такой задачи... а заниматься этим от нечего делать - нету времени sad.gif
andreichk
не вопрос- научусь в Гугль видео выкладывать- обязательно сделаю, так что увидите. Тут есть ещё чего поотлаживать, напр. запихнуть сетку в ЕЕПРОМ и при включении рисовать её на экран оттуда.Можно будет ещё 10кб меса сэкономить.Есть желание дальше копаться?
В перспективе можно будет ещё спектроанализатор поизобретать, да мало ли чего......
Ilya_A
Цитата(andreichk @ Mar 21 2008, 21:55) *
Тут есть ещё чего поотлаживать, напр. запихнуть сетку в ЕЕПРОМ и при включении рисовать её на экран оттуда.


Непонял, а что сложного в векторном рисовании сетки? (с помощю линий)
Зачем ее по пикселам из памяти считывать?
andreichk
я про такое даже не слышал, поэтому просто нарисовал сетку в бмп-формате, разложил на байты и загрузил в проц.Места она заняла ок.10кб, вот я и подумал, что может её в еепром затолкать?
Ilya_A
Цитата(andreichk @ Mar 22 2008, 08:59) *
я про такое даже не слышал, поэтому просто нарисовал сетку в бмп-формате, разложил на байты и загрузил в проц.Места она заняла ок.10кб, вот я и подумал, что может её в еепром затолкать?


Еще раз посмотрел на вашу сетку - в принципе немного попариться и можно нарисовать векторно.
Насколько я понял линии вы рисовать умеете (нет ничего сложного) написать еще алгоритм рисования пунктирных линий с задаваемым шагом пунктира. И все, сетку спокойно можно будет собрать из этих процедур wink.gif

А по поводу иконок - речи нет надо битмапы юзать
andreichk
линии, прямоугольники и кружки рисовать умеем, а штрихпунктиры нет.Даже не представляю себе такие формулы
andreichk
прямоугольник и видеосигнал
Ilya_A
Цитата
линии, прямоугольники и кружки рисовать умеем, а штрихпунктиры нет.Даже не представляю себе такие формулы


Я сам лично никогда не задавался вопросом рисования пунктирных линий, щас подумал - алгоритм мне представился довольно простым, если есть желание - выкладывайте вашу процедуру для обычных линий, видоизменим под пунктир... wink.gif

Цитата
прямоугольник и видеосигнал

Да, картинка красивая... единственно не понятен смысл значка в правом нижнем углу... на нем что вообще нарисовано? (похоже на ворону на камне smile.gif )
andreichk
Цитата(Илья @ Mar 22 2008, 14:53) *
Я сам лично никогда не задавался вопросом рисования пунктирных линий, щас подумал - алгоритм мне представился довольно простым, если есть желание - выкладывайте вашу процедуру для обычных линий, видоизменим под пунктир... wink.gif
Да, картинка красивая... единственно не понятен смысл значка в правом нижнем углу... на нем что вообще нарисовано? (похоже на ворону на камне smile.gif )


ворона на камне lol.gif да ето же бонсай, для души beer.gif

Цитата
void line(int16 x1, int16 y1, int16 x2, int16 y2, int1 color)

{
int16 dy, dx;
signed int8 addx=1, addy=1;
signed int16 P, diff;


int16 i=0;
dx = abs((signed int16)(x2 - x1));
dy = abs((signed int16)(y2 - y1));


if(x1 > x2)
addx = -1;
if(y1 > y2)
addy = -1;

if(dx >= dy)
{
dy *= 2;
P = dy - dx;
diff = P - dx;

for(; i<=dx; ++i)
{
pixel(x1, y1, color);

if(P < 0)
{
P += dy;
x1 += addx;
}
else
{
P += diff;
x1 += addx;
y1 += addy;
}
}
}
else
{
dx *= 2;
P = dx - dy;
diff = P - dy;

for(; i<=dy; ++i)
{
pixel(x1, y1, color);

if(P < 0)
{
P += dx;
y1 += addy;
}
else
{
P += diff;
x1 += addx;
y1 += addy;
}
}
}
}//--------------------------OK
//####################################################
Шпиндель
Посмотрел с интересом, спасибо! Через время.. чувствую, придётся мне делать нечто подобное, вот я тогда за вами побегаю.. wink.gif
Сейчас появляются всевозможные матрицы по ценам до 50 долларов, так что многие задачи для хобби и для работы становятся оправданными.
alexsl
to andreichk.
Добрый день. Уменя вопрос по схемотехнике. Чем вы подсветку питали? У вас ведь CCFL подсветка?
Ilya_A
Вот, собственно, у меня получилась такая процедурка:

Код
/*
входные параметры:
color - с чего начинать (1- с пунктира, 0 -с промежутка)
Len1 - длина пунктира (в пикселах)
Len0 - длина промежутка (в пикселах)
*/
void pline(int16 x1, int16 y1, int16 x2, int16 y2, int1 color, int8 Len1, in8 Len0){
int16 dy, dx;
signed int8 addx=1, addy=1;
signed int16 P, diff;
int16 i=0;
int8 count=0;

dx = abs((signed int16)(x2 - x1));
dy = abs((signed int16)(y2 - y1));
if(x1 > x2) addx = -1;
if(y1 > y2) addy = -1;
if(dx >= dy){
   dy *= 2;
   P = dy - dx;
   diff = P - dx;
   for(; i<=dx; ++i){
      pixel(x1, y1, color);
      if(color){
          if (++count>=Len1) {count=0;color=0;}
      }else{
          if (++count>=Len0) {count=0;color=1;}
      }
      if(P < 0){
         P += dy;
         x1 += addx;
      }else{
         P += diff;
         x1 += addx;
         y1 += addy;
      }
   }
}else{
   dx *= 2;
   P = dx - dy;
   diff = P - dy;
   for(; i<=dy; ++i){
      pixel(x1, y1, color);
      if(color){
          if (++count>=Len1) {count=0;color=0;}
      }else{
          if (++count>=Len0) {count=0;color=1;}
      }
      if(P < 0){
         P += dx;
         y1 += addy;
      }else{
         P += diff;
         x1 += addx;
         y1 += addy;
      }
   }
}
}


В принципе переменную count можно тоже вынести в список входных параметров - и задавать ему начальное значение, тогда можно будет начинать , например, с середины пунктира wink.gif
andreichk
Цитата(Шпиндель @ Mar 22 2008, 19:27) *
Посмотрел с интересом, спасибо! Через время.. чувствую, придётся мне делать нечто подобное, вот я тогда за вами побегаю.. wink.gif
Сейчас появляются всевозможные матрицы по ценам до 50 долларов, так что многие задачи для хобби и для работы становятся оправданными.

ну побегайте

Цитата(alexsl @ Mar 22 2008, 21:23) *
to andreichk.
Добрый день. Уменя вопрос по схемотехнике. Чем вы подсветку питали? У вас ведь CCFL подсветка?

http://www.bue.de/tabdata/datasheet/ds_en_inv-l10a.pdf


Ок, штрихпунктир прорисовывается без косяков,отличная работа Илья.Только теперь я с ужасом представляю себе, что вызов этой процедуры для прорисовки всей сетки нужно будет сделать более 160ти раз, причём с разным шагом и координатами.Стоит ли овчинка выделки?
Ilya_A
Цитата(andreichk @ Mar 23 2008, 21:41) *
Ок, штрихпунктир прорисовывается без косяков,отличная работа Илья.Только теперь я с ужасом представляю себе, что вызов этой процедуры для прорисовки всей сетки нужно будет сделать более 160ти раз, причём с разным шагом и координатами.Стоит ли овчинка выделки?

Что-то вы сильнор преувеличиваете wink.gif
Помоему код будет вполне компактным. Я так понимаю, координата (0,0) у вас в верхнем левом углу. Сообщите координату правой нижней точки окна в котором выводиться сигнал.
andreichk
X-256, Y-239
Ilya_A
Цитата(andreichk @ Mar 23 2008, 23:13) *
X-256, Y-239


Решил сделать универсальную процедуру рисования сетки:
Код
/*
Процедура рисует сетку
    координаты лев. верхнего угла (0,0)
    координаты прав. нижнего угла (x,y)
    step - шаг сетки в пикселах
    len - длина половинных меток в пикселах
*/
void setka(int16 x,int16 y,int8 step,int8 len){
    int8 xm=x/2,ym=y/2;
    BYTE ds=0,            //Приращение для сетки
         ds2=step/2;    //Приращение для половинных меток
    // Рисуем сетку и половинные метки
    while((ds<xm)||(ds<ym)||(ds2<xm)||(ds2<ym)){// пока не вышли за пределы квдрата
        if(ds<ym){// Горизонтальные линии
            pline(0,ym+ds,x,ym+ds,0,1,1);
            pline(0,ym-ds,x,ym-ds,0,1,1);
        }
        if(ds<xm){// Вертикальные линии
            pline(xm+ds,0,xm+ds,y,1,1,1);
            pline(xm-ds,0,xm-ds,y,1,1,1);
        }
        if(ds2<xm){
            line(xm+ds2,0,xm+ds2,len,1);
            line(xm+ds2,ym-len,xm+ds2,ym+len,1);
            line(xm+ds2,y,xm+ds2,y-len,1);
            line(xm-ds2,0,xm-ds2,len,1);
            line(xm-ds2,ym-len,xm-ds2,ym+len,1);
            line(xm-ds2,y,xm-ds2,y-len,1);
        }
        if(ds2<ym){
            line(0,ym+ds2,len,ym+ds2,1);
            line(xm-len,ym+ds2,xm+len,ym+ds2,1);
            line(x,ym+ds2,x-len,ym+ds2,1);
            line(0,ym-ds2,len,ym-ds2,1);
            line(xm-len,ym-ds2,xm+len,ym-ds2,1);
            line(x,ym-ds2,x-len,ym-ds2,1);
        }
        ds+=step;
        ds2+=step;
    }
    // Границы сетки
    line(0,0,0,y,1);
    line(0,0,x,0,1);
    line(0,y,x,y,1);
    line(x,0,x,y,1);
}

Для вашего случая нужно вызывать со следующими параметрами:
Код
setka(256,239,30,2);


П.С. функция line втречается всего 20 раз wink.gif
скомпилированная процедура будет занимать явно меньше 1kB, так что 9kB вы точно сэкономите
andreichk
c небольшой доработкой,приданием ей ещё бОльшей универсальности и дополнительными вызовами процедура отрисовала сетку и сэкономила 22% памяти ПИКа a14.gif

Вызовы процедур, отрисовки сетки(рамки и пр.)

Цитата
pline(8,1,250,1,1,1,14);//штрих-пунктирная линия
setka(256,239,30,2,2);//сетка
pline(8,119,250,119,1,1,14);//штрих-пунктирная линия
Line_(8,120,247,120,1 );//центральная горизонтальная линия
pline(8, 121, 256,121,1, 1,14);//штрих-пунктирная линия
pline(8,238,250,238,1,1,14);//штрих-пунктирная линия
pline(127,0,127,239,1,1,14);//средняя штрих-пунктирная линия
Line_(128,2,128,237,1 );//центральная вертикальная линия
pline(129,0,129,239,1,1,14);//средняя штрих-пунктирная линия
pline(1,0,1,238,1,1,14);//левая штрих-пунктирная линия
pline(255,0,255,238,1,1,14);//правая штрих-пунктирная линия
rect(0, 0, 256, 239, 0,1);//рамка




Цитата
/*
Процедура рисует сетку
координаты лев. верхнего угла (0,0)
координаты прав. нижнего угла (x,y)
step - шаг сетки в пикселах
len - длина половинных меток в пикселах
len0 - длина половинных пустых меток в пикселах
*/
char ds2;
void setka(int16 x,int16 y,int8 step,int8 len,int8 len0){
int8 xm,ym;
char ds; ds=0; //Приращение для сетки
ds2=step/2; //Приращение для половинных меток
xm=x/2;ym=(y/2) + 1;
// Рисуем сетку и половинные метки
while((ds<xm)||(ds<ym)||(ds2<xm)||(ds2<ym)){// пока не вышли за пределы квдрата
if(ds<ym){// Горизонтальные линии
pline(0,ym+ds,x,ym+ds,0,1,len0);
pline(0,ym-ds,x,ym-ds,0,1,len0);
}
if(ds<xm){// Вертикальные линии
pline(xm+ds,0,xm+ds,y,1,1,len0);
pline(xm-ds,0,xm-ds,y,1,1,len0);
}
if(ds2<xm){
line(xm+ds2,0,xm+ds2,len,len0);
line(xm+ds2,ym-len,xm+ds2,ym+len,len0);
line(xm+ds2,y,xm+ds2,y-len,len0);
line(xm-ds2,0,xm-ds2,len,len0);
line(xm-ds2,ym-len,xm-ds2,ym+len,len0);
line(xm-ds2,y,xm-ds2,y-len,len0);
}
if(ds2<ym){
line(0,ym+ds2,len,ym+ds2,len0);
line(xm-len,ym+ds2,xm+len,ym+ds2,len0);
line(x,ym+ds2,x-len,ym+ds2,len0);
line(0,ym-ds2,len,ym-ds2,len0);
line(xm-len,ym-ds2,xm+len,ym-ds2,len0);
line(x,ym-ds2,x-len,ym-ds2,len0);
}
ds+=step;
ds2+=step;
}
// Границы сетки
line(0,0,0,y,len0);
line(0,0,x,0,len0);
line(0,y,x,y,len0);
line(x,0,x,y,len0);
}//--------------------------
//#####################################################################


Найдите отличия( когда я говорил о 160ти вызовах, я имел ввиду именно это)
На форму сигналов и правую часть не обращайте внимания
Ilya_A
Цитата(andreichk @ Mar 24 2008, 20:24) *
c небольшой доработкой,приданием ей ещё бОльшей универсальности и дополнительными вызовами процедура отрисовала сетку и сэкономила 22% памяти ПИКа.

Найдите отличия


Ну что же, поздравляю! Новая картинка мне даже нравиться больше wink.gif

Высвободившуюся память можно заюзать под какую-нибудь цифровую обработку сигналов (как вы и говорили, например FFT) cool.gif
andreichk
а скажите мне, преобразование Фурье к осциллографу имеет применение?

нашёл вот в сети какой-то страшенный код.Скажите, это оно? И что с ним делать?

Цитата
/*************************************************************************
Быстрое преобразование Фурье

Алгоритм проводит быстрое преобразование Фурье комплексной
функции, заданной nn отсчетами на действительной оси.

В зависимости от переданных параметров, может выполняться
как прямое, так и обратное преобразование.

Входные параметры:
nn - Число значений функции. Должно быть степенью
двойки. Алгоритм не проверяет правильность
переданного значения.
a - array [0 .. 2*nn-1] of Real
Значения функции. I-ому значению соответствуют
элементы a[2*I] (вещественная часть)
и a[2*I+1] (мнимая часть).
InverseFFT
- направление преобразования.
True, если обратное, False, если прямое.

Выходные параметры:
a - результат преобразования. Подробнее см.
описание на сайте.
*************************************************************************/
void fastfouriertransform(char *a,int nn,char inversefft)
{
int ii = 0;
int jj = 0;
int n = 0;
int mmax = 0;
int m = 0;
int j = 0;
int istep = 0;
int i = 0;
int isign = 0;
double wtemp = 0;
double wr = 0;
double wpr = 0;
double wpi = 0;
double wi = 0;
double theta = 0;
double tempr = 0;
double tempi = 0;

if( inversefft )
{
isign = -1;
}
else
{
isign = 1;
}
n = 2*nn;
j = 1;
for(ii=1; ii<=nn; ii++)
{
i = 2*ii-1;
if( j>i )
{
tempr = a[j-1];
tempi = a[j];
a[j-1] = a[i-1];
a[j] = a[i];
a[i-1] = tempr;
a[i] = tempi;
}
m = n/2;
while( m>=2 & j>m )
{
j = j-m;
m = m/2;
}
j = j+m;
}
mmax = 2;
while( n>mmax )
{
istep = 2*mmax;
theta = 2*PI/(isign*mmax);
wpr = -(2.0*sqrt(Sin(0.5*theta)));
wpi = Sin(theta);
wr = 1.0;
wi = 0.0;
for(ii=1; ii<=mmax/2; ii++)
{
m = 2*ii-1;
for(jj=0; jj<=(n-m)/istep; jj++)
{
i = m+jj*istep;
j = i+mmax;
tempr = wr*a[j-1]-wi*a[j];
tempi = wr*a[j]+wi*a[j-1];
a[j-1] = a[i-1]-tempr;
a[j] = a[i]-tempi;
a[i-1] = a[i-1]+tempr;
a[i] = a[i]+tempi;
}
wtemp = wr;
wr = wr*wpr-wi*wpi+wr;
wi = wi*wpr+wtemp*wpi+wi;
}
mmax = istep;
}
if( inversefft )
{
for(i=1; i<=2*nn; i++)
{
a[i-1] = a[i-1]/nn;
}
}
}
andreichk
искал что-нибудь по теме почитать- наткнулся на это.Тут на форуме комната смеха есть? lol.gif
http://ru.fileaward.com/oscillometer_spectrum_analyzer.html
Ilya_A
Цитата(andreichk @ Mar 25 2008, 01:05) *
а скажите мне, преобразование Фурье к осциллографу имеет применение?

Если хотите строить спектр сигнала, то без FFT не обойтись wink.gif

Цитата
нашёл вот в сети какой-то страшенный код.Скажите, это оно? И что с ним делать?

Вполне похоже. но только этот алгоритм для комплексной функции. А ваш сигнал - действительная величина. Следовательно вам нужно вот это:
http://alglib.sources.ru/fft/realfft.php

Там же написано что получится на выходе.

Цитата
искал что-нибудь по теме почитать- наткнулся на это.Тут на форуме комната смеха есть?
http://ru.fileaward.com/oscillometer_spectrum_analyzer.htm

Мда..... 400 у.е. за такую хрень.... интересно, а как этот чувак получает динамический диапазон в 190 дБ на звуковой плате компьютера???? sad.gif
andreichk
Ок , оставим пока товарища Фурье в сторонке покурить и попробуем разобраться в следующей проблеме.Значит так,включаю сегодня осциллограф, а на экране вижу вместо сильно растянутого меандра вот эту жуть. Частота на входе 320 кГц, синронизация по фронту, то есть всё как обычно.Никакие нажатия на кнопки ничего не меняют, но по прошествии минут пяти картинка восстановилась, синхронизировалась и начал нормально срабатывать переключатель развёртки. Что это , разогрев микросхем или Барабашка у меня завёлся? help.gif
Ilya_A
Цитата(andreichk @ Mar 26 2008, 01:09) *
Что это , разогрев микросхем или Барабашка у меня завёлся? help.gif

Сложно что-либо сказать, не зная как у вас вообще все это устроенно....
У вас переключается частота оцифровки сигнала? Каким образом?
Что означают 2 цифры uSec/div (из названия смысл понятен, но почему тогда они разные... или это просто для 2х каналов? ) Тогда, судя по этим цифрам (сравнивая с предыдущей) на экран должен укладываться ровно 1 период меандра (0.8 против 0.4 uSec/div).
А ваша картинка больше похожа на уменьшенную частоту оцифровки (картинка мелькала, или стояла на месте?)
Если же это результат потери синхронизации, может у вас триггер синхронизации был выставлен не правильно?
andreichk
на АЦП подаётся фиксированная частота оцифровки 80 МГц. С него 8бит идут на ФИФО, кот. в свою очередь тактируется частотой от 80 МГц до 625 кГц,посредством запрограммированной ПЛИСки, то есть это и есть переключатель развёртки и соответственно показания от 0.4 мкс до 51.2 мкс(за что мы с вами не так давно бились) оба канала имеют независимый переключатель, то есть одновременно можно наблюдать и 20 кГц и 2 МГц. На последнем фото импульсы подаются на нижний канал(0.4 мкс) .Но нормальный их вид как вы правильно заметили , это 1 период на весь экран.А тут вдруг такая мелкота и не пойму -откуда она берётся и почему потом пропадает? Причём частота оцифровки никоим образом не менялась(ну разве только какая-нить гармоника пролазит) такое вообще возможно?
На всякий случай вот тут схема.Кстати, что теперь будем делать с EEPROM? С картинками , как я понимаю, вопрос закрыт wink.gif
Ilya_A
Цитата(andreichk @ Mar 28 2008, 01:34) *
А тут вдруг такая мелкота и не пойму -откуда она берётся и почему потом пропадает?

А раньше (до изменения программы) такое случалось?

Просто я сомтрю у вас FIFO буферы то всего по 512 байт. (я думал несколько Кб). Следовательно скорость считывания при отрисовке должна быть не меньше чем 1/2 от скорости заполнения данными АЦП.
Если она будет меньше, то на высоких частотах оцифровки возможна отрисовка неправильной картины (из-за перезаписи правильных значений новыми данными)

Чтобы этого избежать придется переписать процедуру curve_A() следующим образом:
Код
unsigned int8 Buf[256];
//--------------- собственно кривая ---------------------------
void curve_A(unsigned int8 y_pos_A){
   unsigned int8 x, y , yy;
   for(x=0;x<254;x++){
      Output_bit(READ_FIFO_A ,0); //PIN_C2. разрешить
      Buf[x]=input_b(); //чтение порта В
      Output_bit(READ_FIFO_A ,1); //PIN_C2.запретить
   }
   for(x=1;x<255;x++){
      yy = y;
      adcA = (Buf(x-1) > 200) ? 200 : Buf(x-1); //ограничитель до выбранной величины
      y = (255 - adcA) + y_pos_A; // разворот на 180° по вертикали и сдвиг
      if (yy>y) front(x,yy,y); // Рисуем фронт A
      if (yy<y) spad(x,yy,y); // Рисуем спад A
      pixel(x,y,1); // Рисуем вершину A
   }
}

Может быть это поможет....

Цитата(andreichk @ Mar 28 2008, 01:34) *
Кстати, что теперь будем делать с EEPROM? С картинками , как я понимаю, вопрос закрыт wink.gif

Кстати на счет EEPROM: не вижу подтягивающих резисторов на линиях SCL, SDA
andreichk
Цитата
А раньше (до изменения программы) такое случалось?

я думаю,что да, просто я не обращал внимания


adcA = (Buf(x-1) > 200) ? 200 : Buf(x-1); //ограничитель до выбранной величины
тут очепятка ? должно быть так-Buf[х-1]
Цитата
Может быть это поможет....

пока не понятно, но мне кажется , что ничего не изменилось

Цитата
Кстати на счет EEPROM: не вижу подтягивающих резисторов на линиях SCL, SDA

Упс, забыл нарисовать, на самом деле они есть и даже припаяны

Цитата
Просто я сомтрю у вас FIFO буферы то всего по 512 байт. (я думал несколько Кб). Следовательно скорость считывания при отрисовке должна быть не меньше чем 1/2 от скорости заполнения данными АЦП.
Если она будет меньше, то на высоких частотах оцифровки возможна отрисовка неправильной картины (из-за перезаписи правильных значений новыми данными)

тут мне не понятно- скорость считывания ФИФО устанавливает ПИК и она постоянная и всегда меньше
частоты АЦП, как быть?

кстати насчёт ФИФО, имеет ли смысл применить более ёмкую, напр.IDT7204 или даже IDT7205?

а может у меня вот это имеет место быть?
Ilya_A
Цитата(andreichk @ Mar 29 2008, 17:27) *
adcA = (Buf(x-1) > 200) ? 200 : Buf(x-1); //ограничитель до выбранной величины
тут очепятка ? должно быть так-Buf[х-1]

Естественно!

Цитата(andreichk @ Mar 29 2008, 17:27) *
тут мне не понятно- скорость считывания ФИФО устанавливает ПИК и она постоянная и всегда меньше
частоты АЦП, как быть?
кстати насчёт ФИФО, имеет ли смысл применить более ёмкую, напр.IDT7204 или даже IDT7205?

Тут, помоему чем больше тем лучше. Ведь даже на 10 MIPS вы сможете обеспечить максимальную скорость считывания порядка единиц Мгц. А записывать данные вы можете до 80 Мгц!!!!

Цитата(andreichk @ Mar 29 2008, 17:27) *
а может у меня вот это имеет место быть?

Чтобы это проверить, нужно замерить реальную скорость выгребания данных из FIFO буфера (можно по по количеству ассемблерных инструкций после компиляции программы) И сравнить со скоростью записи в буфер
andreichk
Цитата(Илья @ Mar 29 2008, 13:10) *
Чтобы это проверить, нужно замерить реальную скорость выгребания данных из FIFO буфера (можно по по количеству ассемблерных инструкций после компиляции программы) И сравнить со скоростью записи в буфер

Ок, а с какого места нужно начинать считать эти инструкции?
Ilya_A
Цитата(andreichk @ Mar 30 2008, 17:34) *
Ок, а с какого места нужно начинать считать эти инструкции?

Незнаю, как в CCS, но в MPLABe это делается очень просто, открываем Dissasebly listing, находим строчку начала цикла:
Код
   for(x=0;x<254;x++){
      Output_bit(READ_FIFO_A ,0); //PIN_C2. разрешить
      Buf[x]=input_b(); //чтение порта В
      Output_bit(READ_FIFO_A ,1); //PIN_C2.запретить
   }

И считаем сколько команд ушло на этот цикл wink.gif

Если в CCS такого нет, то может он хотябы отобразить текст откомпилированной программы? И если в нем возможна симуляция, то поставить BreakPoint на начало цикла, а затем посмотреть на какой строчке программа остановиться в асме. далее выполнять программу по шагам ассемблерных инструкций, пока не вернетесь снова на точку останова. Таким образом можно подсчитать количестов асм. инструкций.

Ну или в крайнем случае можно померять клоки осциллографом.
andreichk
есть такое дело

Цитата
.................... //--------------- собственно кривая ---------------------------
.................... void curve_A(unsigned int8 y_pos_A){
.................... unsigned int8 x, y , yy;
.................... for(x=0;x<254;x++){
*
26E4: MOVLB 1
26E6: CLRF x6B
26E8: MOVF x6B,W
26EA: SUBLW FD
26EC: BNC 2710
.................... Output_bit(READ_FIFO_A ,0); //PIN_C2. разрешить
26EE: BCF F8B.2
26F0: BCF F94.2
.................... Buf[x]=input_b(); //чтение порта В
26F2: CLRF 03
26F4: MOVF x6B,W
26F6: ADDLW 55
26F8: MOVWF FE9
26FA: MOVLW 00
26FC: ADDWFC 03,W
26FE: MOVWF FEA
2700: MOVLW FF
2702: MOVWF F93
2704: MOVFF F81,FEF
.................... Output_bit(READ_FIFO_A ,1); //PIN_C2.запретить
2708: BSF F8B.2
270A: BCF F94.2
.................... }
270C: INCF x6B,F
270E: BRA 26E8
.................... for(x=1;x<255;x++){
2710: MOVLW 01
2712: MOVWF x6B
2714: INCFSZ x6B,W
2716: BRA 271A
2718: BRA 27AA
.................... yy = y;
271A: MOVFF 16C,16D
.................... adcA = (Buf[x-1] > 200) ? 200 : Buf[x-1]; //ограничитель до выбранной величины
271E: MOVLW 01
2720: SUBWF x6B,W
2722: CLRF 03
2724: ADDLW 55
2726: MOVWF FE9
2728: MOVLW 00
272A: ADDWFC 03,W
272C: MOVWF FEA
272E: MOVF FEF,W
2730: SUBLW C8
2732: BC 2738
2734: MOVLW C8
2736: BRA 274A
2738: MOVLW 01
273A: SUBWF x6B,W
273C: CLRF 03
273E: ADDLW 55
2740: MOVWF FE9
2742: MOVLW 00
2744: ADDWFC 03,W
2746: MOVWF FEA
2748: MOVF FEF,W
274A: MOVWF x54
.................... y = (255 - adcA) + y_pos_A; // разворот на 180° по вертикали и сдвиг
274C: MOVLW FF
274E: BSF FD8.0
2750: SUBFWB x54,W
2752: ADDWF x6A,W
2754: MOVWF x6C
.................... adcA = y;
2756: MOVFF 16C,154
.................... if (yy>y) front(x,yy,y); // Рисуем фронт A
275A: MOVF x6D,W
275C: SUBWF x6C,W
275E: BC 2774
2760: MOVFF 16B,16E
2764: MOVFF 16D,16F
2768: MOVFF 16C,170
276C: MOVLB 0
276E: CALL 1DEC
2772: MOVLB 1
.................... if (yy<y) spad(x,yy,y); // Рисуем спад A
2774: MOVF x6C,W
2776: SUBWF x6D,W
2778: BC 278E
277A: MOVFF 16B,16E
277E: MOVFF 16D,16F
2782: MOVFF 16C,170
2786: MOVLB 0
2788: CALL 1E18
278C: MOVLB 1
.................... pixel(x,y,1); // Рисуем вершину A
278E: CLRF x8B
2790: MOVFF 16B,18A
2794: CLRF x8D
2796: MOVFF 16C,18C
279A: MOVLW 01
279C: MOVWF x8E
279E: MOVLB 0
27A0: CALL 0BE8
.................... }
27A4: MOVLB 1
27A6: INCF x6B,F
27A8: BRA 2714
.................... }
27AA: MOVLB 0
27AC: RETLW 00
....................
.................... //########################################
Ilya_A
Цитата(andreichk @ Mar 30 2008, 18:10) *
есть такое дело

Да, это в принципе оно и есть. только не видать конца цикла, приведите еще несколько инструкций, чтобы точнее определить полное количество тактов. Я предполагаю, что конец цикла по адресу 0x270F
andreichk
Цитата(Илья @ Mar 30 2008, 12:00) *
Да, это в принципе оно и есть. только не видать конца цикла, приведите еще несколько инструкций, чтобы точнее определить полное количество тактов. Я предполагаю, что конец цикла по адресу 0x270F

заменил предыдущий пость на полный текст процедуры
Ilya_A
Цитата(andreichk @ Mar 30 2008, 19:05) *
заменил предыдущий пость на полный текст процедуры


Цикл от 0x26E8 до 0x270E итого 18 интсрукций, по 1му такту и 1 инструкция 2 такта всего 20 тактов

Следовательно период считываения 2 мкс, а частота 500 кГц

Следовательно можно сделать вывод, что если частота заполнения FIFO будет больше чем 1 Мгц то за время считывания 255 отсчетов в FIFO положится более 512 новых значений и часть отсчетов просто перезапишется новыми.
andreichk
ну это понятно, что перепишется.А как это связано с образованием частокола и последующим его исчезновением?
Ilya_A
Цитата(andreichk @ Mar 30 2008, 19:39) *
ну это понятно, что перепишется.А как это связано с образованием частокола и последующим его исчезновением?

А при какой частоте тактирования FIFO они возникают?

Вообще говоря цикл получился крайне не оптимальным. sad.gif

Совершенно напонятно зачем выполняются строчки:
Код
26F0: BCF F94.2
270A: BCF F94.2

Зачем каждый раз чистить TRIS???? А это уже 2 лишних такта!

Советую вам переписать следующим образом, должно получится гораздо компактнее:
Код
unsigned char * ptr=Buf;
x=2;
while(x++){
      LATC2=0;
      *ptr++=input_b(); //чтение порта В
      LATC2=1;
}

А вообще, похорошему нужно воспользоваться регистрами косвенной адресации (FSR) тогда указатель будет инкрементироваться автоматически после каждого присвоения.
Но тут уже без асма не обойтись.... wink.gif
andreichk
Цитата
А при какой частоте тактирования FIFO они возникают?

да собственно на всех восьми, но заметнее всего при 80ти МГц, то есть 0.4 мксек
Цитата
LATC2=0;

это что такое? sad.gif
Цитата
А вообще, похорошему нужно воспользоваться регистрами косвенной адресации (FSR) тогда указатель будет инкрементироваться автоматически после каждого присвоения.
Но тут уже без асма не обойтись.... wink.gif

тут я без поллитры не разберусь.
про Асм и FSR слышал, но живьём не видел 07.gif
Ilya_A
Цитата(andreichk @ Mar 30 2008, 21:03) *
LATC2
это что такое? sad.gif

Это регистр защелок порта C, а 2 - номер бита.

если не работает можно попробывать сделать асмовскую вставку, незнаю как у вас в CCS, но в PICC это делается так:
Код
asm("BSF F8B.2");  //LATC2=1
asm("BCF F8B.2");  //LATC2=0

F8B - это адрес LATC, вообщето он должен быть прописан и можно писать так:
Код
asm("BSF LATC.2");  //LATC2=1
asm("BCF LATC.2");  //LATC2=0


А вообще тут что нету специалистов по CCS? подскажите человеку!!!! 1111493779.gif

Цитата
пытаюсь загрузить видео, не знаю можно уже посмотреть или нет?

Видео посметреть пока у меня не получается.... sad.gif
andreichk
можно написать так
#asm
BSF F8B.2 //LATC2=1
#endasm
но он не хочет узнавать F8B.2
пишет- неопределённая переменная.
может чего в настройках компилятора недостаёт, буду разбираться

тут попробуйте
http://video.google.de/videoplay?docid=330...h&plindex=0
Ilya_A
Цитата(andreichk @ Mar 30 2008, 21:38) *
можно написать так
#asm
BSF F8B.2 //LATC2=1
#endasm
но он не хочет узнавать F8B.2

Попробуйте написать так: BSF 0x0F8B, 0x2
andreichk
написал так, ошибок нет,но экран тухнет через пару сек

#asm
BSF 0xF8B.2//LATC2=0;
#endasm
*ptr++=input_b(); //чтение порта В
#asm
BCF 0xF8B.2//LATC2=1;
#endasm

Попробуйте написать так: BSF 0x0F8B, 0x2

всё равно тухнет

просмотр видео состоялся?
Ilya_A
Цитата(andreichk @ Mar 30 2008, 23:19) *
написал так, ошибок нет,но экран тухнет через пару сек

Что значит тухнет экран? Весь? или только перестает рисоваться сигнал?
andreichk
в самом прямом смысле тухнет.Пропадает не только линия,но и сетка и цифирьки.
Ilya_A
Цитата(andreichk @ Mar 30 2008, 23:33) *
в самом прямом смысле тухнет.Пропадает не только линия,но и сетка и цифирьки.

При добавлении какой именно строчки такое происходит? Попробуйте модифицировать постепенно.

Цитата
просмотр видео состоялся?

Нет, пишет: No matching videos.

Не проще ли залить файлик на рапиду? wink.gif
andreichk
вот этой
*ptr++=input_b(); //чтение порта В
ну тогда отсюда попробуйте
http://forum.radiospec.ru/index.php?showtopic=6310
Ilya_A
Цитата(andreichk @ Mar 30 2008, 23:59) *
вот этой
*ptr++=input_b(); //чтение порта В

попробуйте сделать так:
Код
*ptr=input_b(); //чтение порта В
ptr++;

Кстати, а приведите лучше дизассемблер, посмотрим что там ваш компилятор на компилировал

Цитата
ну тогда отсюда попробуйте
http://forum.radiospec.ru/index.php?showtopic=6310

12 МБ.... я щас на диалапе, завтра качну по нормальному каналу smile.gif
andreichk
Цитата
.................... //####################################################################
.................... //--------------- собственно кривая ---------------------------
.................... unsigned char *ptr=Buf;
.................... void curve_A(unsigned int8 y_pos_A){
.................... unsigned int8 x,y, yy;
.................... x=2;
*
26E4: MOVLW 02
26E6: MOVLB 1
26E8: MOVWF x6D
.................... // for(x=0;x<254;x++){
.................... while(x++){
26EA: MOVF x6D,W
26EC: INCF x6D,F
26EE: XORLW 00
26F0: BZ 270E
.................... #asm
.................... BSF 0x0F8B,0x2//LATC2=0;
26F2: BSF F8B.2
.................... #endasm
.................... *ptr=input_b(); //чтение порта В
26F4: MOVFF 15F,FE9
26F8: MOVFF 160,FEA
26FC: MOVLW FF
26FE: MOVWF F93
2700: MOVFF F81,FEF
.................... ptr++;
2704: INCF x5F,F
2706: BTFSC FD8.2
2708: INCF x60,F
.................... #asm
.................... BCF 0x0F8B,0x2//LATC2=1;
270A: BCF F8B.2
.................... #endasm
.................... //Output_bit(READ_FIFO_A ,0); //PIN_C2. разрешить
.................... //Buf[x]=input_b(); //чтение порта В
.................... //Output_bit(READ_FIFO_A ,1); //PIN_C2.запретить
.................... }
270C: BRA 26EA
.................... for(x=1;x<255;x++){
270E: MOVLW 01
2710: MOVWF x6D
2712: INCFSZ x6D,W
2714: BRA 2718
2716: BRA 27A4
.................... yy = adcA;//y
2718: MOVFF 154,16F
.................... adcA = (Buf[x-1] > 200) ? 200 : Buf[x-1]; //ограничитель до выбранной величины
271C: MOVLW 01
271E: SUBWF x6D,W
2720: CLRF 03
2722: ADDLW 55
2724: MOVWF FE9
2726: MOVLW 00
2728: ADDWFC 03,W
272A: MOVWF FEA
272C: MOVF FEF,W
272E: SUBLW C8
2730: BC 2736
2732: MOVLW C8
2734: BRA 2748
2736: MOVLW 01
2738: SUBWF x6D,W
273A: CLRF 03
273C: ADDLW 55
273E: MOVWF FE9
2740: MOVLW 00
2742: ADDWFC 03,W
2744: MOVWF FEA
2746: MOVF FEF,W
2748: MOVWF x54
.................... adcA = (255 - adcA) + y_pos_A; // разворот на 180° по вертикали и сдвиг
274A: MOVLW FF
274C: BSF FD8.0
274E: SUBFWB x54,W
2750: ADDWF x6C,W
2752: MOVWF x54
.................... if (yy>adcA) front(x,yy,adcA); // Рисуем фронт A
2754: MOVF x6F,W
2756: SUBWF x54,W
2758: BC 276E
275A: MOVFF 16D,170
275E: MOVFF 16F,171
2762: MOVFF 154,172
2766: MOVLB 0
2768: CALL 1DEC
276C: MOVLB 1
.................... if (yy<adcA) spad(x,yy,adcA); // Рисуем спад A
276E: MOVF x54,W
2770: SUBWF x6F,W
2772: BC 2788
2774: MOVFF 16D,170
2778: MOVFF 16F,171
277C: MOVFF 154,172
2780: MOVLB 0
2782: CALL 1E18
2786: MOVLB 1
.................... pixel(x,adcA,1); // Рисуем вершину A
2788: CLRF x8D
278A: MOVFF 16D,18C
278E: CLRF x8F
2790: MOVFF 154,18E
2794: MOVLW 01
2796: MOVWF x90
2798: MOVLB 0
279A: CALL 0BE8
.................... }
279E: MOVLB 1
27A0: INCF x6D,F
27A2: BRA 2712
.................... }
27A4: MOVLB 0
27A6: RETLW 00
....................
.................... //####


всё равно тухнет.Я так думаю, что там всё правильно и нужно.Наверное не стоит там ковыряться

Цитата
12 МБ....

Ограбили 1111493779.gif я на 43 наснимал !!! 1111493779.gif

давайте лучше это строить, только я не знаю с какого боку подьезжать

Цитата
//##############################################
void spectrum_analizator(void)
{
realfastfouriertransform( Buf,128,0);
}
//##############################################
smile.gif
Ilya_A
Цитата(andreichk @ Mar 31 2008, 00:27) *
всё равно тухнет.Я так думаю, что там всё правильно и нужно.

Нет, вы не правы, там половина операций ненужна... но я заметил что не происходит инициализация указателя ptr, при входе в функцию, хотя у меня написано (ненравится мне этот компилятор, блин...)

напишите явное присвоение
Код
ptr=Buf;

перед циклом
Код
while(x++)

Просто происходило следующее: при каждом входе в процедуру, указатель все увеличивался и увеличивался... и затирал все подряд...

также абсолютнно бессмыслены следующие строчки:
Код
26FC: MOVLW FF
26FE: MOVWF F93

их нужно максимум выполнить 1 раз перед циклом.

А проверка условия выхода из цикла:
Код
26EA: MOVF x6D,W
26EC: INCF x6D,F
26EE: XORLW 00
26F0: BZ 270E

Это же просто ужас!!! 07.gif Они что не знают инструкции INCFSZ ???

Я бы написал весь цикл в 5 асмовских инструкций, и выполнялся бы он за 6 тактов процессора...

Цитата(andreichk @ Mar 31 2008, 00:27) *
давайте лучше это строить, только я не знаю с какого боку подьезжать

Ну вы хоть начните подъезжать!!! wink.gif Может вопросы по конкретнее появятся...
andreichk
Илья, я уже запутался, что куда вписывать, сделайте плиз это за меня , а я сразу же проверю
Цитата
//####################################################################
void pix_A(unsigned int8 y_pos_A) // рисуем кривую, типа синусоиды и пр.
{ unsigned int16 n=0;

Output_bit(PLCD_FIFO_RES ,0); //PIN_C0// сброс FIFO в "0"
Output_bit(PLCD_FIFO_RES ,1); //PIN_C0// и разрешение на считывание
Output_bit(READ_FIFO_B ,1); //PIN_C1 запрет канала B
//-------------------- синхронизация ---------------------------
n=0;
for(;;){
Output_bit(READ_FIFO_A ,0); //PIN_C2. разрешить
adcA=input_b(); //чтение порта В
Output_bit(READ_FIFO_A ,1); //PIN_C2.запретить
adcA = (adcA > 200) ? 200 : adcA; //ограничитель до выбранной величины
adcA = 255 - adcA; // разворот на 180° по вертикали
if (n++>TIMEOUT) {curve_A(y_pos_A); return;}
if (syncA){
if(adcA>sync_volume_A) continue;else break;
}else{
if(adcA<=sync_volume_A+115) continue;else break;
}
} curve_A(y_pos_A);//собственно кривая

}//--------------------------OK
//####################################################################
//--------------- собственно кривая ---------------------------
unsigned char *ptr=Buf;
void curve_A(unsigned int8 y_pos_A){
unsigned int8 x,y, yy;
x=2;
// for(x=0;x<254;x++){
while(x++){
#asm
BSF 0x0F8B,0x2//LATC2=0;
#endasm
*ptr=input_b(); //чтение порта В
ptr++;
#asm
BCF 0x0F8B,0x2//LATC2=1;
#endasm
//Output_bit(READ_FIFO_A ,0); //PIN_C2. разрешить
//Buf[x]=input_b(); //чтение порта В
//Output_bit(READ_FIFO_A ,1); //PIN_C2.запретить
}
for(x=1;x<255;x++){
yy = adcA;//y
adcA = (Buf[x-1] > 200) ? 200 : Buf[x-1]; //ограничитель до выбранной величины
adcA = (255 - adcA) + y_pos_A; // разворот на 180° по вертикали и сдвиг
if (yy>adcA) front(x,yy,adcA); // Рисуем фронт A
if (yy<adcA) spad(x,yy,adcA); // Рисуем спад A
pixel(x,adcA,1); // Рисуем вершину A
}
}
//#########################################
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.