Charles Young's development fork. Going forward I only want to push mature code to main repository.

Dependencies:   mbed

Fork of GEO_COUNTER_L432KC by Geo Electronics "Geo Counter"

RotarySwitch.cpp

Committer:
Charles David Young
Date:
2018-09-06
Revision:
42:204c99cf3fde
Parent:
38:1642320d83a0
Child:
43:f330ec39b8b4

File content as of revision 42:204c99cf3fde:

/**
 * @author Charles Young
 *
 */

#include "RotarySwitch.hpp"

// QEI class supports the mode wheel.  In its most basic function it will tell
// us which direction the wheel is moving (right or left) so that we can
// use it to select the current mode.
QEI Wheel(D12, D11, NC, 16);    // Quadrature encoder

RotarySwitch::RotarySwitch()
{
   LED_status_index = 0;
   LED_status_reported = LED_status_index;
   WheelCurrent = 0;
   WheelPrevious = 0;
   QEPBpressed = false;
   WheelStateTimer = 0;
   
   LEDs_write(0x00);   // initialize LEDs (CPM and CNT1 on)
   Wheel.reset();
}

int RotarySwitch::GetPosition(void)
{
   return LED_status_reported;
}

//---------------------------------------------------------------------------
//Write to 74HC595 (LEDs) - Take care to avoid conflict with MAX7219

void RotarySwitch::LEDs_write(unsigned short data_val)       
{                       
#define DT      1      // delay time in us for SPI emulation

    // Update 74HC595 shift registers 
    unsigned short mask;
    
    SCK = 0;
    wait_us(DT);
    CS2 = 0;    
    
    for(mask = 0x80; mask!= 0; mask>>= 1)
    {
      wait_us(DT);
      SCK = 0;
      if(mask & data_val)
        MOSI = 0;
      else
        MOSI = 1;
      wait_us(DT);
      SCK = 1;
    }
    
    SCK = 0;
    wait_us(DT);
    CS2 = 1;

    return; 
}

void RotarySwitch::UpdateOutput()   
{
    // Blink mode LED
    if (WHEEL_SUBMODE_SELECT == currentWheelState)
       LEDs_write(0);

   if (WheelStateTimer)
   {
      WheelStateTimer++;
      if (++WheelStateTimer > WheelStateTimeout)
      {
         WheelStateMachine(WHEEL_Timeout);
         WheelStateTimer = 0;
      }
   }
}

float RotarySwitch::UpdateInput()   
{
   float direction = 0; // used to return direction of rotation
   
   if (WHEEL_INACTIVE == currentWheelState)
      LEDs_write(0);
   else
      LEDs_write(0x01 << LED_status_index);
        
   // react to wheel if in proper state
   WheelCurrent = int(Wheel.getPulses());
   if (   (WHEEL_MODE_SELECT    == currentWheelState)
       || (WHEEL_SUBMODE_SELECT == currentWheelState))
   {
      if (WheelCurrent > WheelPrevious)
      {
         if (WHEEL_MODE_SELECT == currentWheelState)
            LED_status_index = ++LED_status_index % LED_status_index_size;
         else
            direction = 1;
      }
      else
         if (WheelCurrent < WheelPrevious)
         {
            if (WHEEL_MODE_SELECT == currentWheelState)
               LED_status_index = --LED_status_index % LED_status_index_size;
            else
               direction = -1;
         }

      // only report back mode once selected
      if (WHEEL_SUBMODE_SELECT == currentWheelState)
         LED_status_reported = LED_status_index;
      else // don't report anything if not in submode
         LED_status_reported = LED_status_index_size;
      
     // Keep resetting WheelStateTimer as long as wheel is moving
     if (WheelPrevious != WheelCurrent)
        WheelStateTimer = 1;
   }
   WheelPrevious = WheelCurrent;

   // detect when wheel button is pressed but wait until it is released
   // before doing anything
   bool QEPBbutton = QEPB.read();
   if (   (QEPBbutton)
       && (!QEPBpressed))
   {
      QEPBpressed = true;
   }
   else
      if (   (!QEPBbutton)
          && (QEPBpressed))
      {
         QEPBpressed = false;
         WheelStateMachine(WHEEL_Pressed);
      }
    
   return direction;
}

void RotarySwitch::WheelStateMachine(WheelStateEvent event)
{                       
   switch (currentWheelState) {
      case WHEEL_INACTIVE:
      if (WHEEL_Pressed == event)
      {
         currentWheelState = WHEEL_MODE_SELECT;
         WheelStateTimer = 1;
      }
      break;
      case WHEEL_MODE_SELECT:
      if (WHEEL_Pressed == event)
      {
         currentWheelState = WHEEL_SUBMODE_SELECT;
         WheelStateTimer = 1;
      }
      else
         if (WHEEL_Timeout == event)
            currentWheelState = WHEEL_INACTIVE;
      break;
      case WHEEL_SUBMODE_SELECT:
      if (WHEEL_Pressed == event)
      {
         currentWheelState = WHEEL_MODE_SELECT;
         WheelStateTimer = 1;
      }
      else
         if (WHEEL_Timeout == event)
            currentWheelState = WHEEL_INACTIVE;
      break;
      default:
      break;
   }
}