#include "sav_button.h"

/**
 * Конструктор класса кнопки
 * Кнопка это цифровой пин подтянутый к питанию и замыкаемый на землю
 * Событие срабатывания происходит по нажатию кнопки (возвращается 1)
 * и отпусканию кнопки (возвращается время нажатия кнопки, мсек)
 * tm1 - таймаут дребезга контактов. По умолчанию 50мс
 * tm2 - время длинного нажатия клавиши. По умолчанию 2000мс
 * tm3 - врямы перевода кнопки в генерацию серии нажатий. По умолсанию отключено
 * tm4 - время между кликами в серии. По умолчанию 500 мс. Если tm3 = 0 то не работает
 */
SButton::SButton(uint8_t pin,uint16_t tm1, uint16_t tm2,uint16_t tm3, uint16_t tm4){
   Pin               = pin;
   State             = false;
   Long_press_state  = false;
   Auto_press_state  = false;
   Ms1               = 0;
   Ms2               = 0;
   Ms_auto_click     = 0;
   TM_bounce         = tm1;
   TM_long_click     = tm2;
   TM_auto_click     = tm3;
   Period_auto_click = tm4;
}

/**
 * Инициализация кнопки
 */
void SButton::begin() {
   pinMode(Pin, INPUT_PULLUP);
#ifdef DEBUG_SERIAL      
   Serial.print("Init button pin ");
   Serial.println(Pin);
#endif      
}

/**
 * Действие производимое в цикле или по таймеру
 * возвращает SB_NONE если кнопка не нажата и событие нажатие или динного нажатия кнопки
*/
SBUTTON_CLICK SButton::Loop() {
   uint32_t ms = millis();
   bool pin_state = digitalRead(Pin);
// Фиксируем нажатие кнопки 
   if( pin_state == LOW && State == false && (ms-Ms1)>TM_bounce ){
       uint16_t dt = ms - Ms1;
       Long_press_state = false;
       Auto_press_state = false;
#ifdef DEBUG_SERIAL      
       Serial.print(">>>Event button, pin=");
       Serial.print(Pin);
       Serial.print(",press ON, tm=");
       Serial.print(dt);
       Serial.println(" ms");
#endif      
       State = true;
       Ms2    = ms;
       if( TM_long_click == 0 && TM_auto_click == 0 )return SB_CLICK;
   }

// Фиксируем длинное нажатие кнопки   
   if( pin_state == LOW && !Long_press_state && TM_long_click>0 && ( ms - Ms2 )>TM_long_click ){
      uint16_t dt      = ms - Ms2;
      Long_press_state = true;
#ifdef DEBUG_SERIAL      
      Serial.print(">>>Event button, pin=");
      Serial.print(Pin);
      Serial.print(",long press, tm=");
      Serial.print(dt);
      Serial.println(" ms");
#endif 
      return SB_LONG_CLICK;
   }

// Фиксируем авто нажатие кнопки   
   if( pin_state == LOW && TM_auto_click > 0 
       && ( ms - Ms2 ) > TM_auto_click 
       && ( ms - Ms_auto_click ) > Period_auto_click ){
      uint16_t dt      = ms - Ms2;
      Auto_press_state = true;
      Ms_auto_click    = ms;
#ifdef DEBUG_SERIAL      
      Serial.print(">>>Event button, pin=");
      Serial.print(Pin);
      Serial.print(",auto press, tm=");
      Serial.print(dt);
      Serial.println(" ms");
#endif 
      return SB_AUTO_CLICK;
   }

   
// Фиксируем отпускание кнопки 
   if( pin_state == HIGH && State == true  && (ms-Ms2)>TM_bounce ){
       uint16_t dt      = ms - Ms2;
// Сбрасываем все флаги       
       State            = false;
#ifdef DEBUG_SERIAL      
       Serial.print(">>>Event button, pin=");
       Serial.print(Pin);
       Serial.print(",press OFF, tm=");
       Serial.print(dt);
       Serial.println(" ms");
#endif 
      Ms1    = ms;
// Возвращаем короткий клик      
      if( (TM_long_click != 0 || TM_auto_click != 0) && !Long_press_state && !Auto_press_state )return SB_CLICK;
       
   }


   return SB_NONE;
}     

