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.
piklab/src/devices/pic/gui/pic_memory_editor.cpp

405 lines
15 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 "pic_memory_editor.h"
#include <tqframe.h>
#include <tqgroupbox.h>
#include <tqlabel.h>
#include <tqscrollbar.h>
#include <tqgrid.h>
#include <tqhbox.h>
#include <tqtooltip.h>
#include <tqregexp.h>
#include <tqcolor.h>
#include <tqlayout.h>
#include <tqpixmap.h>
#include <klocale.h>
#include <kpushbutton.h>
#include <kaction.h>
#include "common/common/misc.h"
#include "pic_config_editor.h"
#include "libgui/toplevel.h"
#include "libgui/main_global.h"
#include "devices/pic/prog/pic_prog.h"
#include "libgui/global_config.h"
#include "pic_hex_view.h"
//-----------------------------------------------------------------------------
Pic::MemoryEditorLegend::Data::Data(const TQString &text, TQWidget *parent)
{
button = new PopupButton(text, parent);
KActionCollection *ac = 0;
KAction *a = new KAction(i18n("Go to start"), "top", 0, TQT_TQOBJECT(parent), TQT_SLOT(gotoStart()), ac);
actions.append(a);
button->appendAction(a);
a = new KAction(i18n("Go to end"), "bottom", 0, TQT_TQOBJECT(parent), TQT_SLOT(gotoEnd()), ac);
actions.append(a);
button->appendAction(a);
label = new TQLabel(parent);
}
void Pic::MemoryEditorLegend::Data::setProtected(bool on)
{
if (on) label->setPaletteBackgroundColor(MemoryEditorLegend::protectedColor());
else label->unsetPalette();
}
bool Pic::MemoryEditorLegend::Data::hasAction(const KAction *action) const
{
for (uint i=0; i<actions.count(); i++) if ( actions[i]==action ) return true;
return false;
}
//-----------------------------------------------------------------------------
const char * const Pic::MemoryEditorLegend::BLOCK_COLORS[Protection::MAX_NB_BLOCKS] = {
"#88FF88", "#88FFFF", "#FFFF88", "#FF88FF", "#0088FF", "#88FF00", "#00FF88", "#FF8800"
};
Pic::MemoryEditorLegend::MemoryEditorLegend(MemoryRangeType type, Memory &memory, TQWidget *parent)
: MemoryEditor(type, memory, parent, "memory_displayer_legend")
{
TQGridLayout *grid = new TQGridLayout(_top);
TQWidget *w = new TQWidget(this);
w->setFixedWidth(20);
w->setPaletteBackgroundColor(protectedColor());
grid->addWidget(w, 0, 0);
const Protection &protection = device().config().protection();
TQString s = (protection.family()==Protection::CodeGuard ? i18n("High Security") : i18n("Code protection"));
TQLabel *label = new TQLabel(s, this);
grid->addMultiCellWidget(label, 0,0, 1,2);
grid->addRowSpacing(1, 10);
uint row = 2;
if ( type==MemoryRangeType::Code && protection.hasBootBlock() ) {
w = new TQWidget(this);
w->setFixedWidth(20);
w->setPaletteBackgroundColor(bootColor());
grid->addWidget(w, row, 0);
_boot = Data(protection.bootLabel(), this);
grid->addWidget(_boot.button, row, 1);
grid->addWidget(_boot.label, row, 2);
row++;
}
uint nb = (type==MemoryRangeType::Code ? protection.nbBlocks() : 0);
for (uint i=0; i<nb; i++) {
w = new TQWidget(this);
w->setFixedWidth(20);
w->setPaletteBackgroundColor(blockColor(i));
grid->addWidget(w, row, 0);
_blocks.append(Data(protection.blockLabel(i), this));
grid->addWidget(_blocks[i].button, row, 1);
grid->addWidget(_blocks[i].label, row, 2);
row++;
}
}
void Pic::MemoryEditorLegend::updateDisplay()
{
const Protection &protection = device().config().protection();
Protection::Type ptype = (protection.family()==Protection::CodeGuard ? Protection::HighSecurity : Protection::ProgramProtected);
uint nbChars = 2 * device().nbBytesAddress();
if (_boot.label) {
AddressRange r = memory().bootRange();
if ( r.isEmpty() ) _boot.label->setText(i18n("not present"));
else _boot.label->setText(TQString("[%1:%2]").tqarg(toHex(r.start, nbChars)).tqarg(toHex(r.end, nbChars)));
_boot.button->setEnabled(!r.isEmpty());
_boot.setProtected(memory().isBootProtected(ptype));
}
for (uint i=0; i<_blocks.count(); i++) {
AddressRange r = memory().blockRange(i);
if ( r.isEmpty() ) _blocks[i].label->setText(i18n("not present"));
else _blocks[i].label->setText(TQString("[%1:%2]").tqarg(toHex(r.start, nbChars)).tqarg(toHex(r.end, nbChars)));
_blocks[i].button->setEnabled(!r.isEmpty());
_blocks[i].setProtected(memory().isBlockProtected(ptype, i));
}
}
void Pic::MemoryEditorLegend::gotoStart()
{
Address start = device().range(type()).start;
const KAction *action = static_cast<const KAction *>(sender());
if ( _boot.hasAction(action) ) {
AddressRange r = memory().bootRange();
emit setStartWord(r.start - start);
return;
}
for (uint i=0; i<_blocks.count(); i++) {
if ( _blocks[i].hasAction(action) ) {
AddressRange r = memory().blockRange(i);
emit setStartWord(r.start - start);
return;
}
}
Q_ASSERT(false);
}
void Pic::MemoryEditorLegend::gotoEnd()
{
Address start = device().range(type()).start;
const KAction *action = static_cast<const KAction *>(sender());
if ( _boot.hasAction(action) ) {
AddressRange r = memory().bootRange();
emit setEndWord(r.end - start);
return;
}
for (uint i=0; i<_blocks.count(); i++) {
if ( _blocks[i].hasAction(action) ) {
AddressRange r = memory().blockRange(i);
emit setEndWord(r.end - start);
return;
}
}
Q_ASSERT(false);
}
//-----------------------------------------------------------------------------
Pic::HexWordEditor::HexWordEditor(MemoryRangeType type, Memory &memory, TQWidget *parent)
: Device::HexWordEditor(memory, memory.device().nbCharsWord(type), parent),
MemoryCaster(type, memory)
{}
void Pic::HexWordEditor::setWord(BitValue value)
{
if ( type()==MemoryRangeType::Config ) {
const Config::Word &cword = device().config()._words[_offset];
value |= cword.usedMask().complementInMask(device().mask(MemoryRangeType::Config));
}
memory().setWord(type(), _offset, value);
}
//-----------------------------------------------------------------------------
Pic::MemoryRangeEditor::MemoryRangeEditor(MemoryRangeType type, Memory &memory,
uint nbLines, uint nbCols,
uint wordOffset, int nbWords, TQWidget *parent)
: Device::MemoryRangeEditor(memory, nbLines, nbCols, wordOffset, nbWords, parent, "pic_memory_range_editor"),
MemoryCaster(type, memory), _legend(0)
{
if ( type==MemoryRangeType::Code ) _blockRanges.resize(memory.device().config().protection().nbBlocks());
}
void Pic::MemoryRangeEditor::addLegend(TQVBoxLayout *vbox)
{
if ( type()==MemoryRangeType::Code || type()==MemoryRangeType::Eeprom ) {
_legend = new MemoryEditorLegend(type(), memory(), this);
connect(_legend, TQT_SIGNAL(setStartWord(int)), TQT_SLOT(setStartWord(int)));
connect(_legend, TQT_SIGNAL(setEndWord(int)), TQT_SLOT(setEndWord(int)));
vbox->addWidget(_legend);
}
}
bool Pic::MemoryRangeEditor::isRangeReadOnly() const
{
return ( (type().data().properties & ReadOnly) || type()==MemoryRangeType::CalBackup );
}
void Pic::MemoryRangeEditor::updateDisplay()
{
const Protection &protection = device().config().protection();
if ( type()==MemoryRangeType::Code ) {
if ( protection.hasBootBlock() ) _bootRange = memory().bootRange();
for (uint k=0; k<_blockRanges.count(); k++)
_blockRanges[k] = memory().blockRange(k);
}
Protection::Type ptype = (protection.family()==Protection::CodeGuard ? Protection::HighSecurity : Protection::ProgramProtected);
_codeProtected = memory().protectedRanges(ptype, type());
Device::MemoryRangeEditor::updateDisplay();
if (_legend) _legend->updateDisplay();
}
void Pic::MemoryRangeEditor::updateAddressColor(uint i, Address address)
{
if ( _codeProtected.contains(address) )
_addresses[i]->setPaletteBackgroundColor(MemoryEditorLegend::protectedColor());
else _addresses[i]->unsetPalette();
_blocks[i]->unsetPalette();
if ( type()==MemoryRangeType::Code ) {
if ( _bootRange.contains(address) ) _blocks[i]->setPaletteBackgroundColor(MemoryEditorLegend::bootColor());
else for (uint k=0; k<_blockRanges.count(); k++) {
if ( !_blockRanges[k].contains(address) ) continue;
_blocks[i]->setPaletteBackgroundColor(MemoryEditorLegend::blockColor(k));
break;
}
}
}
Device::HexWordEditor *Pic::MemoryRangeEditor::createHexWordEditor(TQWidget *parent)
{
return new HexWordEditor(type(), memory(), parent);
}
//-----------------------------------------------------------------------------
Pic::MemoryTypeEditor::MemoryTypeEditor(const HexView *hexview, MemoryRangeType type, Memory &memory, TQWidget *parent, const char *name)
: Device::MemoryTypeEditor(hexview, memory, parent, name), MemoryCaster(type, memory)
{}
void Pic::MemoryTypeEditor::init(bool first)
{
Device::MemoryTypeEditor::init(first);
_title->setText(type().label());
uint nbChars = device().nbCharsWord(type());
TQString add;
if ( type()==MemoryRangeType::UserId ) add = i18n(" - recommended mask: %1").tqarg(toHexLabel(device().userIdRecommendedMask(), nbChars));
if ( type()==MemoryRangeType::Cal && _hexview ) add = i18n(" - not programmed by default");
TQString comment = i18n("%1-bit words - mask: %2")
.tqarg(device().nbBitsWord(type())).tqarg(toHexLabel(device().mask(type()), nbChars));
_comment->setText(comment + add);
}
bool Pic::MemoryTypeEditor::internalDoAction(Device::Action action)
{
Programmer::PicBase *prog = static_cast<Programmer::PicBase *>(Main::programmer());
switch (action) {
case Device::Clear: memory().clear(type()); return true;
case Device::Zero: memory().fill(type(), 0); return true;
case Device::ChecksumCheck : memory().checksumCheckFill(); return true;
case Device::Reload: {
const Memory *omemory = static_cast<const Memory *>(originalMemory());
Q_ASSERT(omemory);
memory().copyFrom(type(), *omemory); return true;
}
case Device::Program:
prog->programSingle(type(), memory());
return false;
case Device::Verify:
prog->verifySingle(type(), memory());
return false;
case Device::Read:
return prog->readSingle(type(), memory());
case Device::Erase:
prog->eraseSingle(type());
return false;
case Device::BlankCheck:
prog->blankCheckSingle(type());
return false;
case Device::Nb_Actions: break;
}
Q_ASSERT(false);
return false;
}
//-----------------------------------------------------------------------------
Pic::MemoryTypeRangeEditor::MemoryTypeRangeEditor(const HexView *hexview, MemoryRangeType type, Memory &memory, TQWidget *parent)
: MemoryTypeEditor(hexview, type, memory, parent, "pic_memory_type_range_editor"), _mre(0)
{}
void Pic::MemoryTypeRangeEditor::init(bool first)
{
MemoryTypeEditor::init(first);
uint nbLines = 0;
if ( type()==MemoryRangeType::Code ) nbLines = 16;
else if ( type()==MemoryRangeType::Eeprom ) nbLines = 8;
else nbLines = (device().nbWords(type())/8>1 ? 2 : 1);
_mre = new MemoryRangeEditor(type(), memory(), nbLines, 8, 0, -1, this);
addEditor(_mre);
_top->addWidget(_mre);
_mre->init();
}
//-----------------------------------------------------------------------------
Pic::MemoryUserIdEditor::MemoryUserIdEditor(const HexView *hexview, Memory &memory, TQWidget *parent)
: MemoryTypeRangeEditor(hexview, MemoryRangeType::UserId, memory, parent), _saveReadOnly(false)
{}
void Pic::MemoryUserIdEditor::init(bool first)
{
MemoryTypeRangeEditor::init(first);
_setToChecksum = new KToggleAction(i18n("Set to unprotected checksum"), 0, 0,
TQT_TQOBJECT(this), TQT_SLOT(toggleSetToChecksum()), Main::toplevel().actionCollection());
addAction(_setToChecksum);
if ( readConfigEntry(BaseGlobalConfig::UserIdSetToChecksum).toBool() && memory().isClear(MemoryRangeType::UserId) ) {
_setToChecksum->activate();
toggleSetToChecksum();
}
}
void Pic::MemoryUserIdEditor::toggleSetToChecksum()
{
if ( _setToChecksum->isChecked() ) {
_mre->setComment(i18n("Set to unprotected checksum"));
emit modified();
} else _mre->setComment(TQString());
setReadOnly(_saveReadOnly);
}
void Pic::MemoryUserIdEditor::updateDisplay()
{
if ( _setToChecksum->isChecked() ) memory().setUserIdToUnprotectedChecksum();
MemoryTypeRangeEditor::updateDisplay();
}
void Pic::MemoryUserIdEditor::setReadOnly(bool readOnly)
{
_saveReadOnly = readOnly;
MemoryTypeRangeEditor::setReadOnly(readOnly || _setToChecksum->isChecked());
}
//-----------------------------------------------------------------------------
Pic::MemoryCalibrationEditor::MemoryCalibrationEditor(const HexView *hexview, Memory &memory, TQWidget *parent)
: MemoryTypeEditor(hexview, MemoryRangeType::Cal, memory, parent, "pic_memory_calibration_editor")
{}
void Pic::MemoryCalibrationEditor::init(bool first)
{
MemoryTypeEditor::init(first);
MemoryRangeEditor *mre = new MemoryRangeEditor(MemoryRangeType::Cal, memory(), 1, 8, 0, -1, this);
addEditor(mre);
_top->addWidget(mre);
mre->init();
if ( device().isReadable(MemoryRangeType::CalBackup) ) {
mre = new MemoryRangeEditor(MemoryRangeType::CalBackup, memory(), 1, 8, 0, -1, this);
addEditor(mre);
_top->addWidget(mre);
mre->init();
mre->setComment(i18n("(backup)"));
}
}
bool Pic::MemoryCalibrationEditor::hasAction(Device::Action action) const
{
return ( action==Device::Read || action==Device::Verify || action==Device::Program );
}
bool Pic::MemoryCalibrationEditor::internalDoAction(Device::Action action)
{
Programmer::PicBase *prog = static_cast<Programmer::PicBase *>(Main::programmer());
switch (action) {
case Device::Reload: {
const Memory *omemory = static_cast<const Memory *>(originalMemory());
Q_ASSERT(omemory);
memory().copyFrom(MemoryRangeType::Cal, *omemory);
memory().copyFrom(MemoryRangeType::CalBackup, *omemory);
return true;
}
case Device::Program:
if ( prog->programCalibration(memory().arrayForWriting(Pic::MemoryRangeType::Cal)) )
return prog->readSingle(MemoryRangeType::Cal, memory());
return false;
case Device::Verify:
prog->verifySingle(MemoryRangeType::Cal, memory());
return false;
case Device::Read:
return prog->readSingle(MemoryRangeType::Cal, memory());
case Device::Clear:
case Device::Zero:
case Device::ChecksumCheck:
case Device::Erase:
case Device::BlankCheck:
case Device::Nb_Actions: break;
}
Q_ASSERT(false);
return false;
}