You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
8.5 KiB
250 lines
8.5 KiB
/***************************************************************************
|
|
* Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> *
|
|
* Copyright (C) 2003-2004 Alain Gibaud <alain.gibaud@free.fr> *
|
|
* *
|
|
* 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_config_widget.h"
|
|
|
|
#include <tqtooltip.h>
|
|
#include <tqcheckbox.h>
|
|
#include <tqtimer.h>
|
|
#include <tqpushbutton.h>
|
|
|
|
#include "progs/direct/base/direct_prog_config.h"
|
|
#include "progs/direct/base/direct_prog.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
::Programmer::ConfigWidget *Direct::GroupUI::createConfigWidget(TQWidget *parent) const
|
|
{
|
|
return new ConfigWidget(static_cast<const ::Programmer::Group &>(group()), parent);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
const char * const INV_PIN_LABEL = I18N_NOOP("Check this option if your hardware uses negative logic for this pin.");
|
|
const char * const DELAY_LABEL = I18N_NOOP("Some programming cards need low clock rate:\nadding delay to clock pulses might help.");
|
|
|
|
Direct::HConfigWidget::HConfigWidget(::Programmer::Base &base, TQWidget *parent, bool edit)
|
|
: ::Hardware::HConfigWidget(base, parent, edit)
|
|
{
|
|
// pins assignment
|
|
TQGroupBox *groupb = new TQGroupBox(1,Qt::Horizontal, i18n("Pin assignment"), this);
|
|
_mainVBox->addWidget(groupb);
|
|
TQWidget *w = new TQWidget(groupb);
|
|
TQGridLayout *grid = new TQGridLayout(w, 1, 1, 0, 10);
|
|
if (edit) grid->setColStretch(5, 1);
|
|
for (uint i=0; i<Nb_PinTypes; i++) {
|
|
TQLabel *label = new TQLabel(i18n(PIN_DATA[i].label), w);
|
|
TQToolTip::add(label, PIN_DATA[i].comment);
|
|
grid->addWidget(label, i, 0);
|
|
_combos[i] = new TQComboBox(w);
|
|
_combos[i]->setEnabled(edit);
|
|
connect(_combos[i], TQT_SIGNAL(activated(int)), TQT_SLOT(slotPinChanged()));
|
|
TQToolTip::add(_combos[i], PIN_DATA[i].comment);
|
|
grid->addWidget(_combos[i], i, 1);
|
|
_invcbs[i] = new TQCheckBox(i18n("Inverted"), w);
|
|
_invcbs[i]->setEnabled(edit);
|
|
TQToolTip::add(_invcbs[i], i18n(INV_PIN_LABEL));
|
|
grid->addWidget(_invcbs[i], i, 2);
|
|
if (edit) {
|
|
_testcbs[i] = new TQCheckBox(i18n("on"), w);
|
|
TQToolTip::add(_testcbs[i], PIN_DATA[i].testComment);
|
|
connect(_testcbs[i], TQT_SIGNAL(clicked()), TQT_SLOT(slotTestPin()));
|
|
grid->addWidget(_testcbs[i], i, 3);
|
|
_testLabels[i] = new TQLabel(w);
|
|
TQToolTip::add(_testcbs[i], PIN_DATA[i].testComment);
|
|
grid->addWidget(_testLabels[i], i, 4);
|
|
updateTestStatus(PinType(i), false);
|
|
} else {
|
|
_testcbs[i] = 0;
|
|
_testLabels[i] = 0;
|
|
}
|
|
}
|
|
|
|
TQHBoxLayout *hbox = new TQHBoxLayout(_mainVBox);
|
|
TQLabel *label = new TQLabel(i18n("Clock delay"), this);
|
|
TQToolTip::add(label, i18n(DELAY_LABEL));
|
|
hbox->addWidget(label);
|
|
_delay = new KIntNumInput(0,Qt::Horizontal, this);
|
|
_delay->setRange(0, 50, 5);
|
|
_delay->setEnabled(edit);
|
|
TQToolTip::add(_delay, i18n(DELAY_LABEL));
|
|
hbox->addWidget(_delay);
|
|
|
|
if (edit) {
|
|
_sendBitsButton = new TQPushButton(i18n("Send 0xA55A"), this);
|
|
_sendBitsButton->setToggleButton(true);
|
|
connect(_sendBitsButton, TQT_SIGNAL(clicked()), TQT_SLOT(sendBits()));
|
|
TQToolTip::add(_sendBitsButton, i18n("Continuously send 0xA55A on \"Data out\" pin."));
|
|
_editVBox->addWidget(_sendBitsButton);
|
|
_editVBox->addStretch(1);
|
|
} else _sendBitsButton = 0;
|
|
|
|
// timer for sending bits
|
|
_timerSendBits = new TQTimer(this);
|
|
connect(_timerSendBits, TQT_SIGNAL(timeout()), TQT_SLOT(slotSendBits()));
|
|
|
|
// timer for automatically polling DataOut pin
|
|
_timerPollDataOut = new TQTimer(this);
|
|
connect(_timerPollDataOut, TQT_SIGNAL(timeout()), TQT_SLOT(updateDataIn()));
|
|
}
|
|
|
|
void Direct::HConfigWidget::sendBits()
|
|
{
|
|
if ( _timerSendBits->isActive() ) {
|
|
_sendBitsButton->setText(i18n("Send 0xA55A"));
|
|
_timerSendBits->stop();
|
|
updateTestPin(DataOut);
|
|
} else {
|
|
_sendBitsButton->setText(i18n("Stop"));
|
|
_timerSendBits->start(1);
|
|
}
|
|
}
|
|
|
|
uint Direct::HConfigWidget::pin(PinType ptype) const
|
|
{
|
|
return static_cast<const Hardware *>(_hardware)->pinForIndex(PIN_DATA[ptype].dir, _combos[ptype]->currentItem());
|
|
}
|
|
|
|
void Direct::HConfigWidget::slotPinChanged()
|
|
{
|
|
for (uint i = 0; i<Nb_PinTypes; i++) {
|
|
if ( sender()!=_combos[i] ) continue;
|
|
updatePin(PinType(i));
|
|
}
|
|
}
|
|
|
|
void Direct::HConfigWidget::updatePin(PinType ptype)
|
|
{
|
|
bool ground = hardware()->isGroundPin(pin(ptype));
|
|
_invcbs[ptype]->setEnabled(_edit);
|
|
if (ground) _invcbs[ptype]->hide();
|
|
else _invcbs[ptype]->show();
|
|
if (_edit) {
|
|
_testcbs[ptype]->setEnabled(PIN_DATA[ptype].dir==Port::Out && _connected);
|
|
_testLabels[ptype]->setEnabled(_connected);
|
|
if (ground) {
|
|
_testcbs[ptype]->hide();
|
|
_testLabels[ptype]->hide();
|
|
} else {
|
|
_testcbs[ptype]->show();
|
|
_testLabels[ptype]->show();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Direct::HConfigWidget::slotTestPin()
|
|
{
|
|
for (uint i = 0; i<Nb_PinTypes; i++) {
|
|
if ( sender()!=_testcbs[i] ) continue;
|
|
updateTestPin(PinType(i));
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Direct::HConfigWidget::updateTestPin(PinType ptype)
|
|
{
|
|
Q_ASSERT( _connected && ptype!=DataIn );
|
|
bool on = _testcbs[ptype]->isChecked();
|
|
hardware()->setPin(ptype, on);
|
|
updateTestStatus(ptype, on);
|
|
if ( ptype==Vpp ) updateDataIn();
|
|
}
|
|
|
|
void Direct::HConfigWidget::updateTestStatus(PinType ptype, bool on)
|
|
{
|
|
if (on) _testLabels[ptype]->setText(i18n(PIN_DATA[ptype].onLabel));
|
|
else _testLabels[ptype]->setText(i18n(PIN_DATA[ptype].offLabel));
|
|
}
|
|
|
|
void Direct::HConfigWidget::updateDataIn()
|
|
{
|
|
bool on = hardware()->readBit();
|
|
updateTestStatus(DataIn, on);
|
|
_testcbs[DataIn]->setChecked(on);
|
|
}
|
|
|
|
void Direct::HConfigWidget::sendBits(uint d, int nbb)
|
|
{
|
|
Q_ASSERT(_connected);
|
|
hardware()->setWrite();
|
|
for (; nbb; --nbb) {
|
|
hardware()->setPin(Clock, High);
|
|
if ( d & 0x01 ) hardware()->setPin(DataOut, High);
|
|
else hardware()->setPin(DataOut, Low);
|
|
hardware()->setPin(Clock, Low);
|
|
d >>= 1; // Move the data over 1 bit
|
|
}
|
|
hardware()->setPin(DataOut, Low);
|
|
hardware()->setRead();
|
|
}
|
|
|
|
void Direct::HConfigWidget::slotSendBits()
|
|
{
|
|
sendBits(0xA55A, 16);
|
|
}
|
|
|
|
bool Direct::HConfigWidget::set(const Port::Description &pd, const ::Hardware::Data &data)
|
|
{
|
|
// connect port
|
|
_timerPollDataOut->stop();
|
|
if ( _timerSendBits->isActive() ) sendBits(); // stop
|
|
delete _hardware;
|
|
const HardwareData &hdata = static_cast<const HardwareData &>(data);
|
|
if ( pd.type==PortType::Serial ) _hardware = new SerialHardware(_base, pd.device, hdata);
|
|
else _hardware = new ParallelHardware(_base, pd.device, hdata);
|
|
bool ok = _hardware->connectHardware();
|
|
if ( !_edit) _hardware->disconnectHardware();
|
|
else _connected = ok;
|
|
|
|
// update GUI
|
|
if (_edit) {
|
|
for (uint i=0; i<Nb_PinTypes; i++) {
|
|
_testcbs[i]->setEnabled(_connected);
|
|
updateTestStatus(PinType(i), false);
|
|
}
|
|
if ( _connected ) _timerPollDataOut->start(100);
|
|
_sendBitsButton->setEnabled(_connected);
|
|
}
|
|
|
|
// update pins
|
|
for (uint i=0; i<Nb_PinTypes; i++) {
|
|
_combos[i]->clear();
|
|
Port::IODir dir = PIN_DATA[i].dir;
|
|
for (uint k=0; k<hardware()->nbPins(dir); k++)
|
|
_combos[i]->insertItem(hardware()->pinLabelForIndex(dir, k));
|
|
if (PIN_DATA[i].canBeGround) _combos[i]->insertItem("GND");
|
|
_combos[i]->setCurrentItem(hardware()->indexForPin(dir, hdata.data.pins[i]));
|
|
_invcbs[i]->setChecked(hdata.data.pins[i]<0);
|
|
updatePin(PinType(i));
|
|
}
|
|
_delay->setValue(hdata.data.clockDelay);
|
|
|
|
return ok;
|
|
}
|
|
|
|
Hardware::Data *Direct::HConfigWidget::data() const
|
|
{
|
|
HardwareData *hdata = new HardwareData;
|
|
hdata->portType = _hardware->portDescription().type;
|
|
for (uint i=0; i<Nb_PinTypes; i++) {
|
|
hdata->data.pins[i] = pin(PinType(i));
|
|
if ( _invcbs[i]->isChecked() ) hdata->data.pins[i] = -hdata->data.pins[i];
|
|
}
|
|
hdata->data.clockDelay = _delay->value();
|
|
return hdata;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
Direct::ConfigWidget::ConfigWidget(const ::Programmer::Group &group, TQWidget *parent)
|
|
: ::Hardware::ConfigWidget(new ::Direct::PicBase(group, 0), new Config, parent)
|
|
{}
|
|
|
|
Hardware::HConfigWidget *Direct::ConfigWidget::createHardwareConfigWidget(TQWidget *parent, bool edit) const
|
|
{
|
|
return new HConfigWidget(*_base, parent, edit);
|
|
}
|