

#define SERIAL_SPEED 57600
#define PARAMETR_LENGTH 2 // delka parametru - 2 byty je cislo -32768 az 32767
#define MESSAGE_LENGTH 3 // jeden byte je prikaz typu Command
#define ENABLE 8
#define X_STEP 2
#define X_DIR  5
#define Y_STEP 3
#define Y_DIR  6  
#define Z_STEP 4
#define Z_DIR 7

enum Command {
  KO = 0, // odpoved neco je spatne
  OK = 1, // rozkaz prijaty
  STATUS = 2, // mame spojeni?
  X_MOVE = 3, // prikaz na bliknuti diody x-krat
  TIME_DELAY = 4, // prikaz na nastaveni casu mezi blikancema v ms
  Y_MOVE =5,
};
// příkazy 0-4 jsem zachoval, X bliknutí by mělo znamenat x posuvů dle nastavených parametrů v LAbview(Tom)

bool is_connected = false;
enum Command received;
short parametr;
unsigned long time_delay = 500; // pocatecni hodnota casove konstanty
void setup() {
  Serial.begin(SERIAL_SPEED);
  pinMode(X_STEP, OUTPUT); // krokový pin
  pinMode(X_DIR,  OUTPUT); // směrový pin
  pinMode(Y_STEP, OUTPUT); // krokový pin
  pinMode(Y_DIR,  OUTPUT); // směrový pin
  pinMode(ENABLE, OUTPUT); // nastavení příslušných pinů
  digitalWrite(X_DIR,HIGH); // nastavení směru otáčení
  
  motorStep(500); // 500 mikroposuvů, jestli to funguje

  while(!is_connected)
  {
    send_command(STATUS);
    wait_for_message(1000);
    get_message();
  }
}

void loop() {
// tady se opakuje porad dokola cekani na prikaz
// a provedeni prikazu
  wait_for_message(1000);
  get_message();
}
 void motorStep( short count){
   if (count>= 0)
   digitalWrite(X_DIR,HIGH);
   else
   digitalWrite(X_DIR,LOW);
   
   for(int i = 0; i < round(abs(count)/6); i++) 
   { 
        
        short xtime_a = map(i,0,round(abs(count)/6),1000,time_delay);
        digitalWrite(X_STEP,HIGH); 
        delayMicroseconds(xtime_a); 
        digitalWrite(X_STEP,LOW); 
        delayMicroseconds(xtime_a);
 
    }
     for(int i = 0; i < round(abs(2*count)/3); i++) 
   { 
        digitalWrite(X_STEP,HIGH); 
        delayMicroseconds(time_delay); 
        digitalWrite(X_STEP,LOW); 
        delayMicroseconds(time_delay);
 
    }
     for(int i = 0; i < round(abs(count)/6); i++) 
   { 
        short xtime_b = map(i,0,round(abs(count)/6),time_delay,1000);
        digitalWrite(X_STEP,HIGH); 
        delayMicroseconds(xtime_b); 
        digitalWrite(X_STEP,LOW); 
        delayMicroseconds(xtime_b);
 
    }
   
   
    
}
void motorStepy( short count){
   if (count>= 0)
   digitalWrite(Y_DIR,HIGH);// změnit na ypsilony a nahoře definovat
   else
   digitalWrite(Y_DIR,LOW);
   
   for(int i = 0; i < round(abs(count)/6); i++) 
   { 
        
        short ytime_a = map(i,0,round(abs(count)/6),1000,time_delay);
        digitalWrite(Y_STEP,HIGH); 
        delayMicroseconds(ytime_a); 
        digitalWrite(Y_STEP,LOW); 
        delayMicroseconds(ytime_a);
 
    }
     for(int i = 0; i < round(abs(2*count)/3); i++) 
   { 
        digitalWrite(Y_STEP,HIGH); 
        delayMicroseconds(time_delay); 
        digitalWrite(Y_STEP,LOW); 
        delayMicroseconds(time_delay);
 
    }
     for(int i = 0; i < round(abs(count)/6); i++) 
   { 
        short ytime_b = map(i,0,round(abs(count)/3),time_delay,1000);
        digitalWrite(Y_STEP,HIGH); 
        delayMicroseconds(ytime_b); 
        digitalWrite(Y_STEP,LOW); 
        delayMicroseconds(ytime_b);
 
    }
    
    
}


void wait_for_message(unsigned long timeout) // cekani na prikaz
{
  unsigned long start_time = millis();
  while( (Serial.available() < MESSAGE_LENGTH) && (millis()-start_time < timeout)){}
}


// tady je nacteni prikazu a parametru
// a zpracovani prikazu
// kdyz si na zacatku pridas do toho
// "enum Command" dalsi prikazy,
// tak semka muzes dodat dalsi case
void get_message()
{
    received = read_command();
    parametr = read_parametr();
    switch(received)
    {
      case STATUS: // tady je inicializace konverzace mezi bazmekama
        is_connected = true;
        send_command(OK);
        break;

      case X_MOVE: // priklad, jak se vola funkce s parametrem
        motorStep(parametr);
        send_command(OK);
        break;
       case Y_MOVE: // priklad, jak se vola funkce s parametrem
        motorStepy(parametr);
        send_command(OK);
        break;

      case TIME_DELAY: // priklad, jak se meni globalni promenna
        time_delay = (unsigned long)abs(parametr);
        send_command(OK);
        break;

      default:
      break;
    }
    
}

Command read_command() // precteni prikazu ze serioveho portu
{
  return (Command) Serial.read();
}

short read_parametr() // precteni parametru ze serioveho portu
{
  size_t i=0;
  int c;
  byte par[2];
  short navrat;
  while (i < PARAMETR_LENGTH)
  {
    c = Serial.read();
    if (c<0) break;
    par[i++]=(byte)c;
  }
  navrat = *(short *)par;
  return navrat;
}

void send_command(enum Command command) // poslani prikazu nebo statusu na seriovy port
{
  uint8_t* Command = (uint8_t*) &command;
  Serial.write(Command, sizeof(uint8_t));
}
