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-04
Revision:
23:41260ab0f49d
Parent:
20:fb73eaaf0894
Child:
24:db7494389c03

File content as of revision 23:41260ab0f49d:

/**
 * @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

#define CPM     0x01
#define CPS     0x02
#define PLS     0x04
#define VOLTS   0x08
#define CNT1    0x10
#define CNT2    0x20
#define HV      0x40
#define MENU    0x80
uint8_t LED_statuses[] = {CPM, CPS, PLS, VOLTS, CNT1, CNT2, HV, MENU};

RotarySwitch::RotarySwitch()
{
   LED_status = CPM;
   LED_status_index = 0;
   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_index;
}

//---------------------------------------------------------------------------
//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_MODE_SELECT == currentWheelState)
       LEDs_write(0);

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

void RotarySwitch::UpdateInput()   
{               
   if (WHEEL_INACTIVE_SELECT == currentWheelState)
      LEDs_write(0);
   else
      LEDs_write(LED_statuses[LED_status_index]);
        
   // react to wheel if in proper state
   WheelCurrent = int(Wheel.getPulses());
   if (   (WHEEL_MODE_SELECT    == currentWheelState)
       || (WHEEL_SUBMODE_SELECT == currentWheelState))
   {
     if (WHEEL_MODE_SELECT == currentWheelState)
     {
        if (WheelCurrent > WheelPrevious)
           LED_status_index = ++LED_status_index % sizeof(LED_statuses);
        else
            if (WheelCurrent < WheelPrevious)
               LED_status_index = --LED_status_index % sizeof(LED_statuses);
     }
     // 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;
}

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;
   }
}