
#include <avr/io.h>
#include "binary.h"

#define OUTPUT  1
#define INPUT   0

#define forward  1
#define backward 0

  unsigned char stateTableBackward[] = {  
      (3)+(b0001<<4),                    
      (0)+(b0010<<4),
      (1)+(b0100<<4),
      (2)+(b1000<<4)
   };  
   
  unsigned char stateTableForward[] = {  
      (1)+(b0001<<4),                    
      (2)+(b0010<<4),
      (3)+(b0100<<4),
      (0)+(b1000<<4)
   }; 

struct stepper4ph_t {      
      unsigned Port       :3;
      unsigned MotorNum   :1;
      unsigned State      :3;
      unsigned Direction  :1;
} ;

typedef struct stepper4ph_t stepper4ph;

// -------- function declerations ------------

void stepmotor (stepper4ph * motor);
void Delay(int delay);
void inline changeIO(char port, char mask, char bits);

int main () {

   unsigned long x;
   stepper4ph motor1, motor2; // "make a motor"
 
    // set up directions 
    DDRA = (INPUT << PA0 | INPUT << PA1 |INPUT << PA2 |INPUT << PA3 |INPUT << PA4 |INPUT << PA5 |INPUT << PA6 |INPUT << PA7);
    DDRB = (OUTPUT << PB0 | OUTPUT << PB1 |OUTPUT << PB2 |OUTPUT << PB3 |OUTPUT << PB4 |OUTPUT << PB5 |OUTPUT << PB6 |OUTPUT << PB7);
    DDRC = (OUTPUT << PC0 | OUTPUT << PC1 |OUTPUT << PC2 |OUTPUT << PC3 |INPUT << PC4 |INPUT << PC5 |INPUT << PC6 |INPUT << PC7);
    DDRD = (INPUT << PD0 | INPUT << PD1 |INPUT << PD2 |INPUT << PD3 |INPUT << PD4 |INPUT << PD5 |INPUT << PD6 |INPUT << PD7);

  motor1.Port     = 1; // 0 = portA, so this is port C
  motor1.MotorNum = 0; // 0 is bits 0-3, 1 is bits 4-7
  motor1.Direction = forward;

  motor2.Port     = 1;
  motor2.MotorNum = 1;
  motor2.Direction = forward; //backward;

 // while(1){
      
   for (x = 347; x != 0; x--) {   
     stepmotor(&motor1);
     stepmotor(&motor2);
     Delay(50000);   
   }
   
   while(1){
     asm volatile ("nop"::); 
   }

 // }
}


void stepmotor (stepper4ph * motor) {
          
   unsigned const char *  stateTable;
   unsigned char temp, mask;
   
   stateTable = stateTableBackward;                      //choose state table
   if (motor->Direction == forward) {
      stateTable = stateTableForward;
   } 
   
   motor->State  = (*(stateTable + motor->State) & 0x0F); // execute state machine
   temp =  (*(stateTable + motor->State) & 0xF0);
   
   mask = 0x0F;                                           // choose bit positions
   if (motor->MotorNum == 0) { temp >>= 4; mask = 0xF0; }
  
   changeIO( motor->Port, mask, temp);                    // change io bits
  
  }

void inline changeIO(char port, char mask, char bits) {
 switch (port) {
     case 0:
        PORTA = (PORTA&mask)|bits;
        break;
     case 1:
        PORTB = (PORTB&mask)|bits;
        break;
     case 2:
        PORTC = (PORTC&mask)|bits;
        break;
     case 3:
        PORTD = (PORTD&mask)|bits;
        break;
    }
}

void Delay(int delay) {
  int x;
  for (x = delay; x != 0; x--) {
    asm volatile ("nop"::); 
  }
}

