#ifndef _ENCODER_ 
#define _ENCODER_ 1
/*********************************************************************
Модуль программной поддержки контактного квадратурного энкодера
типа РЕС16 и аналогичных (без использования прерываний)

Copyright 2008 © ARV Research.

Внимание! Вы можете использовать данный модуль по своему усмотрению
в любых проектах. При любой публикации ваших проектов, использующих
этот модуль, следует указать ссылку на сайт http://arv.radioliga.com

Требуется компилятор WinAVR
**********************************************************************/

#define ENC_MAX_SPEED   100     /* максимальная "скорость" вращения энкодера */
#define ENC_BIG_STEP    98      /* "большой" шаг при быстром вращении */
#define ENC_FAST_ROTATE 90      /* константа "быстрого" вращения */

#define ENC_A_PIN       3       /* номер линии порта для сигнала А энкодера */
#define ENC_B_PIN       6       /* номер линии порта для сигнала B энкодера */
#define ENC_A_PORT      PIND    /* порт, к которому подключен сигнал А энкодера */
#define ENC_B_PORT      PINB    /* порт, к которому подключен сигнал B энкодера */

#define ENC_A_UP        (ENC_A_PORT & (1<<ENC_A_PIN))
#define ENC_B_UP        (ENC_B_PORT & (1<<ENC_B_PIN))
#define ENC_A_DN        (!ENC_A_UP)
#define ENC_B_DN        (!ENC_B_UP)

#define rotate_fast(x)  (x > ENC_FAST_ROTATE)
#define DDR(x)          (*(&x + 1))
#define PORT(x)         (*(&x + 2))
/*
Использование модуля элементарно: в начале программы следует вызвать
функцию enc_init(), которая настроит нужные порты ввода-вывода.
Затем в основном цикле в нужном месте можно обратиться либо к
функции enc_rotate(), которая вернет значение, соответствующее направлению
вращения энкодера, либо функцию enc_delta(), которая кроме направления
возвратит и условную величину скорости вращения.
enc_rotate() позволяет использовать энкодер, как 2 кнопки "+1" и "-1"
enc_delta() уже может заменить 4 кнопки "+1", "+100", "-1" и "-100".
Функция способна отличать "рывки туда-сюда" от простого вращения в
одном направлении.

Нажатие встроенной кнопки энкодера НЕ ОБРАБАТЫВАЕТСЯ
*/


// инициализирует порты, к которым подключен энкодер
void enc_init(void);

/* возвращает направление и скорость вращения энкодера
 параметр speed - указатель на переменную, в которую возвращается 
 условная скорость вращения (число от 0 до 100)

 возвращает:
     -1 - вращение влево (против часовой стрелки)
      0 - нет вращения
      1 - вращение вправо (по часовой стрелке)

 ВНИМАНИЕ! функция выполняется достаточно длительное время: 
 максимально (при остановленном энкодере) ENC_MAX_SPEED миллисекунд, 
 при вращении возвращает управление раньше
*/      
signed char enc_rotate(unsigned char * speed);

/* возвращает приращение энкодера: 
    1 или -1 при медленном вращении,
    0 - при остановленном
    ENC_BIG_STEP или -ENC_BIG_STEP при быстром вращении

 ВНИМАНИЕ!!! Функция выполняется долго!!!
 при быстром вращении возвращает управление только ПОСЛЕ ОСТАНОВКИ энкодера!
 остановкой считается, если в течение 2*ENC_MAX_SPEED миллисекунд не было импульсов
 с энкодера.
*/
signed char enc_delta(void);

#endif
