2021-05-26 20:38:27 +02:00
# include "register.h"
# include <exception>
# include <QHeaderView>
2021-05-27 20:13:02 +02:00
# include <QDebug>
2021-05-26 20:38:27 +02:00
Register : : Register ( QString name , int address , int width )
: QObject ( nullptr ) ,
name ( name ) ,
address ( address ) ,
2021-05-27 20:13:02 +02:00
width ( width ) ,
updating ( false )
2021-05-26 20:38:27 +02:00
{
value = 0 ;
}
void Register : : assignUI ( QCheckBox * cb , int bitpos , bool inverted )
{
connect ( this , & Register : : valueChanged , [ = ] ( unsigned int newval ) {
2021-06-06 00:04:47 +02:00
bool bit = newval & ( 1ULL < < bitpos ) ;
2021-05-26 20:38:27 +02:00
if ( inverted ) {
bit = ! bit ;
}
cb - > setChecked ( bit ) ;
} ) ;
connect ( cb , & QCheckBox : : toggled , [ = ] ( bool checked ) {
if ( inverted ) {
checked = ! checked ;
}
setValue ( checked , bitpos , 1 ) ;
} ) ;
}
2021-05-27 20:13:02 +02:00
void Register : : assignUI ( QComboBox * cb , int pos , int width , int ui_bitoffset )
2021-05-26 20:38:27 +02:00
{
connect ( this , & Register : : valueChanged , [ = ] ( ) {
auto value = getValue ( pos , width ) ;
2021-06-06 00:04:47 +02:00
auto mask = createMask ( width ) ;
2021-05-27 20:13:02 +02:00
mask < < = ui_bitoffset ;
value < < = ui_bitoffset ;
auto old_gui = cb - > currentIndex ( ) ;
old_gui & = ~ mask ;
old_gui | = value ;
if ( cb - > count ( ) > static_cast < int > ( old_gui ) ) {
updating = true ;
cb - > setCurrentIndex ( old_gui ) ;
updating = false ;
2021-05-26 20:38:27 +02:00
}
} ) ;
connect ( cb , qOverload < int > ( & QComboBox : : currentIndexChanged ) , [ = ] ( int index ) {
2021-05-27 20:13:02 +02:00
if ( ! updating ) {
index > > = ui_bitoffset ;
setValue ( index , pos , width ) ;
}
2021-05-26 20:38:27 +02:00
} ) ;
}
2021-05-27 20:13:02 +02:00
void Register : : assignUI ( QSpinBox * sb , int pos , int width , int ui_bitoffset )
2021-05-26 20:38:27 +02:00
{
connect ( this , & Register : : valueChanged , [ = ] ( ) {
auto value = getValue ( pos , width ) ;
2021-06-06 00:04:47 +02:00
auto mask = createMask ( width ) ;
2021-05-27 20:13:02 +02:00
mask < < = ui_bitoffset ;
value < < = ui_bitoffset ;
auto old_gui = sb - > value ( ) ;
old_gui & = ~ mask ;
old_gui | = value ;
updating = true ;
sb - > setValue ( old_gui ) ;
updating = false ;
2021-05-26 20:38:27 +02:00
} ) ;
connect ( sb , qOverload < int > ( & QSpinBox : : valueChanged ) , [ = ] ( int index ) {
2021-05-27 20:13:02 +02:00
if ( ! updating ) {
index > > = ui_bitoffset ;
setValue ( index , pos , width ) ;
}
2021-05-26 20:38:27 +02:00
} ) ;
}
2021-05-29 17:02:13 +02:00
void Register : : assignUI ( std : : vector < Register * > regs , int address , QCheckBox * cb , int bitpos , bool inverted )
{
auto reg = findByAddress ( regs , address ) ;
if ( reg ) {
reg - > assignUI ( cb , bitpos , inverted ) ;
}
}
void Register : : assignUI ( std : : vector < Register * > regs , int address , QComboBox * cb , int pos , int width , int ui_bitoffset )
{
auto reg = findByAddress ( regs , address ) ;
if ( reg ) {
reg - > assignUI ( cb , pos , width , ui_bitoffset ) ;
}
}
void Register : : assignUI ( std : : vector < Register * > regs , int address , QSpinBox * sb , int pos , int width , int ui_bitoffset )
{
auto reg = findByAddress ( regs , address ) ;
if ( reg ) {
reg - > assignUI ( sb , pos , width , ui_bitoffset ) ;
}
}
2021-05-26 20:38:27 +02:00
QString Register : : hexString ( )
{
return " 0x " + QString ( " %1 " ) . arg ( value , ( width - 1 ) / 4 + 1 , 16 , QChar ( ' 0 ' ) ) ;
}
bool Register : : setFromString ( QString s )
{
bool okay ;
auto num = s . toULong ( & okay , 0 ) ;
if ( okay ) {
setValue ( num ) ;
}
return okay ;
}
2021-06-06 00:04:47 +02:00
unsigned long long Register : : getValue ( )
2021-05-26 20:38:27 +02:00
{
return value ;
}
2021-06-06 00:04:47 +02:00
unsigned long long Register : : getValue ( int pos , int width )
2021-05-26 20:38:27 +02:00
{
2021-06-06 00:04:47 +02:00
unsigned long mask = createMask ( width ) ;
2021-05-26 20:38:27 +02:00
mask < < = pos ;
auto masked = value & mask ;
masked > > = pos ;
return masked ;
}
2021-06-06 00:04:47 +02:00
void Register : : setValue ( unsigned long long newval )
2021-05-26 20:38:27 +02:00
{
setValue ( newval , 0 , width ) ;
}
2021-06-06 00:04:47 +02:00
void Register : : setValue ( unsigned long long newval , int pos , int width )
2021-05-26 20:38:27 +02:00
{
2021-06-06 00:04:47 +02:00
unsigned long long mask = createMask ( width ) ;
2021-05-26 20:38:27 +02:00
newval & = mask ;
newval < < = pos ;
mask < < = pos ;
auto oldval = value ;
value & = ~ mask ;
value | = newval ;
if ( newval ! = oldval ) {
emit valueChanged ( value ) ;
}
}
2021-05-29 17:02:13 +02:00
Register * Register : : findByAddress ( std : : vector < Register * > regs , int address )
{
for ( auto r : regs ) {
if ( r - > getAddress ( ) = = address ) {
return r ;
}
}
return nullptr ;
}
2021-06-06 00:04:47 +02:00
unsigned long long Register : : createMask ( int width )
{
// can't shift by 64 bits at a time (apparantly a limit of the instruction set: https://stackoverflow.com/questions/55376273/weird-result-in-left-shift-1ull-s-1-if-s-64)
// Maximum register width is 64 for now, so shift by one less than width and then shift again by one
return ( ( 1ULL < < ( width - 1 ) ) < < 1 ) - 1 ;
}
2021-05-26 20:38:27 +02:00
int Register : : getAddress ( ) const
{
return address ;
}
QString Register : : getName ( ) const
{
return name ;
}
void Register : : fillTableWidget ( QTableWidget * l , std : : vector < Register * > regs )
{
l - > clear ( ) ;
l - > setRowCount ( regs . size ( ) ) ;
l - > setColumnCount ( 3 ) ;
l - > setHorizontalHeaderLabels ( { " Name " , " Address " , " Value " } ) ;
l - > verticalHeader ( ) - > setVisible ( false ) ;
l - > horizontalHeader ( ) - > setStretchLastSection ( true ) ;
// l->setSortingEnabled(true);
for ( unsigned int i = 0 ; i < regs . size ( ) ; i + + ) {
l - > setItem ( i , 0 , new QTableWidgetItem ( regs [ i ] - > getName ( ) ) ) ;
l - > item ( i , 0 ) - > setFlags ( l - > item ( i , 0 ) - > flags ( ) & = ~ Qt : : ItemIsEditable ) ;
auto address = " 0x " + QString : : number ( regs [ i ] - > address , 16 ) ;
l - > setItem ( i , 1 , new QTableWidgetItem ( address ) ) ;
l - > item ( i , 1 ) - > setFlags ( l - > item ( i , 1 ) - > flags ( ) & = ~ Qt : : ItemIsEditable ) ;
auto valueItem = new QTableWidgetItem ;
valueItem - > setFlags ( valueItem - > flags ( ) | Qt : : ItemIsEditable ) ;
valueItem - > setData ( Qt : : DisplayRole , regs [ i ] - > hexString ( ) ) ;
l - > setItem ( i , 2 , valueItem ) ;
connect ( regs [ i ] , & Register : : valueChanged , [ = ] ( ) {
l - > item ( i , 2 ) - > setData ( Qt : : DisplayRole , regs [ i ] - > hexString ( ) ) ;
} ) ;
}
connect ( l , & QTableWidget : : cellChanged , [ = ] ( int row , int column ) {
if ( column = = 2 ) {
auto reg = regs [ row ] ;
QString input = l - > item ( row , column ) - > data ( Qt : : DisplayRole ) . toString ( ) ;
reg - > setFromString ( input ) ;
l - > item ( row , column ) - > setData ( Qt : : DisplayRole , reg - > hexString ( ) ) ;
}
} ) ;
}