|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org> *
|
|
|
|
* *
|
|
|
|
* 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 "register.h"
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
namespace Register
|
|
|
|
{
|
|
|
|
List *_list = 0;
|
|
|
|
}
|
|
|
|
Register::List &Register::list()
|
|
|
|
{
|
|
|
|
if ( _list==0 ) _list = new List;
|
|
|
|
return *_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
Register::TypeData::TypeData(Address address, uint nbChars)
|
|
|
|
: _nbChars(nbChars), _address(address)
|
|
|
|
{
|
|
|
|
Q_ASSERT( address.isValid() && nbChars!=0 );
|
|
|
|
}
|
|
|
|
Register::TypeData::TypeData(const TQString &name, uint nbChars)
|
|
|
|
: _nbChars(nbChars), _name(name)
|
|
|
|
{
|
|
|
|
Q_ASSERT( !name.isEmpty() && nbChars!=0 );
|
|
|
|
}
|
|
|
|
Register::TypeData::TypeData(const TQString &name, Address address, uint nbChars)
|
|
|
|
: _nbChars(nbChars), _address(address), _name(name)
|
|
|
|
{
|
|
|
|
Q_ASSERT( address.isValid() && nbChars!=0 && !name.isEmpty() );
|
|
|
|
}
|
|
|
|
|
|
|
|
Register::Type Register::TypeData::type() const
|
|
|
|
{
|
|
|
|
if ( !_address.isValid() ) {
|
|
|
|
if ( _name.isEmpty() ) return Invalid;
|
|
|
|
return Special;
|
|
|
|
}
|
|
|
|
if ( _name.isEmpty() ) return Regular;
|
|
|
|
return Combined;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Register::TypeData::toString() const
|
|
|
|
{
|
|
|
|
return TQString("%1 %2 %3").tqarg(toLabel(_address)).tqarg(_nbChars).tqarg(_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
Register::TypeData Register::TypeData::fromString(const TQString &s)
|
|
|
|
{
|
|
|
|
TQStringList list = TQStringList::split(" ", s);
|
|
|
|
if ( list.count()<2 || list.count()>3 ) return TypeData();
|
|
|
|
bool ok;
|
|
|
|
Address address = list[0].toUInt(&ok);
|
|
|
|
if ( !ok ) return TypeData();
|
|
|
|
uint nbChars = list[1].toUInt(&ok);
|
|
|
|
if ( !ok || nbChars==0 || (nbChars%2)!=0 ) return TypeData();
|
|
|
|
TQString name;
|
|
|
|
if ( list.count()==3 ) name = list[2];
|
|
|
|
if ( !address.isValid() ) {
|
|
|
|
if ( name.isEmpty() ) return TypeData();
|
|
|
|
return TypeData(name, nbChars);
|
|
|
|
}
|
|
|
|
if ( name.isEmpty() ) return TypeData(address, nbChars);
|
|
|
|
return TypeData(name, address, nbChars);
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void Register::List::init()
|
|
|
|
{
|
|
|
|
_regulars.clear();
|
|
|
|
_specials.clear();
|
|
|
|
_watched.clear();
|
|
|
|
_portDatas.clear();
|
|
|
|
delayedChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Register::List::setWatched(const TypeData &data, bool watched)
|
|
|
|
{
|
|
|
|
if (watched) {
|
|
|
|
if ( _watched.contains(data) ) return;
|
|
|
|
_watched.append(data);
|
|
|
|
} else _watched.remove(data);
|
|
|
|
delayedChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Register::List::clearWatched()
|
|
|
|
{
|
|
|
|
_watched.clear();
|
|
|
|
delayedChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Register::List::setValue(const TypeData &data, BitValue value)
|
|
|
|
{
|
|
|
|
if ( !data.address().isValid() ) {
|
|
|
|
_specials[data.name()].old = _specials[data.name()].current;
|
|
|
|
_specials[data.name()].current = value;
|
|
|
|
} else {
|
|
|
|
Q_ASSERT( (data.nbChars()%2)==0 );
|
|
|
|
uint nb = data.nbChars()/2;
|
|
|
|
for (uint i=0; i<nb; i++) {
|
|
|
|
Address address = data.address() + i;
|
|
|
|
_regulars[address].old = _regulars[address].current;
|
|
|
|
_regulars[address].current = value.byte(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
delayedChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Register::List::setPortData(uint index, const TQMap<uint, Device::PortBitData> &data)
|
|
|
|
{
|
|
|
|
_portDatas[index].old = _portDatas[index].current;
|
|
|
|
_portDatas[index].current = data;
|
|
|
|
delayedChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
BitValue Register::List::value(const TypeData &data) const
|
|
|
|
{
|
|
|
|
if ( !data.address().isValid() ) {
|
|
|
|
if ( !_specials.contains(data.name()) ) return BitValue();
|
|
|
|
return _specials[data.name()].current;
|
|
|
|
}
|
|
|
|
Q_ASSERT( (data.nbChars()%2)==0 );
|
|
|
|
uint nb = data.nbChars()/2;
|
|
|
|
BitValue value = 0;
|
|
|
|
for (int i=nb-1; i>=0; i--) {
|
|
|
|
value <<= 8;
|
|
|
|
BitValue v = _regulars[data.address() + i].current;
|
|
|
|
if ( !v.isInitialized() ) return BitValue();
|
|
|
|
value += v;
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
BitValue Register::List::oldValue(const TypeData &data) const
|
|
|
|
{
|
|
|
|
if ( !data.address().isValid() ) {
|
|
|
|
if ( !_specials.contains(data.name()) ) return BitValue();
|
|
|
|
return _specials[data.name()].old;
|
|
|
|
}
|
|
|
|
Q_ASSERT( (data.nbChars()%2)==0 );
|
|
|
|
uint nb = data.nbChars()/2;
|
|
|
|
BitValue value = 0;
|
|
|
|
for (int i=nb-1; i>=0; i--) {
|
|
|
|
value <<= 8;
|
|
|
|
BitValue v = _regulars[data.address() + i].old;
|
|
|
|
if ( !v.isInitialized() ) return BitValue();
|
|
|
|
value += v;
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|