/* Enoder example

Simple program to test a rotary encoder with pushbutton

Setup:

         +----------------+
  LED -- | P1.0      P2.6 | -- NC 
  LED -- | P1.1      P2.7 | -- Push Button
  LED -- | P1.2           |       
  LED -- | P1.3           |       
  LED -- | P1.4      P1.7 | -- Encoder B
  LED -- | P1.5      P1.6 | -- Encoder A
         +----------------+

Function:
 * Every time the encoder is pushed the LED on P1.0 will be toggled
 * The LED on P1.1 to P1.5 will move left/right according to the encoder
 * The script uses the internal pullup resistors

*/

#include <io.h>
#include <signal.h>

unsigned char encoder_pos = BIT3; // Set starting pos to P1.3
unsigned char push_pos = 0;

// interrupt function toggling P1.0 on every push of encoder
interrupt (PORT2_VECTOR) p1_encoder_int(){
  dint();

  if( P2IFG & 0x80 ) {
    push_pos ^= BIT0;
    P1OUT = BIT7 | BIT6 | encoder_pos | push_pos; // output P1 with push status and encoder pos
  }
  P2IFG = 0x00;
  eint();
}

// interrupt function moving positin bit per encoder
interrupt (PORT1_VECTOR) p1_encoder_move(){
  dint();

  if( P1IFG & 0x40 ) {
    if ( P1IN & BIT7 ) { // b is high -> counter clockwise
      if ( encoder_pos > BIT1 ) { // only move down if not already at bottom
        encoder_pos = encoder_pos >> 1;
      } 
    } else { // b is low -> clockwise
      if ( encoder_pos < BIT5 ) {
        encoder_pos = encoder_pos << 1;
      }
    }
    P1OUT = BIT7 | BIT6 | encoder_pos | push_pos; // output P1 with push status and encoder pos
  }
  P1IFG = 0x00;
  eint();
}

int main(void) {
  WDTCTL = WDTPW | WDTHOLD;

  // Setup port
  P1SEL = 0x00;  // select io function for all ports (this is actually default for P1)
  P1REN = 0xC0;  // select pullup resistors for pin 1.7 and 1.6
  P1DIR = 0x3F;  // iioo oooo 
  P1OUT = 0xC8;  // need to set P1.6 and P1.7 to high so PULLUP resistor will be selected 
  P1IES = 0x00;  // select low to high transition for interrupts on all port pins (this actually the default)
  P1IE  = 0x40;  // enable interrupt for P1.6 to reader status of encoder every time Encoder sigal A goes high
  P1IFG = 0x00;  // clear interrupt register

  P2SEL = 0x00;  // selection io function for all ports (default is actually XIN.XOUT for P2.7/2.6)
  P2REN = 0x80;  // select pullup resistors for pin 2.7
  P2DIR = 0x7F;  // iooo oooo 
  P2OUT = 0x80;  // need to set P2.7 to high so PULLUP resistor will be selected 
  P2IES = 0x00;  // select low to high transition for interrupts on all port pins
  P2IE  = 0x80;  // enable interrupt P2.7 for push button
  P2IFG = 0x00;  // clear interrupt register

  eint();

  for (;;) {
    // loop forever
  }
 
}


