
#include "config.h"
#include "delay.h"
#include "serial.c"
#include "serio.c"

// interrupt-driven rotary encoder, no debounce

#define S0 0
#define S1 1
#define S2 2
#define S3 3

volatile unsigned char state, last_state;
volatile unsigned char count, last_count;

void update_state(void){
  state = PORTB & 0x3;
  switch(state) {
  case S0:
    if (last_state == S1) count++;
    else if (last_state == S2) count--;
    break;
  case S1:
    if (last_state == S3) count++;
    else if (last_state == S0) count--;
    break;
  case S2:
    if (last_state == S0) count++;
    else if (last_state == S3) count--;
    break;
  case S3:
    if (last_state == S2) count++;
    else if (last_state == S1) count--;
    break;
  }
  if (last_count != count) {
    // valid pulse
    last_state = state;
    last_count = count;
  } else {
    // invalid transistion, reset last state
    last_state = state;
  }
}

#if defined(HI_TECH_C)
void interrupt pic_isr(void)
#endif
#if defined(__18CXX)
#pragma interrupt pic_isr
void pic_isr(void)
#endif
{
  if (INT0IF || INT1IF) {
    if (INT0IF) {
      INT0IF = 0;
      // toggle active edge
      if (INTEDG0) INTEDG0 = 0; else INTEDG0 = 1;
    }
    if (INT1IF) {
      INT1IF = 0;
      // toggle active edge
      if (INTEDG1) INTEDG1 = 0; else INTEDG1 = 1;
    }
    update_state();
  }
}

void main(void){
  unsigned char count_old;

  // set RB0, RB1 for input
  TRISB0 = 1;TRISB1 = 1;
  RBPU = 0; // enable weak pullups

  if (RB0) INTEDG0 = 0; // falling edge
  else INTEDG0 = 1;
  if (RB1) INTEDG1 = 0; // falling edge
  else INTEDG1 = 1;

  last_state = PORTB & 0x03; // init last state
  serial_init(95,1); // 19200 in HSPLL mode, crystal = 7.3728 MHz
  pcrlf();  printf("Rotary Test Started");  pcrlf();
  // enable INT0,INT1 interrupts
  IPEN = 0;  INT0IF = 0; INT0IE = 1; 
  INT1IF = 0; INT1IE = 1; 
  PEIE = 1;  GIE = 1;
  printf("No Debounce");  pcrlf();
  printf("Rotary Switch Test Started");
  pcrlf();
  count = 0; count_old = 0;
  while(1) {
    //tip: don't put volatile chars in printfs, may change 
    // by the time the printf gets around to printing it!
    if (count != count_old){
      count_old = count;
      printf("Count: %x",count_old);
      pcrlf();
    }
  }
}

//for MCC18, place the interrupt vector goto
#if defined(__18CXX)
#if defined(HIGH_INTERRUPT)
#pragma code HighVector=HIGH_INTERRUPT
#else
#pragma code HighVector=0x0008  
#endif
void HighVector (void)
{
    _asm goto pic_isr _endasm
}
#pragma code
#endif





