/******************************************************************************
 Title:    dual stepper sequencer
 Author:   rue_mohr
 Date:     
 Software: AVR-GCC 3.3 
 Hardware: attiny26
  

 
motor 0 step PB0 |-------U--------| PA0  motor 0 PH1
motor 1 step PB1 |                | PA1  motor 0 PH2
             PB2 |                | PA2  motor 0 PH3
             PB3 |                | PA3  motor 0 PH4
             VCC |     TINY26     | AGND
             GND |                | AVCC
motor 0 dir  PB4 |                | PA4  mtoor 1 PH1
mtoor 1 dir  PB5 |                | PA5  mtoor 1 PH2
             PB6 |                | PA6  mtoor 1 PH3
      reset  PB7 |----------------| PA7  mtoor 1 PH4
 
 

    
*******************************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include "binary.inc"
#include "commonStuff.h"

// port bit definitions
//#define Beeper              5



// commands


int steptable[] = { 1, 3, 0, 2 }; // grey counter state machine
int cheat[]     = { 0x0A, 0x06, 0x09, 0x05 }; // grey count with inversions


void Delay    ( unsigned int delay);
void stepMotor1(unsigned char dir) ;
void stepMotor2(unsigned char dir) ;
void PCIInit() ;

int main (void)  {
 
  int temp;
 
  DDRA = (OUTPUT << PA0 | OUTPUT << PA1 |OUTPUT << PA2 |OUTPUT << PA3 |OUTPUT << PA4 | OUTPUT << PA5 |OUTPUT << PA6 |OUTPUT << PA7);
  DDRB = (INPUT << PB0 | INPUT << PB1 | INPUT << PB2 | INPUT << PB3 | INPUT << PB4 | INPUT << PB5 |INPUT << PB6 |INPUT << PB7);
 
  PCIInit();
  sei();
 
  while(1) {          
    Delay(10000);  
  }
 
}
    
//------------------------| FUNCTIONS |------------------------


//------| Other Functions |--------

// this is an interrupt-friendly delay

void Delay(unsigned int delay) {
  unsigned int x;
  for (x = delay; x != 0; x--) {
    asm volatile ("nop"::);
    asm volatile ("nop"::);
    asm volatile ("nop"::);
    asm volatile ("nop"::);
    asm volatile ("nop"::);
    asm volatile ("nop"::);
    asm volatile ("nop"::);
    asm volatile ("nop"::);
    asm volatile ("nop"::);
    asm volatile ("nop"::);
    asm volatile ("nop"::);
    asm volatile ("nop"::);
    asm volatile ("nop"::);
    asm volatile ("nop"::);
    asm volatile ("nop"::);
    asm volatile ("nop"::);     
  }
}

void PCIInit() {
  SetBit(PCIE0, GIMSK); // PCI B0:3 enable the interrupt !!!PROCESSOR!!!!
}


SIGNAL (SIG_PIN_CHANGE) { 
  char tPINB;
  char Change;
  static char oPINB;
  
  tPINB  = PINB;                                 // always snapshot first  
  Change = tPINB ^ oPINB;                        // find pin changes
  Change &= tPINB;                               // this will now just be high edges
  if (Change & 0x01) stepMotor1(tPINB & 0x10);   // filter out rising edges for motor 1 
  if (Change & 0x02) stepMotor2(tPINB & 0x20);   // filter out rising edges for motor 2    
  oPINB = tPINB;                                 // update state tracking.
}


void stepMotor1(unsigned char dir) {
  static char index = 0;
  char temp;
  
  index = steptable[index];
  if (dir) index = (~index & 3);
  temp = (PORTA & 0xF0) | cheat[index];
  PORTA = temp;
}


void stepMotor2(unsigned char dir) {
  static char index = 0;
  char temp;
  
  index = steptable[index];
  if (dir) index = (~index & 3);
  temp = (PORTA & 0x0F) | (cheat[index]<<4);
  PORTA = temp;
}





