/*
* Copyright (C) 2018 dimercur
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/**
* \file robot.h
* \author L.Senaneuch
* \version 1.0
* \date 06/06/2017
* \brief Fonctions for communicating with robot.
*/
#include "robot.h"
int fd;
int getChar(char * c);
int readSerial(char * msg);
char checkSumGO(char * msg);
int receiveMsg(void);
int sendCmd(char cmd, const char * arg);
int open_communication_robot(const char * path)
{
#ifndef __STUB__
struct termios options;
fd = open(path, O_RDWR | O_NOCTTY | O_NDELAY);
if(fd !=-1)
{
fcntl(fd, F_SETFL, 0);
tcgetattr(fd, &options);
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
cfsetospeed (&options, B9600);
cfsetispeed (&options, B9600);
options.c_cc[VMIN]=0;
options.c_cc[VTIME]=0;
tcsetattr(fd, TCSANOW, &options);
return 0;
}
else
{
perror("can't openSerial");
return -1;
}
#else
return 0;
#endif
}
int close_communication_robot(void)
{
#ifndef __STUB__
return close(fd);
#else
return 0;
#endif
}
int send_command_to_robot(char cmd, const char * arg)
{
#ifndef __STUB__
sendCmd(cmd,arg);
// TODO : check return from sendCmd
return receiveMsg();
#else
int reponse;
switch(cmd)
{
case DMB_PING:
reponse = 0;
break;
case DMB_IDLE:
reponse = 0;
break;
case DMB_START_WITH_WD:
reponse = 0;
break;
case DMB_RELOAD_WD:
reponse = 0;
break;
case DMB_GET_VBAT:
reponse = 2;
break;
case DMB_IS_BUSY:
reponse = 1;
break;
case DMB_START_WITHOUT_WD:
reponse = 0;
break;
case DMB_MOVE:
reponse = 0;
break;
case DMB_TURN:
reponse = 0;
break;
case DMB_GO_FORWARD:
reponse = 0;
break;
case DMB_GO_BACK:
reponse = 0;
break;
case DMB_GO_LEFT:
reponse = 0;
break;
case DMB_GO_RIGHT:
reponse = 0;
break;
case DMB_STOP_MOVE:
reponse = 0;
break;
default:
reponse = 0;
break;
}
return reponse;
#endif
}
/****************************/
/* PRIVATE */
/****************************/
int sendCmd(char cmd, const char * arg)
{
char cmdWithArg[20]={};
cmdWithArg[0]=cmd;
switch(cmd)
{
case DMB_GO_FORWARD: strcpy(cmdWithArg,"M=+64000");
break;
case DMB_GO_BACK: strcpy(cmdWithArg,"M=-64000");
break;
case DMB_GO_LEFT: strcpy(cmdWithArg,"T=+64000");
break;
case DMB_GO_RIGHT: strcpy(cmdWithArg,"T=-64000");
break;
case DMB_STOP_MOVE: strcpy(cmdWithArg,"M=0");
break;
case DMB_MOVE: strcat(cmdWithArg,"=");
strcat(cmdWithArg,arg);
break;
case DMB_TURN: strcat(cmdWithArg,"=");
strcat(cmdWithArg,arg);
break;
}
int sizeCmd = strlen(cmdWithArg);
cmdWithArg[sizeCmd] = checkSumGO(cmdWithArg);
cmdWithArg[sizeCmd+1] = '\r';
cmdWithArg[sizeCmd+2] = '\0';
return write(fd,cmdWithArg,strlen(cmdWithArg));
}
int receiveMsg(void)
{
char msg[20];
int b;
if((b = readSerial(msg))!=ROBOT_TIMED_OUT)
{
int taille = strlen(msg);
char checksum = msg[taille-2];
msg[taille-1] = 0;
msg[taille-2] = 0;
if(checksum!=checkSumGO(msg))
{
return ROBOT_CHECKSUM;
}
else
{
switch(msg[0])
{
case 'O' : return 0;
case 'E' : return ROBOT_ERROR;
case 'C' : return ROBOT_UKNOWN_CMD;
default : return atoi(&msg[0]);
}
}
}
else
{
return ROBOT_TIMED_OUT;
}
}
int getChar(char * c)
{
int n =0;
int delay =0;
while((n=read(fd,c,1)) <=0)
{
usleep(5000);
delay++;
if(delay > 10)
{
return ROBOT_TIMED_OUT;
}
}
return n;
}
int readSerial(char * msg)
{
char car=0;
int i=0;
for(int j = 0 ; j < 20 ; j++)
msg[j]=0;
while(car !='\r' && car!='\n') {
if(i>=20)
return -5;
if(getChar(&car)==ROBOT_TIMED_OUT) {
return ROBOT_TIMED_OUT;
}
msg[i] = car;
i++;
}
return i;
}
char checkSumGO(char * msg)
{
char resultat = 0;
int i = 0;
int taille = strlen(msg);
for(i=0;i