/*****************************************************************************

    source::worx libPiGPio
    Copyright © 2022 c.holzheuer
    chris@sourceworx.org

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    Uses:

    pigpiod_if2 by joan2937, pigpio @ abyz.me.uk
    https://abyz.me.uk/rpi/pigpio

    sigslot  by 2017 Pierre-Antoine Lacaze
    https://github.com/palacaze/sigslot

***************************************************************************/


#include <iostream>
#include <pigrotarydial.h>

/**

             +---------+         +---------+      0
             |         |         |         |
   A         |         |         |         |
             |         |         |         |
   +---------+         +---------+         +----- 1

       +---------+         +---------+            0
       |         |         |         |
   B   |         |         |         |
       |         |         |         |
   ----+         +---------+         +---------+  1

*/

pigRotaryDial::pigRotaryDial()
{

}

pigRotaryDial::pigRotaryDial( pigpio::bcm_t bcmButton, pigpio::bcm_t bcmUp, pigpio::bcm_t bcmDown )
{
    init( bcmButton, bcmUp, bcmDown );
}


pigRotaryDial::~pigRotaryDial()
{

}


void pigRotaryDial::init( pigpio::bcm_t bcmButton, pigpio::bcm_t bcmUp, pigpio::bcm_t bcmDown )
{

    pigButton::init( bcmButton );

    _pinUp.init( bcmUp, pull_up );
    _pinUp.set_callback( this );
    _pinUp.set_glitch_filter( 1000 );

    _pinDown.init( bcmDown, pull_up );
    _pinDown.set_callback( this );
    _pinDown.set_glitch_filter( 1000 );

    _oldState = ( _pinUp.get_level() << 1 ) | _pinDown.get_level();

}


void pigRotaryDial::reset()
{
    _state = false;
    _value = 0;
}



void pigRotaryDial::trigger( pigpio::bcm_t bcm, uint32_t level )
{
     if( level == pigpio::TimeOut )
         return;

     if( bcm ==_pinIn.bcm  )
     {
         // simply on/off
         toggle_state();
         return;
     }

     if( bcm ==_pinUp.bcm )
         _levUp = level;
     else
         _levDown = level;

     int newState = _levUp << 1 | _levDown;
     int inc = Transits[ _oldState << 2 | newState ];

     if( inc )
     {
         _oldState = newState;
         //int detent = _value / 4;
         _value += inc;

         //if( detent != ( _step / 4) )
         //    handlePulse( _step / 4 );
         //handlePulse( _step );

         sigValue( _value );
     }

}
