Port serie sous linux rts txd drt source piklab

zemil Messages postés 5 Date d'inscription dimanche 24 août 2008 Statut Membre Dernière intervention 16 septembre 2008 - 16 sept. 2008 à 20:59
SebLinck Messages postés 212 Date d'inscription mardi 17 mai 2005 Statut Membre Dernière intervention 23 juin 2011 - 18 sept. 2008 à 09:48
je sui sous linux depuis peux je program avec kdevelope en c++

par hazard j'ais trouvé un logiciel qui arive a faire se que je recherche jé ais donc recupéré la
source mais je narive toujours pas a faire se que je recherche c'est a dir piloté les 3 sortie depuis mon programe et je nais pas resusi a compilé le programe entierement 





j'ai besoin de recopier 3 variable bool dans les 3 sortie  rts txd drt comme dans le logiciel
comuniqué avec un ecran a led qui contien des registre a décalage 16 registre de 8
avec une des sortir je crée une horloge avec une 2emme une sorti data au front monten de la sortie clock la dernier led s'alume si la sortie data et a 1 et decal toute les led  la 3emme sortie et un latche je sé pas comment sa se dit en français
mon programe sapel ap001widget.h ap001widget.cpp et ap001widget.ui la partie grafique
mes 3 variable sont sortie[0] sortie[1] sortie[2]
j'ai 2 fonction que je lance depuis  ap001Widget.cpp quand japuie sur 2 bouton

void ap001Widget::ouvertureport()
{
}
void ap001Widget::ecriture()
{
if(portouvert)
{
//recopie etas de sortie[0] sortie[1] sortie[2] dans rts txd drt
}
}

la source et disponible ici : http://packages.ubuntu.com/fr/source/hardy/i386/piklab
j'ai chercher dans serial.h, serial.h ,direct.h,direct.cpp

Merci de votre aide

joint: serial.h, serial.h ,direct.h,direct.cpp

serial.h
/***************************************************************************
 *   Copyright (C) 2005 Nicolas Hadacek <hadacek@kde.org>                  *
 *   Copyright (C) 2003-2004 Alain Gibaud            *
 *   Copyright (C) 2002-2003 Stephen Landamore <stephen@landamore.com>     *
 *                                                                         *
 *   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.                                   *
 ***************************************************************************/
#ifndef SERIAL_H
#define SERIAL_H

#include "common/global/global.h"
#ifdef Q_OS_UNIX
#  include <termios.h>
#elif defined(Q_OS_WIN)
#  include
#endif
#include "port_base.h"

namespace Port
{

class Serial : public Base
{
public:
  enum Speed { S0 = 0, S50, S75, S110, S134, S150, S200, S300, S600, S1200,
               S1800, S2400, S4800, S9600, S19200, S38400, S57600, S115200,
               Nb_Speeds };
  static const uint SPEED_VALUES[Nb_Speeds];
  struct SpeedData {
    bool supported;
    uint flag;
  };
  static const SpeedData SPEED_DATA[Nb_Speeds];
  enum Property { NoProperty 0, NeedDrain 1, NeedFlush = 2, NeedBreak = 4,
                  Blocking = 8 };
  Q_DECLARE_FLAGS(Properties, Property)

  Serial(const QString &device, Properties properties, Log::Base &base);
  virtual ~Serial() { close(); }
  virtual Description description() const { return Description(PortType::Serial, _device); }

  static const QStringList &probedDeviceList();
  static IODirs probe(const QString &device);
  static bool isAvailable() { return true; }
  enum InputFlag { NoInputFlag 0, IgnoreBreak 1, IgnoreParity = 2 };
  Q_DECLARE_FLAGS(InputFlags, InputFlag)  enum ControlFlag { NoControlFlag 0, ByteSize8 1, HardwareFlowControl = 2,                     EnableReceiver 4, IgnoreControlLines 8 };
  Q_DECLARE_FLAGS(ControlFlags, ControlFlag)
  bool setMode(InputFlags inputFlags, ControlFlags controlFlags, Speed speed, uint readTimeout); // in ms
  bool drain(uint timeout);
  bool flush(uint timeout);
  bool doBreak(uint duration); // in ms
  bool setHardwareFlowControl(bool on);

  enum Pin { DCD = 0, RX, TX, DTR, SG, DSR, RTS, CTS, RI, Nb_Pins };
  struct SPinData {
    IODir dir;
    const char *label;
  };
  static const SPinData PIN_DATA[Nb_Pins];
  virtual bool setPinOn(uint pin, bool on, LogicType type);
  virtual bool readPin(uint pin, LogicType type, bool &value);
  virtual QValueVector pinData(IODir dir) const;
  virtual bool isGroundPin(uint pin) const;
  virtual uint groundPin() const { return SG; }
  virtual IODir ioDir(uint pin) const;

private:
  QString    _device;
  Properties _properties;
#if defined(Q_OS_UNIX)
  typedef int Handle;
  typedef termios Parameters;
#elif defined(Q_OS_WIN)
  typedef HANDLE Handle;
  struct Parameters {
    DCB             dcb;
    COMMTIMEOUTS    comtmo;
  };
#endif
  Handle  _fd;
  Parameters _oldParameters;

  bool setParameters(const Parameters &parameters);
  bool getParameters(Parameters &parameters);
  virtual bool internalOpen();
  virtual void internalClose();
  virtual bool internalSend(const char *data, uint size, uint timeout);
  virtual bool internalReceive(uint size, char *data, uint timeout);
  virtual void setSystemError(const QString &message);
  bool internalSetPinOn(Pin pin, bool on);
  bool internalReadPin(Pin pin, LogicType type, bool &value);

  static const Handle INVALID_HANDLE;
  static Handle openHandle(const QString &device, IODirs dirs);
  static void closeHandle(Handle handle);
  static QStringList *_list;
  static QStringList deviceList();
  static void setHardwareFlowControl(Parameters &parameters, bool on);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(Serial::Properties)
Q_DECLARE_OPERATORS_FOR_FLAGS(Serial::InputFlags)
Q_DECLARE_OPERATORS_FOR_FLAGS(Serial::ControlFlags)

} // namespace

#endif

serial.cpp
/***************************************************************************
 *   Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@kde.org>             *
 *   Copyright (C) 2003-2004 Alain Gibaud            *
 *   Copyright (C) 2002-2003 Stephen Landamore <stephen@landamore.com>     *
 *                                                                         *
 *   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.                                   *
 ***************************************************************************/
#include "serial.h"

#ifdef Q_OS_UNIX
#  include <stdio.h>
#  include <fcntl.h>
#  include <sys/time.h>
#  include <sys/types.h>
#  include <sys/stat.h>
#  include <sys/ioctl.h>
#  include <errno.h>
#  include // needed on some system
#endif
#include <qdatetime.h>

//-----------------------------------------------------------------------------
QStringList *Port::Serial::_list = 0;
#if defined(Q_OS_UNIX)
const Port::Serial::Handle Port::Serial::INVALID_HANDLE = -1;
#elif defined(Q_OS_WIN)
const Port::Serial::Handle Port::Serial::INVALID_HANDLE = INVALID_HANDLE_VALUE;
#endif
///ouverture du port et ranvoir le numero-----------------------------
Port::Serial::Handle Port::Serial::openHandle(const QString &device, IODirs dirs)
{
#if defined(Q_OS_UNIX)
  // open non blocking: avoid missing DCD (comment from xwisp2)
  int mode = O_NOCTTY | O_NONBLOCK;
  if ( dirs & In ) {
    if ( dirs & Out ) mode |= O_RDWR;
    else mode |= O_RDONLY;
  } else mode |= O_WRONLY;
  return ::open(device.latin1(), mode);
#elif defined(Q_OS_WIN)
  int mode = 0;
  if ( dirs & In ) mode |= GENERIC_READ;
  if ( dirs & Out ) mode |= GENERIC_WRITE;
  return CreateFileA(device.latin1(), mode, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
#endif
}
//ouverture du port et ranvoir le numero-------------------------------

void Port::Serial::closeHandle(Handle handle)
{
#if defined(Q_OS_UNIX)
  ::close(handle);
#elif defined(Q_OS_WIN)
  CloseHandle(handle);
#endif
}

Port::IODirs Port::Serial::probe(const QString &device)
{
  Handle handle = openHandle(device, In);
  if ( handle==INVALID_HANDLE ) return NoIO;
  closeHandle(handle);
  handle = openHandle(device, In | Out);
  if ( handle==INVALID_HANDLE ) return In;
  closeHandle(handle);
  return (In | Out);
}

QStringList Port::Serial::deviceList()
{
  QStringList list;
#if defined(Q_OS_UNIX)
  // standard serport in user space
  for (uint i=0; i<8; i++) list.append(QString("/dev/ttyS%1").arg(i));
  // new devfs serport flavour
  for (uint i=0; i<8; i++) list.append(QString("/dev/tts/%1").arg(i));
  // standard USB serport in user space
  for (uint i=0; i<8; i++) list.append(QString("/dev/ttyUSB%1").arg(i));
  // new devfs USB serport flavour
  for (uint i=0; i<8; i++) list.append(QString("/dev/usb/tts/%1").arg(i));
  // FreeBSD
  for (uint i=0; i<8; i++) list.append(QString("/dev/ttyd%1").arg(i));
  // Slackware 11 devfs USB Serial port support.
  for (uint i=0; i<8; i++) list.append(QString("/dev/tts/USB%1").arg(i));
  // MacOSX devfs USB Serial port support.
  list.append("/dev/tty.usbserial");
#elif defined(Q_OS_WIN)
  for (uint i=1; i<10; i++) list.append(QString("COM%1").arg(i));
#endif
  return list;
}

const QStringList &Port::Serial::probedDeviceList()
{
  if ( _list==0 ) {
    QStringList all = deviceList();
    _list = new QStringList;
    for (uint i=0; iappend(all[i]);
  }
  return *_list;
}

//-----------------------------------------------------------------------------
const uint Port::Serial::SPEED_VALUES[Nb_Speeds] = {
  0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400,
  57600, 115200
};
const Port::Serial::SpeedData Port::Serial::SPEED_DATA[Nb_Speeds] = {
#if defined(Q_OS_UNIX)
  { true, B0     }, { true, B50     }, { true, B75    }, { true, B110   },
  { true, B134   }, { true, B150    }, { true, B200   }, { true, B300   },
  { true, B600   }, { true, B1200   }, { true, B1800  }, { true, B2400  },
  { true, B4800  }, { true, B9600   }, { true, B19200 }, { true, B38400 },
  { true, B57600 }, { true, B115200 }
#elif defined(Q_OS_WIN)
  { false, 0        }, { false, 0         }, { false, 0        }, { true, CBR_110   },
  { false, 0        }, { false, 0         }, { false, 0        }, { true, CBR_300   },
  { true,  CBR_600  }, { true, CBR_1200   }, { false, 0        }, { true, CBR_2400  },
  { true, CBR_4800  }, { true, CBR_9600   }, { true, CBR_19200 }, { true, CBR_38400 },
  { true, CBR_57600 }, { true, CBR_115200 }
#endif
};

const Port::Serial::SPinData Port::Serial::PIN_DATA[Nb_Pins] = {
  { In,   "DCD" }, { In, "RX"  }, { Out, "TX"  }, { Out, "DTR" },
  { NoIO, "GND" }, { In, "DSR" }, { Out, "RTS" }, { In,  "CTS" },
  { Out,  "RI"  }
};

QValueVector Port::Serial::pinData(IODir dir) const
{
  QValueVector v;
  for (uint i=0; i<Nb_Pins; i++) {
    if ( PIN_DATA[i].dir!=dir ) continue;
    PinData pd = { i, PIN_DATA[i].label };
    v.append(pd);
  }
  return v;
}
bool Port::Serial::isGroundPin(uint pin) const
{
  return ( PIN_DATA[pin].label==QString("GND") );
}

Port::IODir Port::Serial::ioDir(uint pin) const
{
  return PIN_DATA[pin].dir;
}

Port::Serial::Serial(const QString &device, Properties properties, Log::Base &base)
  : Base(base), _device(device), _properties(properties), _fd(INVALID_HANDLE)
{}

bool Port::Serial::getParameters(Parameters &parameters)
{
  if ( _fd==INVALID_HANDLE ) return false;
#if defined(Q_OS_UNIX)
  if ( tcgetattr(_fd, &parameters)<0 )
{
    setSystemError(i18n("Could not get file descriptor parameters"));
    return false;
}
#elif defined(Q_OS_WIN)
  if ( !GetCommState(_fd, &parameters.dcb) || !GetCommTimeouts(_fd, &parameters.comtmo) )
{
    setSystemError(i18n("Could not get file descriptor parameters"));
    return false;
}
#endif

 
  return true;

}

bool Port::Serial::setParameters(const Parameters &parameters)
{
  if ( _fd==INVALID_HANDLE ) return false;
#if defined(Q_OS_UNIX)
  if ( tcsetattr(_fd, TCSANOW, &parameters)<0 )
{
    setSystemError(i18n("Could not set file descriptor parameters"));
    return false; 
}
#elif defined(Q_OS_WIN)
  Parameters tmp = parameters;
  if ( !SetCommState(_fd, &tmp.dcb) || !SetCommTimeouts(_fd, &tmp.comtmo) )
{
    setSystemError(i18n("Could not set file descriptor parameters"));
    return false; 
}
#endif
  return true;

}

///demande ouvertur du port-----------------------------------

bool Port::Serial::internalOpen()
{
  _fd = openHandle(_device, In | Out);
  if ( _fd==INVALID_HANDLE ) {
    setSystemError(i18n("Could not open device "%1" read-write").arg(_device));
    return false;
  }
  if ( !getParameters(_oldParameters) ) return false; // save configuration
#if defined(Q_OS_UNIX)
  if ( _properties & Blocking ) {
    int flags = fcntl(_fd, F_GETFL, 0);
    if ( fcntl(_fd, F_SETFL, flags & ~O_NONBLOCK)<0 ) {
      setSystemError(i18n("Could not modify file descriptor flags"));
      return false;
    }
  }
#endif
  return flush(DEFAULT_TIMEOUT);
}

//demande ouvertur du port-----------------------------------

void Port::Serial::internalClose()
{
  if ( _fd==INVALID_HANDLE ) return;
  if ( _properties & NeedFlush ) flush(0);
  if ( _properties & NeedBreak ) doBreak(1);
  setParameters(_oldParameters);
  closeHandle(_fd);
  _fd = INVALID_HANDLE;
}

bool Port::Serial::internalSend(const char *data, uint size, uint timeout)
{
  if ( _fd==INVALID_HANDLE ) return false;
  QTime time;
  time.start();
  for (uint todo=size; todo!=0; ) {
#if defined(Q_OS_UNIX)
    int res = write(_fd, data+size-todo, todo);
    if ( res<0 && errno!=EAGAIN )
{
  if ( (_properties & NeedDrain) && !drain(timeout) ) return false;
}
#elif defined(Q_OS_WIN)
    DWORD res = 0;
    if ( WriteFile(_fd, data+size-todo, todo, &res, NULL)==0 )
{
  if ( (_properties & NeedDrain) && !drain(timeout) ) return false;
}
#endif
      setSystemError(i18n("Error sending data"));
      return false;
    }
    if ( res>0 ) todo -= res;
    else {
      if ( uint(time.elapsed())>timeout ) {
        log(Log::LineType::Error, i18n("Timeout sending data (%1/%2 bytes sent).").arg(size-todo).arg(size));
        return false;
      }
      msleep(1);
    }
 

  return true;
}

bool Port::Serial::internalReceive(uint size, char *data, uint timeout)
{
  if ( _fd==INVALID_HANDLE ) return false;
  QTime time;
  time.start();
  for(uint todo=size; todo!=0; ) {
#if defined(Q_OS_UNIX)
    // this help reduce CPU usage. It also prevents blocking if the serial cable is disconnected
    fd_set rfd;
    FD_ZERO(&rfd);
    FD_SET(_fd, &rfd);
    struct timeval tv;
    tv.tv_sec = timeout / 1000;
    tv.tv_usec = (timeout%1000)*1000;
    int res = select(_fd+1, &rfd, 0, 0, &tv);
    if ( res<0 ) {
      setSystemError(i18n("Error receiving data"));
      return false;
    }
    if ( res==0 ) {
      log(Log::LineType::Error, i18n("Timeout waiting for data."));
      return false;
    }
    res = read(_fd, data+size-todo, todo);
    if ( res<0 && errno!=EAGAIN ) {
      setSystemError(i18n("Error receiving data"));
      return false;
    }

#elif defined(Q_OS_WIN)
    DWORD res = 0;
    if ( ReadFile(_fd, data+size-todo, todo, &res, NULL)==0 ) {
      setSystemError(i18n("Error receiving data"));
      return false;
    }

#endif

    if ( res>0 ) todo -= res;
    else {
      if ( uint(time.elapsed())>timeout ) {
        log(Log::LineType::Error, i18n("Timeout receiving data (%1/%2 bytes received).").arg(size-todo).arg(size));
        return false;
      }
      msleep(1);
    }
  }
  return true;
}

bool Port::Serial::drain(uint timeout)
{
  if ( _fd==INVALID_HANDLE ) return false;
#if defined(Q_OS_UNIX)
  // tcdrain will block if the serial cable is disconnected
  // so we first check for data in output buffer...
  QTime time;
  time.start();
  for (;;) {
    int nb;
    if ( ioctl(_fd, TIOCOUTQ, &nb)==-1 ) {
      setSystemError(i18n("Error checking for data in output buffer"));
      return false;
    }
    if ( nb==0 ) break;
    if ( uint(time.elapsed())>timeout ) {
      _fd = INVALID_HANDLE; // otherwise close blocks...
      log(Log::LineType::Error, i18n("Timeout sending data (%1 bytes left).").arg(nb));
      return false;
    }
  }
  if ( tcdrain(_fd)<0 ) {
    setSystemError(i18n("Error while draining"));
    return false;
  }
#endif
  return true;
}

bool Port::Serial::flush(uint timeout)
{
  if ( _fd==INVALID_HANDLE ) return false;
  if ( (_properties & NeedDrain) && !drain(timeout) ) return false;
#if defined(Q_OS_UNIX)
  if ( tcflush(_fd, TCIFLUSH)<0 ) {
    setSystemError(i18n("Could not flush device"));
    return false;
  }
#elif defined(Q_OS_WIN)
  if ( FlushFileBuffers(_fd)==0 || PurgeComm(_fd, PURGE_TXABORT)==0
       || PurgeComm(_fd, PURGE_RXABORT)==0 || PurgeComm(_fd, PURGE_TXCLEAR)==0
       || PurgeComm(_fd, PURGE_RXCLEAR)==0 ) {
    setSystemError(i18n("Could not flush device"));
    return false;
  }
#endif

  return true;
}

bool Port::Serial::internalSetPinOn(Pin pin, bool on)
{
#if defined(Q_OS_UNIX)
  int bit = 0;
  switch (pin) {
    case TX:  return ( ioctl(_fd, on ? TIOCSBRK : TIOCCBRK, 0)>=0 );
    case DTR: bit = TIOCM_DTR; break;
    case RTS: bit = TIOCM_RTS; break;
    case RI:  bit = TIOCM_RI; break;
    default:  Q_ASSERT(false); return false;
  }
  return ( ioctl(_fd, on ? TIOCMBIS : TIOCMBIC, &bit)>=0 );
#elif defined(Q_OS_WIN)
  DWORD func = 0;
  switch (pin) {
    case TX:  func = (on ? SETBREAK : CLRBREAK); break;
    case DTR: func = (on ? SETDTR : CLRDTR); break;
    case RTS: func = (on ? SETRTS : CLRRTS); break;
    case RI:  // #### not possible with Win32 API ??
    default:  Q_ASSERT(false); return false;
  }
  return ( EscapeCommFunction(_fd, func)!=0 );
#endif
}

bool Port::Serial::setPinOn(uint pin, bool on, LogicType type)
{
  if ( _fd==INVALID_HANDLE ) return false;
  if ( type==NegativeLogic ) on = !on;
  Q_ASSERT( pin<Nb_Pins );
  Q_ASSERT( PIN_DATA[pin].dir==Out );
  if ( !internalSetPinOn(Pin(pin), on) ) {
    setSystemError(i18n("Error setting bit %1 of serial port to %2").arg(PIN_DATA[pin].label).arg(on));
    return false;
  }
  return true;
}

bool Port::Serial::internalReadPin(Pin pin, LogicType type, bool &value)
{
#if defined(Q_OS_UNIX)
  int bits;
  if ( ioctl(_fd, TIOCMGET, &bits)<0 ) return false;
  int mask = 0;
  switch (pin) {
    case DCD: mask = TIOCM_CD;  break;
    case RX : mask = TIOCM_SR;  break;
    case DSR: mask = TIOCM_DSR; break;
    case CTS: mask = TIOCM_CTS; break;
    default:  Q_ASSERT(false); return false;
  }
  value = ((type==NegativeLogic ? ~bits : bits) & mask);
  return true;
#elif defined(Q_OS_WIN)
  DWORD status;
  if ( GetCommModemStatus(_fd, &status)==0 ) return false;
  switch (pin) {
    case DCD: value = (status & MS_RLSD_ON); break;
    case DSR: value = (status & MS_DSR_ON); break;
    case CTS: value = (status & MS_CTS_ON); break;
    case RX:  // not possible with Win32 API ??
    default:  Q_ASSERT(false); return false;
  }
  if ( type==NegativeLogic) value = !value;
  return true;
#endif
}

  bool Port::Serial::readPin(uint pin, LogicType type, bool &value)
{
  if ( _fd==INVALID_HANDLE ) return false;
  Q_ASSERT( pin<Nb_Pins );
  Q_ASSERT( PIN_DATA[pin].dir==In );
  if ( !internalReadPin(Pin(pin), type, value) ) {
    setSystemError(i18n("Error reading serial pin %1").arg(PIN_DATA[pin].label));
    return false;
  }
  return true;
}

bool Port::Serial::setMode(InputFlags inputFlags, ControlFlags controlFlags, Speed speed, uint readTimeout)
{
  Q_ASSERT (SPEED_DATA[speed].supported );
  if ( !flush(0) ) return false;
  Parameters parameters;
  if ( !getParameters(parameters) ) return false;
#if defined(Q_OS_UNIX)
  cfsetispeed(&parameters, SPEED_DATA[speed].flag);
  cfsetospeed(&parameters, SPEED_DATA[speed].flag);
  parameters.c_cflag &= ~(CSIZE|PARENB|PARODD|HUPCL|CSTOPB);
  int cflags = 0;
  if ( controlFlags & ByteSize8 ) cflags |= CS8;
  if ( controlFlags & HardwareFlowControl ) cflags |= CRTSCTS;
  if ( controlFlags & EnableReceiver ) cflags |= CREAD;
  if ( controlFlags & IgnoreControlLines ) cflags |= CLOCAL;
  parameters.c_cflag |= cflags;
  parameters.c_iflag &= ~(ISTRIP|INPCK|IGNCR|INLCR|ICRNL|IXOFF|IXON);
  int iflags = 0;
  if ( inputFlags & IgnoreBreak ) iflags |= IGNBRK;
  if ( inputFlags & IgnoreParity ) iflags |= IGNPAR;
  parameters.c_iflag |= iflags;
  parameters.c_oflag &= ~OPOST;
  parameters.c_lflag &= ~(ICANON|ECHO|ECHONL|ISIG|IEXTEN|TOSTOP);
  parameters.c_cc[VMIN]  = 0;               // wait for 1 char or timeout
  parameters.c_cc[VTIME] = readTimeout/100; // wait in deciseconds
#elif defined(Q_OS_WIN)
  if ( controlFlags & EnableReceiver ) ; // #### not sure what to do
  if ( controlFlags & IgnoreControlLines ) ; // #### not sure what to do
  setHardwareFlowControl(parameters, (controlFlags & HardwareFlowControl));
  if ( inputFlags & IgnoreParity ) parameters.dcb.Parity = NOPARITY;
  parameters.dcb.StopBits = ONESTOPBIT;
  if ( controlFlags & ByteSize8 ) parameters.dcb.ByteSize = 8;
  parameters.dcb.BaudRate = SPEED_DATA[speed].flag;
  parameters.comtmo.ReadIntervalTimeout = MAXDWORD;
  parameters.comtmo.ReadTotalTimeoutMultiplier = MAXDWORD;
  parameters.comtmo.ReadTotalTimeoutConstant = readTimeout;
  parameters.comtmo.WriteTotalTimeoutMultiplier = 1;
  parameters.comtmo.WriteTotalTimeoutConstant = readTimeout;
#endif
  return setParameters(parameters);
  // need flush ??
}

bool Port::Serial::doBreak(uint duration)
{
  if ( !flush(0) ) return false;
#if defined(Q_OS_UNIX)
  if ( ioctl(_fd, TIOCSBRK)<0 ) {
    setSystemError(i18n("Error setting up break"));
    return false;
  }
#elif defined(Q_OS_WIN)
  if ( SetCommBreak(_fd)==0 ) {
    setSystemError(i18n("Error setting up break"));
    return false;
  }
#endif

  msleep(duration);
#if defined(Q_OS_UNIX)
  if ( ioctl(_fd, TIOCCBRK) )
{
    setSystemError(i18n("Error clearing up break"));
    return false;
  }
#elif defined(Q_OS_WIN)
  if ( ClearCommBreak(_fd)==0 )
{
    setSystemError(i18n("Error clearing up break"));
    return false;
  }
#endif

  msleep(1);
  return flush(0);
}

void Port::Serial::setHardwareFlowControl(Parameters &parameters, bool on)
{
#if defined(Q_OS_UNIX)
  if (on) parameters.c_cflag |= CRTSCTS;
  else parameters.c_cflag &= ~CRTSCTS;
  parameters.c_cc[VMIN]  = 0; // #### needed ?
  parameters.c_cc[VTIME] = 0; // #### needed ?
#elif defined(Q_OS_WIN)
  // #### not sure about that
  parameters.dcb.fParity = on;
  parameters.dcb.fOutxCtsFlow = on;
  parameters.dcb.fOutxDsrFlow = on;
  parameters.dcb.fDtrControl = (on ? DTR_CONTROL_ENABLE : DTR_CONTROL_DISABLE);
  parameters.dcb.fDsrSensitivity = on;
  parameters.dcb.fTXContinueOnXoff = on;
  parameters.dcb.fOutX = on;
  parameters.dcb.fInX = on;
  parameters.dcb.fNull = on;
  parameters.dcb.fRtsControl = (on ? RTS_CONTROL_ENABLE : RTS_CONTROL_DISABLE);
  parameters.dcb.fAbortOnError = on;
#endif
}

bool Port::Serial::setHardwareFlowControl(bool on)
{
  Parameters parameters;
  if ( !getParameters(parameters) ) return false;
  setHardwareFlowControl(parameters, on);
  return setParameters(parameters);
}

void Port::Serial::setSystemError(const QString &message)
{
#if defined(Q_OS_UNIX)
  log(Log::LineType::Error, message + QString(" (errno=%1)").arg(strerror(errno)));
#elif defined(Q_OS_WIN)
  LPVOID lpMsgBuf;
  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);
  log(Log::LineType::Error, message + QString(" (last error=%1 %2)").arg(GetLastError()).arg((const char *)(LPCTSTR)lpMsgBuf));
  LocalFree(lpMsgBuf);
#endif
}

direct.h
/************<<<<***************************************************************
 *   Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@kde.org>             *
 *   Copyright (C) 2003-2004 Alain Gibaud            *
 *   Copyright (C) Brian C. Lane                                           *
 *                                                                         *
 *   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.                                   *
 ***************************************************************************/
#ifndef DIRECT_H
#define DIRECT_H

#include "devices/pic/prog/pic_prog.h"

namespace Direct
{enum State { Low 0, High 1, Off = Low, On = High };
enum PinType { Vpp = 0, Vdd, Clock, DataOut, DataIn, DataRW, Nb_PinTypes };
struct PinData {
  const char *label, *offLabel, *onLabel, *key, *comment;
  Port::IODir dir;
  bool canBeGround;
  const char *testComment;
};
extern const PinData PIN_DATA[Nb_PinTypes];

//-----------------------------------------------------------------------------
class HardwareData;
enum Type { Normal, EPEToolkitMK3 };
struct HData
{
  int pins[Nb_PinTypes];
  uint clockDelay;
  Type type;
};

class Hardware : public ::Programmer::PicHardware
{
public:
  static Hardware *create(Port::Base *port, const Device::Data &device, const HData &data);

public:
  Hardware(::Programmer::Base &base, Port::Base *port, const HardwareData &data);
  bool readBit();
  void setPin(PinType type, bool on);
  void setRead() { setPin(DataRW, true); }
  void setWrite() { setPin(DataRW, false); }

  uint nbPins(Port::IODir dir) const;
  QString pinLabelForIndex(Port::IODir dir, uint i) const;
  Port::IODir ioTypeForPin(int pin) const;
  uint pinForIndex(Port::IODir dir, uint i) const;
  uint indexForPin(Port::IODir dir, int pin) const;
  bool isGroundPin(int pin) const;
  Type type() const { return _data.type; }

  // hardware test --- please use it for a newly
  // designed/constructed programmer board
  // because pin assignation is hard coded in this
  // routine, you might have to edit it. ++Gib:
  //static int hardware_test();
  // timing test --- please use it to ensure that
  // the program meets the  timing specifications
  //static int timing_test();

private:
  HData _data;

  virtual bool internalConnectHardware();

  friend class Programmer;
};
extern bool operator !=(const HData &d1, const HData &d2);

class SerialHardware : public Hardware
{
public:
  SerialHardware(::Programmer::Base &base, const QString &portDevice, const HardwareData &data);
};

class ParallelHardware : public Hardware
{
public:
  ParallelHardware(::Programmer::Base &base, const QString &portDevice, const HardwareData &data);
};

} // namespace

#endif

direct.cpp

/***************************************************************************
 *   Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@kde.org>             *
 *   Copyright (C) 2003-2004 Alain Gibaud            *
 *   Copyright (C) Brian C. Lane                                           *
 *                                                                         *
 *   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.                                   *
 ***************************************************************************/
#include "direct.h"

#include

#include "common/port/parallel.h"
#include "common/port/serial.h"
#include "progs/base/generic_prog.h"
#include "direct_prog_config.h"

using namespace std;

//-----------------------------------------------------------------------------
const Direct::PinData Direct::PIN_DATA[Nb_PinTypes] = {
  { I18N_NOOP("MCLR (Vpp)"),  "0 V", "13 V", "vpp",
    I18N_NOOP("The VPP pin is used to select the high voltage programming mode."),
    Port::Out, false, I18N_NOOP("Check this box to turn voltage on/off for this pin.") },
  { I18N_NOOP("Power (Vdd)"), "0 V", "5 V",  "vdd",
    I18N_NOOP("The VDD pin is used to apply 5V to the programmed device.\nMust be set to GND if your programmer doesn't control the VDD line."),
    Port::Out, true,  I18N_NOOP("Check this box to turn voltage on/off for this pin.") },
  { I18N_NOOP("Clock"),       "0 V", "5 V",  "clock",
    I18N_NOOP("The CLOCK pin is used to synchronize serial data of the DATA IN and DATA OUT pins."),
    Port::Out, false, I18N_NOOP("Check this box to turn voltage on/off for this pin.") },
  { I18N_NOOP("Data Out"),    "0 V", "5 V",  "datao",
    I18N_NOOP("The DATA OUT pin is used to send data to the programmed device."),
    Port::Out, false, I18N_NOOP("Check this box to turn voltage on/off for this pin.") },
  { I18N_NOOP("Data In"),     "0 V", "5 V",  "datai",
    I18N_NOOP("The DATA IN pin is used to receive data from the programmed device."),
    Port::In,  false, I18N_NOOP("This pin is driven by the programmed device.\nWithout device, it must follow the "Data out" pin (when powered on).") },
  { I18N_NOOP("Data R/W"),    "Data in", "Data out", "drw",
    I18N_NOOP("The DATA RW pin selects the direction of data buffer.\nMust be set to GND if your programmer does not use bi-directionnal buffer."),
    Port::Out, true,  I18N_NOOP("Check this box to change DATA buffer direction.") }
};

//-----------------------------------------------------------------------------
namespace Direct
{
class SerialPort : public Port::Serial
{
public:
  SerialPort(const QString &device, Log::Base &base)
    : Serial(device, NeedBreak, base) {}

  bool open() {
    if ( !Port::Serial::open() ) return false;
    if ( !setMode(IgnoreBreak | IgnoreParity, ByteSize8 | EnableReceiver | IgnoreControlLines, S9600, 0) ) return false;
    // set up lines for "idle state" ???
    return true;
  }
};
} // namespace

//-----------------------------------------------------------------------------
Direct::Hardware::Hardware(::Programmer::Base &base, Port::Base *port, const HardwareData &data)
  : ::Programmer::PicHardware(base, port, data.name), _data(data.data)
{}

bool Direct::Hardware::internalConnectHardware()
{
  if ( !_port->open() ) return false;

  // keep the safe state of rw (read)...
  setPin(DataOut, Low);
  setPin(Clock, Low);
  setPin(Vpp, Off);
  setPin(Vdd, Off);
  setRead();

  return true;
}

void Direct::Hardware::setPin(PinType type, bool on)
{
  int pin = _data.pins[type];
  if ( isGroundPin(pin) ) return;
  uint p = (pin<0 ? -pin : pin)-1;
  //log(Log::DebugLevel::Extra, QString("Hardware::setPin %1 %2: %3 %4").arg(PIN_DATA[type].label).arg(pin).arg(on).arg(_data.clockDelay));
  _port->setPinOn(p, on, (pin<0 ? Port::NegativeLogic : Port::PositiveLogic));
  if ( type==Clock ) Port::usleep(_data.clockDelay);
}

bool Direct::Hardware::readBit()
{
  int pin = _data.pins[DataIn];
  Q_ASSERT( pin!=0 );
  uint p = (pin<0 ? -pin : pin)-1;
  bool on;
  _port->readPin(p, (pin<0 ? Port::NegativeLogic : Port::PositiveLogic), on);
  //log(Log::DebugLevel::Extra, QString("Hardware::read DataIn %2: %3").arg(pin).arg(on));
  return on;
}

uint Direct::Hardware::nbPins(Port::IODir dir) const
{
  return _port->pinData(dir).count();
}

QString Direct::Hardware::pinLabelForIndex(Port::IODir dir, uint i) const
{
  Port::PinData pd = _port->pinData(dir)[i];
  return QString("%1 (%2)").arg(pd.pin+1).arg(pd.label);
}

Port::IODir Direct::Hardware::ioTypeForPin(int pin) const
{
  if ( isGroundPin(pin) ) return Port::NoIO;
  uint p = (pin<0 ? -pin : pin)-1;
  return _port->ioDir(p);
}

uint Direct::Hardware::pinForIndex(Port::IODir dir, uint i) const
{
  Q_ASSERT( i<=uint(_port->pinData(dir).count()) );
  if ( i==uint(_port->pinData(dir).count()) ) return _port->groundPin()+1;
  return _port->pinData(dir)[i].pin+1;
}

uint Direct::Hardware::indexForPin(Port::IODir dir, int pin) const
{
  QValueVector v = _port->pinData(dir);
  Q_ASSERT( pin!=0 );
  uint p = (pin<0 ? -pin : pin)-1;
  for (uint i=0; iisGroundPin(p);
}

bool Direct::operator !=(const HData &d1, const HData &d2)
{
  for (uint i=0; i<Nb_PinTypes; i++)
    if ( d1.pins[i]!=d2.pins[i] ) return true;
  if ( d1.clockDelay!=d2.clockDelay ) return true;
  return false;
}

//-----------------------------------------------------------------------------
Direct::SerialHardware::SerialHardware(::Programmer::Base &base, const QString &portDevice, const HardwareData &data)
  : Hardware(base, new SerialPort(portDevice, base), data)
{}

Direct::ParallelHardware::ParallelHardware(::Programmer::Base &base, const QString &portDevice, const HardwareData &data)
  : Hardware(base, new Port::Parallel(portDevice, base), data)
{}

/*
//-----------------------------------------------------------------------------
int Direct::Hardware::hardware_test()
{
    char t[80] ;

    cout << endl << "Please execute this Direct::Hardware test without any PIC"
    " connected to your programmer" <<endl << endl ;

    do
    {
        cout << "Ready for tests ? (y/n) " ;
        cin >> t ;
    } while(t[0] != 'y' && t[0] != 'n') ;
    if( t[0] == 'n') return -1 ;

    // stage 1 - hard initialization
    // setpins("parallel","/dev/parport0", -5, -4, 3, 2, 10) ;

    //Default RW line not used...
    HData data = { { 3, 5, 7, 4, 8, 0 }, 0 };
    Log::ConsoleView view;
    Direct::Programmer programmer;
    programmer.setView(&view);
    SerialHardware hw(programmer, "/dev/ttyS0", data);
    if ( !hw.connectHardware() ) {
        cout << "Direct::Hardware initialization error" <<endl ;
        return 1 ;
    }

    //++Mirko!!
    //By Ciri 11/3/2004...
    //From here to the end of function i haven't modified nothing...
    //--Mirko!!

    // stage 2 - all lines off
    hw.setPin(Vpp, Off);
    hw.setPin(Vdd, Off);
    hw.setPin(Clock, Low);
    hw.setPin(DataOut, Low);
    cout << "All the following lines must be 0V : " << endl <<
    "16F84 pin 13 (data out)"<<endl <<
    "16F84 pin 12 (clock)"<<endl <<
    "16F84 pin 14 (VDD=power)"<<endl <<
    "16F84 pin 4  (VPP=prog)"<<endl ;
    do
    {
        cout << "OK ? (y/n) " ;
        cin >> t ;
    } while(t[0] != 'y' && t[0] != 'n') ;

    if( t[0] == 'n') return 2 ;

    // stage 3 - data out check
    hw.setPin(DataOut, High);
    cout << "16F84 pin 13 (data out) must be 5V"<<endl ;
    do
    {
        cout << "OK ? (y/n) " ;
        cin >> t ;
    } while(t[0] != 'y' && t[0] != 'n') ;
    hw.setPin(DataOut, Low);

    if( t[0] == 'n') return 3 ;

    // stage 4 - clock check
    hw.setPin(Clock, High);
    cout << "16F84 pin 12 (clock) must be 5V"<<endl ;
    do
    {
        cout << "OK ? (y/n) " ;
        cin >> t ;
    } while(t[0] != 'y' && t[0] != 'n') ;
    hw.setPin(Clock, Low);

    if( t[0] == 'n') return 4 ;

    // stage 5 - VDD check
    hw.setPin(Vdd, On);
    cout << "16F84 pin 14 (power) must be 5V"<<endl ;
    do
    {
        cout << "OK ? (y/n) " ;
        cin >> t ;
    } while(t[0] != 'y' && t[0] != 'n') ;
    hw.setPin(Vdd, Off) ;

    if( t[0] == 'n') return 5 ;

    // stage 6 - VPP check
    hw.setPin(Vpp, On);
    cout << "16F84 pin 4 (VDD) must be between 13V and 14V"<<endl ;
    do
    {
        cout << "OK ? (y/n) " ;
        cin >> t ;
    } while(t[0] != 'y' && t[0] != 'n') ;
    hw.setPin(Vpp , Off);

    if( t[0] == 'n') return 6 ;

    // stage 7 - test input data
    // set data out hi, because bi-directionnal
    // on pin 13 uses the open collector capability of 7407
    hw.setPin(DataOut, High);
    int in = hw.readBit();
    if( !in )
    {
        cout << "DataIn error (16F84 pin 13) : must be 5V and is not" << endl ;
        return 7 ;
    }
    cout << "Please set 16F84 pin 13 (DataIn) low " <<
    "(connect it to 16F84 pin 5 - GND)" << endl ;
    do
    {
        cout << "Done ? (y/n) " ;
        cin >> t ;
    } while(t[0] != 'y' && t[0] != 'n') ;

    in = hw.readBit();
    if(in )
    {
        cout << "DataIn error (pin 13) : must be 0V and is not" << endl ;
        return 7 ;
    }

    cout << "Congratulations! - Direct::Hardware is OK." <<endl ;
    return 0 ;
}

// this is my specific speed test
int Direct::Hardware::timing_test()
{
    char t[80] ;
    int cmd ;
    long loop = 50000000 ;

    cout << endl << "Please execute this Direct::Hardware test without any PIC"
    " connected to your programmer" <<endl << endl ;

    do
    {
        cout << "Ready for tests ? (y/n) " ;
        cin >> t ;
    } while(t[0] != 'y' && t[0] != 'n') ;
    if( t[0] == 'n') return -1 ;

    // stage 1 - hard initialization
    //Default Line RW not used...
    HData data = { { -5, -4, 3, 2, 10, 25 }, 0 };
    Log::ConsoleView view;
    Log::Manager manager;
    manager.setView(&view);
    ParallelHardware hw("/dev/parport0", manager, data);
    if ( !hw.connectHardware() ) {
        cout << "Direct::Hardware initialization error" <<endl ;
        return 1 ;
    }

    //++Mirko!!
    //By Ciri 11/3/2004...
    //From here to the end of function i have modified nothing...
    //--Mirko!!

    // stage 2 - all lines off
    hw.setPin(Vpp, Off);
    hw.setPin(Vdd, Off);
    hw.setPin(Clock, Low);
    hw.setPin(DataOut, Low);

    // stage 3 - choose test
    cout << "Remember : " << endl <<
    "16F84 pin 5  is GND"<<endl <<
    "16F84 pin 13 is data-out"<<endl <<
    "16F84 pin 12 is clock"<<endl ;

    cout << loop << " periods test .... " << endl ;

    cout << "1 - Maximum speed clock " << endl <<
    "2 - 100us half period "<<endl <<
    "3 - load data 0x2AAA (programmer->chip)"<<endl <<
    "4 - end"<<endl ;
    do
    {
        cout << "CMD (1-4)>> " ;
        cin >> cmd ;
    } while(cmd < 1 || cmd > 4) ;

    if(cmd == 4) return 2 ;
    else if ( cmd == 1)
    {
        for(long j=0 ; j < loop ; ++j)
        {
            hw.setPin(Clock, Low);
            hw.setPin(Clock, High);
        }
    }

    else if ( cmd == 2)
    {
        for(long j=0 ; j < loop ; ++j)
        {
            hw.setPin(Clock, Low);
            Port::usleep(100);
            hw.setPin(Clock, High);
            Port::usleep(100);
        }
    }

    else if ( cmd == 3) {
        for (long j=0; j<loop; ++j)
        {
            int d = 0x2AAA ;
            d &= 0x3FFF ;               // mask unused msb
            d <<= 1;                // insert start bit

            for (uint x = 0; x<16; x++) {
                hw.setPin(Clock, High);
                if ( d & 0x01 ) hw.setPin(DataOut, High);
                else hw.setPin(DataOut, Low);
                hw.setPin(Clock, Low);
                d >>= 1;
            }
            hw.setPin(DataOut, High);
        }
    }

    return 0;
}
*/

1 réponse

SebLinck Messages postés 212 Date d'inscription mardi 17 mai 2005 Statut Membre Dernière intervention 23 juin 2011
18 sept. 2008 à 09:48
Salut,

ça donne pas envie de lire tout ce code !

Cordialement,
Sébastien.
0
Rejoignez-nous