/*
 *  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 2 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 Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */


//
// Class: cSerial
//
// Created by: Kristian Mueller <Kristian-M@Kristian-M.de>
// Created on: Sat Jun 18 16:59:36 2005
//

#include <termios.h>
#include <exception>
#include <string>
#include <iostream>
#include "cSerial.h"
#include "gVar.h"

cSerial::cSerial() : cFile(){
}


cSerial::~cSerial(){    
    try{
        // close implicit with destruction
        this->closeFile();
    }
    catch( ... ){}
}


bool cSerial::openFile( const char* device, const int mode ){
    // com must be opened with O_RDWR|O_NOCTTY
    // call the base class method
    if(!cFile::openFile(device, O_RDWR|O_NOCTTY))
        return false;

	// save current IO-settings
    if(tcgetattr(iDescriptor, &aOriginalTermSettings) != 0 )
        throw(std::string("tcgetattr"));

    // initialize the port with default settings
    setupBaudRate(B19200);
    
	// VTIME (caracter timer), VMIN(caractercount)
//    setupTimeOuts(1, 11);
    setupTimeOuts(1, PACKET_SIZE);
    //    setupTimeOuts(TIME_OUT, PACKET_DATA_LENGHT);

    return true;
}

void cSerial::closeFile(void){
    if(isOpen()){
        // restore old IO-settings after all output is done
        if(tcsetattr(iDescriptor, TCSADRAIN, &aOriginalTermSettings ) != 0 )
            throw(std::string("tcsetattr"));

        // call the base class method
        cFile::closeFile();
    }
}

bool cSerial::setupBaudRate(const unsigned int iSpeed){
    struct termios aTermIoSettings;

    if(!isOpen())
        return false;   // port is closed
    
    // get the current settings
    if( tcgetattr(iDescriptor, &aTermIoSettings) != 0)
        throw(std::string( "tcgetattr" ));
    
    // control mode flags
    aTermIoSettings.c_cflag = iSpeed | CS8 | CLOCAL | CREAD;    
    aTermIoSettings.c_lflag = 0;	// no local mode flags needed
    aTermIoSettings.c_oflag = 0;    // raw output
    aTermIoSettings.c_iflag = 0;    // raw input

    configurePort(aTermIoSettings);

    return true;
}

bool cSerial::setupTimeOuts(const unsigned int timeout, const unsigned int min){
    struct termios aTermIoSettings;

    if(!isOpen())
        return false;   // port is closed

    // get the current settings
    if(tcgetattr(iDescriptor, &aTermIoSettings ) != 0)
        throw(std::string("tcgetattr"));

    aTermIoSettings.c_cc[VMIN] = min;
    aTermIoSettings.c_cc[VTIME] = timeout;

    configurePort(aTermIoSettings);

    return true;
}

void cSerial::configurePort(const struct termios& aTermIoSettings){
    // now clean the modem line
    if( tcflush(iDescriptor, TCIFLUSH) != 0)
        throw(std::string("tcflush"));

    // activate the settings for modem immediately
    if(tcsetattr(iDescriptor, TCSANOW, &aTermIoSettings ) != 0 )
        throw(std::string("tcsetattr"));
}

bool cSerial::sendACK(){

std::cerr << "sending ACK!" << std::endl;

	writeToFile('A');
	return true;
};

bool cSerial::waitForACK(){
	char sRead;
	
    setupTimeOuts(5, 0);
	sRead = 0;
std::cerr << "waiting fo ACK..." << std::endl;
//	for (int i ; ((i <= 3) && (sRead[0] == 0)) ; i++) {
		readFromFile(sRead);
//	}
    setupTimeOuts(1, PACKET_SIZE);

	if (sRead != 'A'){
        std::cerr << "no ACK recived!" << std::endl;
		return false;
    }
    std::cerr << "ACK recived!" << std::endl;
	return true;
};

