Исходники, алгоритмы.

Кружок юных, и не только, радиолюбителей

Исходники, алгоритмы.

Сообщение slav0n » 15 апр 2011, 15:09

Выкладываем здесь различные примеры исходников.

Для начала очень компактное целочисленное вычисление квадратного корня.
Код: Выделить всё
unsigned short isqrt(unsigned long x)
{
     unsigned short y = 0;
     unsigned long  z = 1;
     while(x >= z)
    {
         x -= z;
         z += 2;
         y++;
    };
    return y;
}
while(1||!1);
slav0n
Site Admin
 
Сообщения: 4341
Зарегистрирован: 15 ноя 2009, 18:43
Благодарил (а): 24 раз.
Поблагодарили: 385 раз.

Программный ведомый шины I2C на ассемблере

Сообщение slav0n » 15 апр 2011, 15:55

Программная реализация ведомого шины I2C.
Так как делалось для конкретной задачи эмуляции LNBP21, реализована простейшая отработка только двух байтов: байт адреса и управляющий байт. Для полноценной реализации протокола I2C требуется доработка. Разобравшимся в исходнике, думаю, это будет несложно.
Код: Выделить всё
;Эмулятор шины I2C LNBP21
;Отрабатывает вкл-выкл питания конвертера PINB.3
;а также переключение поляризации PINB.4

.include "tn13def.inc" ;ATtiny13

;Hfuse FF
;Lfuse 7A

.def data      = r23
.def count_bit = r24
.def count_byte= r25

.equ SCL = 1     ;опрделяем пины
.equ SDA = 0     ;шины I2C

.equ ON_OFF = 3   ;определяем выходные
.equ H_V    = 4   ;пины

.equ DEVICE =$10 ;определяем адрес устройства

;***** BEGIN *****
ldi data,(1<<ON_OFF)|(1<<H_V)
out DDRB,data  ;конфигурируем порт на выход

WAIT_START:
ldi count_byte,2

WAIT_SCL:
sbis PINB,SCL  ;ждем когда клок будет 1
rjmp PC-1

sbis PINB,SDA  ;ждем когда data будет 1
rjmp PC-1

sbic PINB,SDA  ;ждем когда data будет 0
rjmp PC-1

sbis PINB,SCL  ;если клок не 1,
rjmp WAIT_SCL  ;это не START, идем ждать клок 1

sbic PINB,SCL  ;ждем когда клок будет 0
rjmp PC-1

;=======принимаем байт ===================
LOOP_st:
ldi count_bit, 8

LOOP:
sbis PINB,SCL  ;ждем когда клок будет 1, при этом ведущий устанавливает бит для передачи
rjmp PC-1

lsl data       ;сдвигаем регистр data на один разряд влево
sbic PINB,SDA  ;проверяем линию данных
ori  data,1    ;если единица, пишем её в data

sbic PINB,SCL  ;ждем когда клок будет 0
rjmp PC-1

dec count_bit   ;уменьшаем счетчик разрядов на 1
brne LOOP     

dec count_byte  ;уменьшаем счетчик байтов на 1
brne ADR       ;если это был 1-й байт, идем на проверку адреса

;-------устанавливаем выходные сигналы-------------
;-------в зависимости от второго принятого байта---
out PORTB,count_bit  ;обнуляем выходы

sbrs data, 3
sbi PORTB,H_V

sbrc data, 2
sbi PORTB,ON_OFF

rjmp ACK
;-----------------------------------------

ADR:
cpi  data,DEVICE ;если адрес не наш, выходим на ожидание условия START
brne WAIT_START

ACK:
sbi DDRB, SDA  ;порт на вывод
cbi PORTB,SDA  ;выводим ноль на SDA, тоесть отвечаем АСК

sbis PINB,SCL  ;ждем когда клок будет 1
rjmp PC-1

sbic PINB,SCL  ;ждем когда клок будет 0,при этом ведущий читает наш АСК
rjmp PC-1

cbi DDRB,SDA   ;порт на ввод - отпускаем СДА

tst count_byte  ;проверяем счетчик принятых байт
brne LOOP_st   ;если не 0, идем принимать второй байт

rjmp WAIT_START
while(1||!1);
slav0n
Site Admin
 
Сообщения: 4341
Зарегистрирован: 15 ноя 2009, 18:43
Благодарил (а): 24 раз.
Поблагодарили: 385 раз.

Вычисление синус, косинус и арктангенс. CORDIC

Сообщение slav0n » 15 апр 2011, 18:43

Еще один достойный внимания алгоритм.
Код: Выделить всё
/*
Алгоритм CORDIC ([CO]ordinate [R]otation [DI]gital [C]alculation)

Позволяет быстро и компактно вычислять синус, косинус и арктангенс
без использования плавающей точки.
Данные в функцию передаются и возвращаются
с помощью структуры типа codr_data

аргументы и результаты умножаются и делятся на 100 соответственно.
*/

/*=========================
синус-косинус
-------------------------
начальные условия:
mod= 0
angle= угол, y=0, x= 6073

результат:
y = sin
x = cos

=========================
арктангенс
-------------------------
начальные условия:
mod= 1
angle= 0, y = y, x = x

результат:
angle = -atan(y/x)
==========================*/


#define  K 16468
#define  KK 6073 // (1/16468)

const int tab_arctg[13] PROGMEM =
    {4500,2657,1404,713,358,179,90,45,22,11,6,3,1,};

struct codr_data{
   int angle;
   int y;
   int x;
   char mod;
   };

void CORDIC(struct codr_data *cd)
{                   
   int y_next;
   int x_next;
   int arctg;
   int *p = tab_arctg;

   for(u8 i=0;i<13;i++)
   {
      arctg = pgm_read_word(p++);
      
      x_next = cd->x >> i;
      y_next = cd->y >> i;
      
      if(cd->mod == 0) //sin cos
      {
         if(cd->angle < 0)
         {
            x_next = -x_next;
            y_next = -y_next;
         }
         else arctg = -arctg;
      }
      else
      if(cd->mod == 1) //arctg
      {
         if(cd->y < 0)
         {
            x_next = -x_next;
            y_next = -y_next;
            arctg = -arctg;
         }
      }
         
      cd->y -= x_next;
      cd->x += y_next;
      
      cd->angle += arctg;
   }
}
/************ пример использования *********************/
void main(void)
{
   struct codr_data cd;
   int my_cos, my_sin, my_atan, coord_x, coord_y, my_angl;
   
   cd.mod = 0; //sin cos
   cd.angle = my_angl;
   cd.y = 0;
   cd.x = 6073;
   
   CORDIC(&cd);
   
   my_cos = cd.x;
   my_sin = cd.y;
   
   
   cd.mod = 1; //atan         
   cd.angle = 0;
   cd.y = coord_y;
   cd.x = coord_x;
   
   CORDIC(&cd);
   
   my_angl = cd.angle;
}
while(1||!1);

За это сообщение автора slav0n поблагодарил:
attache(09 июн 2011, 11:43)
slav0n
Site Admin
 
Сообщения: 4341
Зарегистрирован: 15 ноя 2009, 18:43
Благодарил (а): 24 раз.
Поблагодарили: 385 раз.

Изменяем параметр двумя кнопками

Сообщение slav0n » 01 июл 2011, 07:23

Изменяем двумя кнопками некое значение по кругу от 0 до limit-1 с шагом step. Направление счета изменяем знаком step.
Операторы сравнения не используются.

Код: Выделить всё
void Up_Down_button(unsigned char *value, unsigned char limit, signed char step)
{
      *value += limit;
      
      if(Button_Down)*value +=step;
      else
      if(Button_Up  )*value -=step;

      *value %= limit;
}
while(1||!1);
slav0n
Site Admin
 
Сообщения: 4341
Зарегистрирован: 15 ноя 2009, 18:43
Благодарил (а): 24 раз.
Поблагодарили: 385 раз.

Сообщение lizard66 » 27 окт 2011, 22:43

Всю тригонометрию делал методом степенных рядов Тейлора-Маклонена, поэтому арккосинус был уже на 90% готов, а корень делал по этому алгоритму:

x1 = 1;
x2 = 0;
while (true) {
x2 = (x1+N/x1)/2;
if (fabs(x1-x2) < eps) break;
x1 = x2;
}

для точности два знака после запятой достаточно 4-5 итераций
Аватара пользователя
lizard66
 
Сообщения: 152
Зарегистрирован: 11 фев 2011, 17:59
Благодарил (а): 4 раз.
Поблагодарили: 6 раз.

Re: ПО для Primuss3-spectrum

Сообщение slav0n » 27 окт 2011, 23:53

lizard66 писал(а):а корень делал по этому алгоритму

lizard66 писал(а):Сорри, все пишем на асме

:-):
while(1||!1);
slav0n
Site Admin
 
Сообщения: 4341
Зарегистрирован: 15 ноя 2009, 18:43
Благодарил (а): 24 раз.
Поблагодарили: 385 раз.

Сообщение lizard66 » 28 окт 2011, 08:22

slav0n писал(а):
lizard66 писал(а):а корень делал по этому алгоритму

lizard66 писал(а):Сорри, все пишем на асме

:-):


Алгоритм так наглядней выглядет или на асме тебе былоб понятней? Сорри за синтаксис, "С" владею плохо, мот надо было переменные обьявить и функции? :-):
Аватара пользователя
lizard66
 
Сообщения: 152
Зарегистрирован: 11 фев 2011, 17:59
Благодарил (а): 4 раз.
Поблагодарили: 6 раз.

Re: Исходники , алгоритмы.

Сообщение slav0n » 28 окт 2011, 09:41

lizard66 писал(а):Алгоритм так наглядней выглядет или на асме тебе былоб понятней? Сорри за синтаксис, "С" владею плохо
Не думаю, что на асме алгоритмы выглядят понятней чем на C. Почти машинный язык, однако. :-):
Твой способ на "человеческом" языке выглядит примерно так:
Код: Выделить всё
unsigned sqrt_cpu_newton(long L)
   {
      unsigned rslt = (unsigned)L;
      long div = L;
      if (L <= 0) return 0;
      while (l)
      {
         div = (L / div + div) / 2;
         if (rslt > div) rslt = (unsigned)div;
             else return rslt;
      }
   }

взято отсюда
while(1||!1);

За это сообщение автора slav0n поблагодарил:
lizard66(28 окт 2011, 12:19)
slav0n
Site Admin
 
Сообщения: 4341
Зарегистрирован: 15 ноя 2009, 18:43
Благодарил (а): 24 раз.
Поблагодарили: 385 раз.

Сообщение lizard66 » 28 окт 2011, 09:47

slav0n писал(а):взято отсюда


Очень познавательная ссылка, спасибо.
Аватара пользователя
lizard66
 
Сообщения: 152
Зарегистрирован: 11 фев 2011, 17:59
Благодарил (а): 4 раз.
Поблагодарили: 6 раз.

скользящий сглаживающий алгоритм

Сообщение slav0n » 13 дек 2011, 07:04

Нашел на хабре интересную формулу

output[i] = alpha*input[i] + (1-alpha)*output[i-1]
0<=alpha<=1

Применительно к микроконтроллерам можно использовать так:

output[i] = input[i] /2 + output[i-1] /2
while(1||!1);
slav0n
Site Admin
 
Сообщения: 4341
Зарегистрирован: 15 ноя 2009, 18:43
Благодарил (а): 24 раз.
Поблагодарили: 385 раз.

Сообщение slav0n » 20 янв 2012, 19:17

Вот здесь нашел до кучи еще один вариант сглаживания:

output[i] = output[i-1] + (input[i] - output[i-1])*alpha
0<alpha<1

> Научите какой алгоритм (формулу) требуется установить в контроллер
> для реализации инерционного звена 1-го порядка...

Обозначим X - вход звена, Y - выход звена.

Формула для вычисления выхода инерционного звена 1-го порядка (на языке ST):
Y := Y + (X-Y)*K;

Где K - коэффициент, который обычно вычисляется заранее (один раз) по формуле:
K:=T/(t+T);
Где
t - постоянная времени инерционного звена,
T - период расчета (если расчет выполняется в каждом скане контроллера, то берется время скана; если по прерыванию - то тик прерывания и т.д. )

K имеет смысл в пределах от 0 до 1 (не включая границ). При K=0 выход звена "замораживается" (т.е. постоянная времени звена равна бесконечности), при K=1 звено превращается в повторитель (т.е. постоянная времени звена равна нулю).

>..., интегратора
> (здесь вроде все
> понятно),
> реального дифференциала...

Требуется дополнительная переменная X0 для хранения значения входа из предыдущего скана. Расчет:
Y := (X-X0)*K;
X0 := X;

Где K - коэффициент, который обычно вычисляется заранее (один раз) по формуле:
K:=t/T;
Где
t - постоянная времени дифференцирующего звена,
T - период расчета (если расчет выполняется в каждом скане контроллера, то берется время скана; если по прерыванию - то тик прерывания и т.д.)

> ..., скользящего среднего?

Поскольку Виктор Бардичев уже ответил, добавлю только, что реализация скользящего среднего (СС) в контроллере требует работы с массивами и индексной или косвенной адресацией. Преимущества СС по сравнению с инерционным звеном (экспоненциальным фильтром) неочевидны, поэтому на практике я никогда не сталкивался с необходимостью реализовать именно СС.
while(1||!1);
slav0n
Site Admin
 
Сообщения: 4341
Зарегистрирован: 15 ноя 2009, 18:43
Благодарил (а): 24 раз.
Поблагодарили: 385 раз.

Алгоритмические симфонии из одной строки кода - как и почему

Сообщение slav0n » 21 мар 2012, 08:54

Любопытный способ получения мелодий.
http://countercomplex.blogspot.com/2011 ... ne-of.html
http://countercomplex.blogspot.com/2011 ... music.html

А здесь можно самому поиграться - http://wurstcaptures.untergrund.net/music/
while(1||!1);
slav0n
Site Admin
 
Сообщения: 4341
Зарегистрирован: 15 ноя 2009, 18:43
Благодарил (а): 24 раз.
Поблагодарили: 385 раз.

Сообщение slav0n » 22 мар 2012, 16:38

Попробовал реализовать этот алгоритм на AVR. Код на Си получается простой до безобразия. :-):
Для этого используем аппаратный 8-битный таймер в режиме Fast PWM.

s_cx.GIF

Вот собственно код для ATtiny13
Код: Выделить всё
#include <avr/io.h>

main(void)
{
      TCCR0B=(0<<CS02)|(0<<CS01)|(1<<CS00);    // clk
      TCCR0A=(1<<COM0A1)|(0<<COM0A0)|      //pinout 1-0-1
         (1<<WGM01)|(1<<WGM00);        //Fast PWM
            
      DDRB = (1<<PB0); //sound out Timer/Counter0

      long t;

      for(;;t++)
      {
      //  Немного формул взятых из Интернета. Желаемое раскомментировать.
                //   OCR0A = t * ((t>>12|t>>8)&63&t>>4);
      //   OCR0A = (t>>7|t|t>>6)*10+4*(t&t>>13|t>>6);
      //   OCR0A = t*(42&t>>10);
      //   OCR0A = t*((42&t>>10)%14);
      //   OCR0A = (t*3)&t>>8;
      //   OCR0A = t*9&t>>4|t*5&t>>7|t*3&t/1024;
      //   OCR0A = t>>4|t&((t>>5)/(t>>7-(t>>15)&-t>>7-(t>>15)));
      //   OCR0A = t>>6&1?t>>5:-t>>4;
      //   OCR0A = t&t%255;
      //   OCR0A = (t>>6|t|t>>(t>>16))*10+((t>>11)&7);
      //   OCR0A = ((t*(t>>8|t>>9)&46&t>>8))^(t&t>>13|t>>6);
      //   OCR0A = (t*5&t>>7)|(t*3&t>>10);
      //   OCR0A = t*(((t>>9)&10)|((t>>11)&24)^((t>>10)&15&(t>>15)));
      //   OCR0A = t*(((t>>9)^((t>>9)-1)^1)%13);
      //   OCR0A = (t>>5)|(t>>4)|((t%42)*(t>>4)|(0x15483113)-(t>>4))/(t>>16)^(t|(t>>4));
      //   OCR0A = t>>6^t&37|t+(t^t>>11)-t*((t%24?2:6)&t>>11)^t<<1&(t&598?t>>4:t>>10);
      
      //   OCR0A = ((t&4096)?((t*(t^t%255)|(t>>4))>>1):(t>>3)|((t&8192)?t<<2:t));
      //   OCR0A = t*(t>>((t&4096)?((t*t)/4096):(t/4096)))|(t<<(t/256))|(t>>4);
      //   OCR0A = ((t%42)*(t>>4)|(0x15483113)-(t>>4))/(t>>16)^(t|(t>>4));
      
      //   OCR0A = (((((t*((t>>9|t>>13)&15))&255/15)*9)%(1<<7))<<2)%6<<4;
         
      //   OCR0A = ((t>>5&t)-(t>>5)+(t>>5&t))+(t*((t>>14)&14));
         OCR0A = (t*(t>>12)*64+(t>>1)*(t>>10)*(t>>11)*48)>>(((t>>16)|(t>>17))&1);

      //   OCR0A = t*t/(t>>12&t>>8)<<7;
      //   OCR0A = 8*t*t*(t>>(t>>10)%3+15)/(3+(t>>10&(t>>15&3|4)))|t/16;

         char d = 200;          // переменной d подбираем темп мелодии
         while(--d)asm("nop"::);
      }
}
Вложения
PIC_0032.rar
звук формулы:
(t*(t>>12)*64+(t>>1)*(t>>10)*(t>>11)*48)>>(((t>>16)|(t>>17))&1)
(218.54 Кб) Скачиваний: 32
while(1||!1);
slav0n
Site Admin
 
Сообщения: 4341
Зарегистрирован: 15 ноя 2009, 18:43
Благодарил (а): 24 раз.
Поблагодарили: 385 раз.

Re: Исходники , алгоритмы.

Сообщение Azumi » 23 мар 2012, 15:59

slav0n, для привязки дисплея к примусу, Вы использовали самодельную библиотеку? Не поделитесь версиеи для кодвижна?
А то мне понравилось такое расположение ножек, чтоб все не на одном порту висело, а на разных, произвольно.
Azumi
 
Сообщения: 18
Зарегистрирован: 01 янв 2012, 23:30
Благодарил (а): 1 раз.
Поблагодарили: 0 раз.

Re: Исходники , алгоритмы.

Сообщение slav0n » 23 мар 2012, 16:26

Azumi писал(а):для привязки дисплея к примусу, Вы использовали самодельную библиотеку? Не поделитесь версиеи для кодвижна?

Для какого конкретно дисплея, символьного или графического? Да,и я пишу в WinAvr. Синтаксис немного отличается от кодвижена.
while(1||!1);
slav0n
Site Admin
 
Сообщения: 4341
Зарегистрирован: 15 ноя 2009, 18:43
Благодарил (а): 24 раз.
Поблагодарили: 385 раз.

Re: Исходники , алгоритмы.

Сообщение Azumi » 23 мар 2012, 16:45

Прошу прощения, забыл уточнить) Для символьного.
А библиотека подоидет от винавр к кодвижну?
Что-то все фанатеют по винавр и примеров в сети для него больше... Неужели он и правда лучше, или это просто дело привычки? Как-то раз пробовал, так мне оно показалось слишком усложненным.
Azumi
 
Сообщения: 18
Зарегистрирован: 01 янв 2012, 23:30
Благодарил (а): 1 раз.
Поблагодарили: 0 раз.

Сообщение slav0n » 23 мар 2012, 18:55

В общем-то библиотеки как таковой нет. Надо еще подумать - как представить то что написано в удобоваримом виде. :-)
А пока вот нашел - готовая библиотека AVR-GCC LCD library – mixed pin support
while(1||!1);
slav0n
Site Admin
 
Сообщения: 4341
Зарегистрирован: 15 ноя 2009, 18:43
Благодарил (а): 24 раз.
Поблагодарили: 385 раз.

Re: Исходники , алгоритмы.

Сообщение Azumi » 23 мар 2012, 20:00

Завтра на работе попробую, спасибо.
А сделать так, чтоб RW (пятую ногу), можно было повесить на землю - это сложно?
Вообще, планируется написать прошивку, чтобы проверить уже готовыи примус, но без карты. + попутно разобраться с дисплеем)

Я просто дисплеи недавно получил, специально для сборки примуса, а до этого не писал под них. Пытаюсь понять, что к чему)

Пока еще не разобрался, как вписывать свои знаки в свободные ячеики памяти, и как ножки в произвольные порты подключать.
Также, непонятно, зачем нужен 8 битныи режим, если 4 битныи прекрасно работает (я вообще далек от программирования, потому для меня это не очевидно).
Azumi
 
Сообщения: 18
Зарегистрирован: 01 янв 2012, 23:30
Благодарил (а): 1 раз.
Поблагодарили: 0 раз.

WinAVR подключение LCD HD44780

Сообщение slav0n » 24 мар 2012, 10:14

Вот немного кода. Можно настроить на любые ноги МК.
RW на корпус, 4-битный режим.
Код: Выделить всё
//===== определяем порты подключенные к индикатору ========
#define set_RS  PORTD |= (1<< 5)
#define clr_RS  PORTD &=~(1<< 5)
   
#define set_E   PORTD |= (1<< 4)
#define clr_E   PORTD &=~(1<< 4)
   
#define set_D4  PORTD |= (1<< 0)
#define clr_D4  PORTD &=~(1<< 0)
   
#define set_D5  PORTD |= (1<< 1)
#define clr_D5  PORTD &=~(1<< 1)
   
#define set_D6  PORTD |= (1<< 7)
#define clr_D6  PORTD &=~(1<< 7)
   
#define set_D7  PORTD |= (1<< 6)
#define clr_D7  PORTD &=~(1<< 6)

#define COM  0
#define DAT  -1


// =================== запись тетрады ======================
void Write4bit(char tetr)
{
   set_E;                   // устанавливаем бит Е

   if(tetr & 0x01) set_D4;
   else         clr_D4;
   if(tetr & 0x02) set_D5;
   else         clr_D5;
   if(tetr & 0x04) set_D6;
   else         clr_D6;
   if(tetr & 0x08) set_D7;
   else         clr_D7;

   clr_E;                // сбрасываем бит Е
   _delay_us(25);                       
}

// ====================запись команд/данных===============
void WriteComDat(char byte_wr, char rs)
{
   if(rs== COM)clr_RS;     // rs=0 - команды
   else       set_RS;     // иначе rs=1 - данные
   
   Write4bit(byte_wr>>4);  // записываем старшую тетраду         
   Write4bit(byte_wr);     // записываем младшую тетраду
   _delay_us(100);         // ждем 100 микросекунд
   
   if(rs==COM) _delay_ms(1);  // если была команда, то ждем еще 1 милисекунду
}

// ================= инициализация индикатора ============================
void InitLcd(void)   
{
// массив данных инициализации ЖКИ-индикатора
   const char byte_init[]={0x10,0x10,0x10,0x02,0x01,0x14,0x0C,0x2c};   

   for(unsigned char i=0;i<8;i++) WriteComDat(byte_init[i], COM);      
}

//=================== очистка экрана ====================================
void ClrScr(void)
{
   WriteComDat(1,COM);
   _delay_ms(5); // ждем 5 милисекунд
}

// ================== инициализация области CGRAM ========================
void InitCGram(unsigned char *buf)
{
   WriteComDat(0x40, COM); // установка видео-адреса в области CGRAM
   for(unsigned char i=0;i<64;i++) WriteComDat(*buf++, DAT); // загрузка символов в CGRAM
}

//=================== печать символа =====================================
void PrintSymbol(unsigned char symbol,unsigned char Position)
{
   WriteComDat(Position|0x80, COM); // установка видео-адреса
   WriteComDat(symbol, DAT);          // передача символа
}

while(1||!1);
slav0n
Site Admin
 
Сообщения: 4341
Зарегистрирован: 15 ноя 2009, 18:43
Благодарил (а): 24 раз.
Поблагодарили: 385 раз.

Re: Исходники, алгоритмы.

Сообщение AlekseiKO » 18 апр 2016, 03:48

Мужики не знал где написать, вот решил тут! Так что не пинайте за вопрос. Я не профи, просто любитель.
Вопрос не относится к примусу!
Значит так:
Есть мега 8, есть прошивка в hex , схема....
Короче собрал все в кучу, спаял, прошил мегу , выставил фьзы как требовалось.
Программа запустилась на меге.
3 кнопки. 1 меню, 2 +, 3 -
В меню выбираю значение "частоту" и начинаю ее повышать или уменьшать. Но при нажатии на кнопку значение прыгает через 1 и даже больше. (Пример: 20, 23, 25, 27, 30)
И если быстро быстро, резко резко , нажать на кнопку то только тогда как положено на 1 деление переключается.

Так вот вопрос. Время нажатия на кнопку чем определятся ? В коде программы? Или же номиналами деталей какими то?

Спасибо
AlekseiKO
 
Сообщения: 34
Зарегистрирован: 11 янв 2011, 09:50
Благодарил (а): 5 раз.
Поблагодарили: 1 раз.

След.

Вернуться в Я не волшебник, я только учусь...

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

cron