/*************************************************************************** * Copyright (C) 2006 Nicolas Hadacek * * * * 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 "pic_register_view.h" #include #include #include #include #include #include #include #include #include "libgui/main_global.h" #include "devices/gui/hex_word_editor.h" #include "common/gui/misc_gui.h" #include "devices/pic/base/pic.h" #include "progs/base/generic_prog.h" #include "progs/base/generic_debug.h" #include "progs/base/prog_group.h" #include "libgui/gui_debug_manager.h" #include "coff/base/text_coff.h" //----------------------------------------------------------------------------- Pic::BankWidget::BankWidget(uint i, TQWidget *parent) : TQFrame(parent, "bank_widget"), _bindex(i), _bankCombo(0) { setFrameStyle(WinPanel | Sunken); TQGridLayout *top = new TQGridLayout(this, 1, 1, 5, 0); top->setColSpacing(1, 4); TQFont f("courier", font().pointSize()); const Pic::Data &data = static_cast(*Main::deviceData()); const Pic::RegistersData &rdata = data.registersData(); bool debugging = Main::programmerGroup().isDebugger(); uint row = 0; if ( rdata.nbBanks!=1 ) { if ( data.is18Family() ) { if ( (i/2)==0 ) { TQString title = ((i%2)==0 ? i18n("Access Bank (low)") : i18n("Access Bank (high)")); TQLabel *label = new TQLabel(title, this); label->setAlignment(AlignCenter); top->addMultiCellWidget(label, row,row, 0,6, AlignHCenter); } else { _bankCombo = new TQComboBox(this); for (uint k=1; k<2*rdata.nbBanks-1; k++) { _bankCombo->insertItem((k%2)==0 ? i18n("Bank %1 (low)").arg(k/2) : i18n("Bank %1 (high)").arg(k/2)); } if ( _bindex==3 ) _bankCombo->setCurrentItem(1); connect(_bankCombo, TQ_SIGNAL(activated(int)), TQ_SLOT(bankChanged())); top->addMultiCellWidget(_bankCombo, row,row, 0,6, AlignHCenter); } } else { TQLabel *label = new TQLabel(i18n("Bank %1").arg(i), this); label->setAlignment(AlignCenter); top->addMultiCellWidget(label, row,row, 0,6, AlignHCenter); } row++; top->setRowSpacing(row, 5); row++; } TDEIconLoader loader; TQPixmap readIcon = loader.loadIcon("viewmag", TDEIcon::Small); TQPixmap editIcon = loader.loadIcon("edit", TDEIcon::Small); uint nb; if ( !data.is18Family() ) nb = rdata.nbRegistersPerBank(); else nb = kMax(rdata.accessBankSplit, rdata.nbRegistersPerBank() - rdata.accessBankSplit); _registers.resize(nb); for (uint k=0; ksetFont(f); top->addWidget(_registers[k].alabel, row, 0); if (debugging) { _registers[k].button = new PopupButton(this); _registers[k].button->appendItem(i18n("Read"), readIcon, ReadId); _registers[k].button->appendItem(i18n("Edit"), editIcon, EditId); _registers[k].button->appendItem(i18n("Watch"), WatchId); connect(_registers[k].button, TQ_SIGNAL(activated(int)), TQ_SLOT(buttonActivated(int))); top->addWidget(_registers[k].button, row, 2); _registers[k].edit = new Register::LineEdit(this); connect(_registers[k].edit, TQ_SIGNAL(modified()), TQ_SLOT(write())); _registers[k].edit->setFont(f); top->addWidget(_registers[k].edit, row, 6); } else { _registers[k].label = new TQLabel(this); top->addWidget(_registers[k].label, row, 2); } row++; } if (debugging) { top->setColSpacing(3, 5); top->setColSpacing(5, 5); } top->setRowStretch(row, 1); updateRegisterAddresses(); } void Pic::BankWidget::bankChanged() { updateRegisterAddresses(); updateView(); } uint Pic::BankWidget::bank() const { const Pic::Data &data = static_cast(*Main::deviceData()); if ( !data.is18Family() ) return _bindex; if ( _bindex==0 ) return 0; const Pic::RegistersData &rdata = data.registersData(); if ( _bindex==1 ) return rdata.nbBanks - 1; return (_bankCombo->currentItem()+1)/2; } uint Pic::BankWidget::nbRegisters() const { const Pic::Data &data = static_cast(*Main::deviceData()); const Pic::RegistersData &rdata = data.registersData(); if ( !data.is18Family() ) return rdata.nbRegistersPerBank(); if ( _bindex==0 || (_bankCombo && _bankCombo->currentItem()==2*int(rdata.nbBanks)-3) ) return rdata.accessBankSplit; if ( _bindex==1 || (_bankCombo && _bankCombo->currentItem()==0) ) return rdata.nbRegistersPerBank() - rdata.accessBankSplit; return rdata.nbRegistersPerBank() / 2; } uint Pic::BankWidget::indexOffset() const { const Pic::Data &data = static_cast(*Main::deviceData()); const Pic::RegistersData &rdata = data.registersData(); uint offset = bank() * rdata.nbRegistersPerBank(); if ( !data.is18Family() ) return offset; if ( _bindex==0 || (_bankCombo && (_bankCombo->currentItem()%2)==1) ) return offset; if ( _bindex==1 || (_bankCombo && _bankCombo->currentItem()==0) ) return offset + rdata.accessBankSplit; return offset + rdata.nbRegistersPerBank()/2; } void Pic::BankWidget::updateRegisterAddresses() { const Pic::Data &data = static_cast(*Main::deviceData()); const Pic::RegistersData &rdata = data.registersData(); uint nbChars = rdata.nbCharsAddress(); uint nb = nbRegisters(); uint offset = indexOffset(); for (uint k=0; k<_registers.count(); k++) { if ( kshow(); _registers[k].address = rdata.addressFromIndex(offset + k); _registers[k].alabel->setText(toHexLabel(_registers[k].address, nbChars) + ":"); } else _registers[k].alabel->hide(); } } void Pic::BankWidget::buttonActivated(int id) { const Pic::Data &data = static_cast(*Main::deviceData()); const Pic::RegistersData &rdata = data.registersData(); for (uint i=0; i<_registers.count(); i++) { if ( sender()!=_registers[i].button ) continue; Register::TypeData rtd(_registers[i].address, rdata.nbChars()); switch (id) { case ReadId: Debugger::manager->readRegister(rtd); break; case EditId: _registers[i].edit->selectAll(); _registers[i].edit->setFocus(); break; case WatchId: { bool isWatched = Register::list().isWatched(rtd); Debugger::manager->setRegisterWatched(rtd, !isWatched); break; } } break; } } void Pic::BankWidget::write() { const Pic::Data &data = static_cast(*Main::deviceData()); const Pic::RegistersData &rdata = data.registersData(); for (uint i=0; i<_registers.count(); i++) { if ( sender()!=_registers[i].edit ) continue; Register::TypeData rtd(_registers[i].address, rdata.nbChars()); Debugger::manager->writeRegister(rtd, _registers[i].edit->value()); break; } } void Pic::BankWidget::updateView() { const Pic::Data &data = static_cast(*Main::deviceData()); const Pic::RegistersData &rdata = data.registersData(); bool active = ( Main::programmerState()==Programmer::Halted ); const Coff::Object *coff = Debugger::manager->coff(); uint nb = nbRegisters(); for (uint i=0; i<_registers.count(); i++) { uint address = _registers[i].address; Device::RegisterProperties rp = rdata.properties(address); TQString label = rdata.label(address); Register::TypeData rtd(address, rdata.nbChars()); bool isWatched = Register::list().isWatched(rtd); if (coff) { TQString name = coff->variableName(address); if ( !name.isEmpty() ) label = "<" + name + ">"; } if (_registers[i].button) { if ( ishow(); _registers[i].button->setText(label); if (isWatched) { TQFont f = _registers[i].button->font(); f.setBold(true); _registers[i].button->setFont(f); } else _registers[i].button->unsetFont(); _registers[i].button->popup()->setItemEnabled(ReadId, active && (rp & Device::Readable)); _registers[i].button->popup()->setItemEnabled(EditId, active); _registers[i].button->popup()->changeItem(WatchId, isWatched ? i18n("Stop Watching") : i18n("Watch")); _registers[i].button->popup()->setItemEnabled(WatchId, rp & Device::Readable); } else _registers[i].button->hide(); } if (_registers[i].label) { if ( ishow(); _registers[i].label->setText(label); } else _registers[i].label->hide(); } if (_registers[i].edit) { if ( ishow(); _registers[i].edit->setEnabled(active); BitValue value = Register::list().value(rtd); if ( value!=Register::list().oldValue(rtd) ) _registers[i].edit->setColor(red); else _registers[i].edit->unsetColor(); _registers[i].edit->setValue(NumberBase::Hex, value, rdata.nbChars()); } else _registers[i].edit->hide(); } } } //----------------------------------------------------------------------------- Pic::RegisterView::RegisterView(TQWidget *parent) : Register::View(parent, "pic_register_view"), _readAllButton(0), _clearAllButton(0) { TQVBoxLayout *vbox = new TQVBoxLayout(this, 10, 10); TQHBoxLayout *hbox = new TQHBoxLayout(vbox); bool debugging = Main::programmerGroup().isDebugger(); const Pic::Data &data = static_cast(*Main::deviceData()); uint nb = data.registersData().nbBanks; if ( debugging && nb!=0 ) { TQWidget *w = new TQWidget(this); hbox->addWidget(w); TQGridLayout *grid = new TQGridLayout(w, 1, 1, 0, 10); _readAllButton = new TQPushButton(i18n("Read All"), w); connect(_readAllButton, TQ_SIGNAL(clicked()), Debugger::manager, TQ_SLOT(readAllRegisters())); grid->addWidget(_readAllButton, 0, 0); _clearAllButton = new TQPushButton(i18n("Clear all watching"), w); connect(_clearAllButton, TQ_SIGNAL(clicked()), TQ_SLOT(stopWatchAllRegisters())); grid->addWidget(_clearAllButton, 0, 1); grid->setColStretch(2, 1); } TQHBoxLayout *hbox2 = 0; if ( nb==0 ) { TQLabel *label = new TQLabel(i18n("Registers information not available."), this); vbox->addWidget(label); } else { hbox = new TQHBoxLayout(vbox); hbox2 = new TQHBoxLayout(hbox); hbox->addStretch(1); if ( data.is18Family() ) { nb = 2; for (uint k=1; kshow(); hbox2->addWidget(_banks[i]); } } vbox->addStretch(1); } void Pic::RegisterView::updateView() { if (_readAllButton) _readAllButton->setEnabled(Main::programmerState()==Programmer::Halted); for (uint i=0; i<_banks.count(); i++) if (_banks[i]) _banks[i]->updateView(); } void Pic::RegisterView::stopWatchAllRegisters() { Debugger::manager->stopWatchAll(); } //---------------------------------------------------------------------------- Pic::RegisterListViewItem::RegisterListViewItem(const Register::TypeData &data, TDEListViewItem *parent) : Register::ListViewItem(data, parent) {} uint Pic::RegisterListViewItem::nbCharsAddress() const { const Pic::Data &data = static_cast(*Main::deviceData()); return data.registersData().nbCharsAddress(); } TQString Pic::RegisterListViewItem::label() const { if ( _data.type()!=Register::Regular ) return _data.name(); const Coff::Object *coff = Debugger::manager->coff(); if (coff) { TQString name = coff->variableName(_data.address()); if ( !name.isEmpty() ) return "<" + name + ">"; } const Pic::Data &data = static_cast(*Main::deviceData()); return data.registersData().label(_data.address()); } #include "pic_register_view.moc"