Showing posts with label Cpp. Show all posts
Showing posts with label Cpp. Show all posts

Fast linked list without list

If you need a very fast way to iterate over a list of objects and call the same method on all of them, then here is a posible solution.
Derive your objects from this class and implement doSomething():

class Element
{
    public:
        Element();
        ~Element();

        virtual void doSomething()=0;

        Element* next;

        static void addElement( Element* el )
        {
            el->next = first;
            first = el;
        }

        static Element* first=nullptr;
};

And to use it:

    // Adding one element to the list:
    Element::addElement( &myObject );

    // Iterating over the objects:
    Element* el = Element::first;
    while( el )
    {
        el->doSomething();
        el = el->next;
    }


Find file in folder recursive with Qt.


This function returns the absolute path of a file in a folder (or subfolder).
It searchs recursively in all subfolders until it finds the file or return an empty QString if the file is not found.


QString findFile( QString dir, QString fileName )
{
    QDir pathDir( dir );
    for( QFileInfo fileInfo : pathDir.entryInfoList() )
    {
        if( fileInfo.isFile() )
        {
            if( fileInfo.fileName() == fileName ) 
                return fileInfo.absoluteFilePath();
        }
        else if( !fileInfo.fileName().endsWith(".") )
        {
            QString found = findFile( fileInfo.absoluteFilePath(), fileName );
            if( !found.isEmpty() ) return found;
        }
    }
    return "";
}



Connect QObject signal to non QObject class.

Usually you need to derive from QObject and use the Q_OBJECT macro to connect to some slot in your class.
But sometimes you want to connect a QObject signal to do something in a non QObject class.

There are several posible reasons to not derive from QObject or use the Q_OBJECT macro, but in any case you can connect to a non QObejct class using lambdas:

```c
  // Connect to menu action

  QMenu* menu:

  QAction* myAction = menu->addAction( QIcon(":/myIcon.svg"), "Do something" );

  QObject::connect( myAction, &QAction::triggered, [=](){ myFuncion(); });



  // Connect to QPushButton

  QPushButton* button = new QPushButton();

  QObject::connect( button, &QPushButton::released, [=](){ onButtonReleased(); });
```


Submenu in a QMenu.

Adding a submenu to a QMenu is really easy, and you add nested submenus if you want:
```c
	QMenu* mainMenu;
	
	QAction* action1 = mainMenu->addAction(QIcon(":/icon1.png"),"Entry1" );
    connect( action1, &QAction::triggered,
                this, &MyClasss::mySlot1, Qt::UniqueConnection );

    QAction* action2 = mainMenu->addAction(QIcon(":/icon2.png"), "Entry2" );
    connect( action2, &QAction::triggered,
                this, &MyClasss::mySlot2, Qt::UniqueConnection );

	// --- SUBMENU --------------------------------------------------------
	
	QMenu* subMenu = mainMenu->addMenu( QIcon(":/menuIcon.png"), "SubMenu Title" );
	
	QAction* subAction1 = mainMenu->addAction(QIcon(":/subIcon1.png"),"subEntry1" );
    connect( subAction1, &QAction::triggered,
                   this, &MyClasss::subSlot1, Qt::UniqueConnection );

    QAction* subAction2 = mainMenu->addAction(QIcon(":/subIcon2.png"), "subEntry2" );
    connect( subAction2, &QAction::triggered,
                   this, &MyClasss::subSlot2, Qt::UniqueConnection );

	// --------------------------------------------------------------------
	
	
	QAction* action3 = mainMenu->addAction(QIcon(":/icon3.png"),"Entry3" );
    connect( action3, &QAction::triggered,
                this, &MyClasss::mySlot3, Qt::UniqueConnection );

    QAction* action4 = mainMenu->addAction(QIcon(":/icon4.png"), "Entry4" );
    connect( action4, &QAction::triggered,
                this, &MyClasss::mySlot4, Qt::UniqueConnection );
```

Simple and fast signal-slot system in C++.

 This is a simple and fast implementation of a signal-slot system in C++.

It's goal is to be simple and as fast as possible.

For that, we create a signal-slot system tha is specific for our use case, that's the price we pay for a fast system.
In this case we create callbacks that take an integer value, but it could be adapted for any oyhter use case.

First we need a base class for our callbacks.
We need this class to virtualize the call() function and easily link callbacks in order to create a list.
It is implemented as a linked list: each callbacks holds a pointer to the function to call and a pointer to the next callback.

```c
class CallBackBase
{
    public:
        CallBackBase(){;}
        virtual ~CallBackBase(){;}

        virtual void call( int ){;}

        CallBackBase* nextCallBack;
};
```

Here we have our callback class.
We create callbacks with an object and a member funtion to call:
```c
template <class Obj>
class CallBack : public CallBackBase
{
        friend class Signal;

    public:
        CallBack( Obj* object, void (Obj::*func)(int) )
        : CallBackBase()
        {
            m_object = object;
            m_func   = func;
            nextCallBack = 0;
        }
        ~CallBack() {;}

        virtual void call( int val ) override
        { (m_object->*m_func)(val); }

    private:
        Obj* m_object;
        void (Obj::*m_func)(uint8_t);
};
```

And this is our signal class:
We can add callbacks with the function connect() and remove callbacks with the function disconnect().
On emitValue() we call all the callbacks with an integer value as argument:

```c
class Signal
{
    public:
        Signal()
        {
            m_slot = 0;
        }
        ~Signal()       // Free resources created
        {
            CallBackBase* slot = m_slot;
            while( slot ) // delete slots
            {
                CallBackBase* slotDel = slot;
                slot = slot->nextCallBack;
                delete slotDel;
        }   }

        template <class Obj>
        void connect( Obj* obj, void (Obj::*func)(int) )
        {
            CallBack<Obj>* slot = new CallBack<Obj>( obj, func );

            slot->nextCallBack = m_slot;
            m_slot = slot;
        }

        template <class Obj>
        void disconnect( Obj* obj, void (Obj::*func)(int) )
        {
            CallBackBase* preSlot = 0;
            CallBackBase* posSlot = m_slot;
            while( posSlot )
            {
                CallBack<Obj>* cb = dynamic_cast<CallBack<Obj>*>(posSlot);

                if( cb->m_object == obj && cb->m_func == func )
                {
                    if( preSlot ) preSlot->nextCallBack = posSlot->nextCallBack;
                    else          m_slot = posSlot->nextCallBack;
                    delete posSlot;
                    break;
                }
                preSlot = posSlot;
                posSlot = posSlot->nextCallBack;
        }   }

        void emitValue( int val ) // Calls all connected CallBacks 
        {
            CallBackBase* slot = m_slot;
            while( slot )
            {
                slot->call( val );
                slot = slot->nextCallBack;
        }   }

    private:
        CallBackBase* m_slot;
};
```

To use it we create signals, connect callbacks and call emitValue() when needed.

```c
	AnObjectClass*    anObject     = new AnObjectClass();
	OtherObjectClass* otherObject  = new OtherObjectClass();
	ThirdObjectClass* thirdObject  = new ThirdObjectClass();
	OtherObjectClass* otherObject2 = new OtherObjectClass();

    Signal on_write;
    on_write.connect( anObject,    &AnObjectClass::writeFunc );
    on_write.connect( otherObject, &OtherObjectClass::otherFunc );
    
    Signal on_read;
    on_read.connect( thirdObject,  &ThirdObjectClass::readFunc );
    on_read.connect( otherObject2, &OtherObjectClass::someFunc );
    
    
    void on_write_event( int value )
    {
		on_write.emitValue( value );
	}
	
	void on_read_event( int value )
	{
		on_read.emitValue( value );
	}
```

C++ Pointer to member Function.

```c
// Create a data type: "Pointer to MyClass function" with type name: "funcPtr_t"
typedef void (MyClass::*funcPtr_t)();

QList funcList;           // Create a list of pointers

funcPtr_t fp = &MyClass::myFunction; // Create a pointer to function "myFunction" with name "fp"

funcList.append( fp );               // Add to list

for( funcPtr_t func : funcList)      // Call all functions in our list (there is only one)
{
	(this->*func)();                 // We are calling from an object of the same class
}

// ---------------------------------------------------------------------------------------------

Myclass myObject;

for( funcPtr_t func : funcList)      // Call all functions in our list (there is only one)
{
	(myObject.*func)();              // We are calling from outside "MyClass"
}

	// ---------------------------------------------------------------------------------------------

Myclass* myObject = new Myclass();

for( funcPtr_t func : funcList)      // Call all functions in our list (there is only one)
{
	(myObject->*func)();             // We are calling from outside "MyClass"
}
```

Integer to any base QString

This function takes an integer and returns a QString with the representation in any base < 16.

It uses the val2hex function from previous post:
.....................................................................................................
```c
QString val2hex( int d )
{
    QString Hex="0123456789ABCDEF";

    QString h = Hex.mid( d&15, 1 );

    while( d>15 )
    {
        d >>= 4;
        h = Hex.mid( d&15,1 ) + h;
    }
    return h;
}

QString decToBase( int value, int base, int digits )
{
    QString converted = "";

    for( int i=0; i= base ) converted = val2hex(value%base) + converted;
        else                converted = val2hex(value) + converted;

        value = floor( value/base );
    }
    return converted;
}
```
.....................................................................................................

Integer to Hex QString

This function takes an integer and returns a QString with the exadecimal representation:
.....................................................................................................
```c
QString val2hex( int d )
{
    QString Hex="0123456789ABCDEF";

    QString h = Hex.mid( d&15, 1 );

    while( d>15 )
    {
        d >>= 4;
        h = Hex.mid( d&15,1 ) + h;
    }
    return h;
}
```
.....................................................................................................

File to QString

Read a file and parse whole content to a QString:
.....................................................................................................
```c
QString fileToString( const QString &fileName, const QString &caller )
{
    QFile file( fileName );

    if( !file.open(QFile::ReadOnly | QFile::Text))
    {
        QMessageBox::warning( 0l, caller, 
                              "Cannot read file "
                              +fileName+":\n"
                              +file.errorString());
        return "";
    }

    QTextStream in( &file );
    QString text = in.readAll();
    file.close();

    return text;
}
```
.....................................................................................................

File to QStringList

Read a file and parse each line to a QStringList:

.....................................................................................................

```c
QStringList fileToStringList( const QString &fileName, const QString &caller )
{
    QStringList text;
    QFile file(fileName);

    if( !file.open( QFile::ReadOnly | QFile::Text) )
    {
        QMessageBox::warning( 0l, caller, 
                              "Cannot read file "
                              +fileName+":\n"
                              +file.errorString());
        return text;
    }

    QTextStream in( &file );
    while( !in.atEnd() ) text.append( in.readLine() );
    file.close();

    return text;
}
```

.....................................................................................................

Add entry to QListWidget and resize to content

Sometimes is useful resizing a QListWidget to the size of its content.
This is one way to do it.

Don't forget resizing again when you remove an item.

.....................................................................................................

```c
void addEntry( QString name, QListWidget* list )
{
    QListWidgetItem* item = new QListWidgetItem( name, list, 0 );
  
    QFont font;
    font.setPointSize(10);
    font.setWeight(70);
    item->setFont( font );

    item->setIcon( QIcon(":/icon.png") );
       
    int iconSize = 22;                       // I know icon size

    int size = list->count()*iconSize + 2;

    list->setFixedHeight( size );
}
```

.....................................................................................................

Wemos to InfluxDB via Wifi

This is a simple example of how to send data from a Wemos board to InfluxDB  throught wifi.

Tested with Wemos D1 R2 and Arduino IDE.

You should change ssid, password to your wifi.
Also InfluxDB database name and data you are using.

.....................................................................................................

```c
#include <Arduino.h>

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>

#define USE_SERIAL // Comment this line for no serial

const char* ssid = "Your_SSID";
const char* password = "Your_Pass";

ESP8266WiFiMulti WiFiMulti;

void setup()
{
    #ifdef USE_SERIAL
    Serial.begin( 115200 );
    #endif

    WiFi.mode( WIFI_STA );
    WiFiMulti.addAP( ssid, password );
}

void loop()
{
    if( WiFiMulti.run() == WL_CONNECTED ) // wait for WiFi connection
    {
        int sensorValue = analogRead( A0 );
       
        // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 3.2V):
        float voltage = sensorValue * (3.2/1023.0);
       
        #ifdef USE_SERIAL
        Serial.println( voltage );
        #endif
       
        HTTPClient http;

        #ifdef USE_SERIAL
        Serial.print( "[HTTP] begin...\n" );
        #endif
       
        // Start writting to influxbd database: mydb
        // Set database, IP and Port you are using
        http.begin( "http://192.168.1.33:8086/write?db=mydb" );
  
        // Send data to influxbd
        // Set data you are using
        int httpCode = http.POST( "Volts,Bat=Lead-Acid,Ser=pruebas value="+String(voltage) );
       
        #ifdef USE_SERIAL
        if(httpCode == 204) // Data Succesfully Written
        {
            Serial.printf( "Data Succesfully Written... code: %d\n", httpCode );

        }
        else // Data Failed
        {
            Serial.printf( "Data Failed... code: %d\n", httpCode );
            Serial.printf( "Error: %s\n", http.errorToString(httpCode).c_str() );
        }
        #endif
       
        http.end();
    }

    delay( 10000 ); // Wait for 10 seconds
}
```

.....................................................................................................

AVR Software PWM

One way to do software pwm is setting up a timer with interrupt corresponding to each pwm step. then in the interrupt routine check whether each pwm channel should be on or off.

The key question here is how fast and how many steps should be the PWM.
All depends in how much processing time you need for other tasks, and how many PWMs to run.

A good aproach that works for me is doing a 64 steps, 200 uS per step PWM for around 50 PWM channels.
This give us a total time of 50*200=12800 uS = 12.8 mS => 78.125 Hz.
Getting less than 10% of processing time.

I ussually do it with Timer0, this creates a 200 uS Timer0 CompA Interrupt.
I think it works for most AVR, but you can choose the part you need depending on wich registers your mcu uses:

```c
// For 16 MHz clock

#define T0Top_Avr 50
#define T0PresAvr 3

   #if defined( OCR0 )
      OCR0  = T0TOP_Avr;
      TCCR0 = 64 + TMR0PresAvr; // CTC mode: TOP = OCR0
   #elif defined( OCR0A )
      OCR0A  = T0TOP_Avr;
      TCCR0A = 2;               // CTC mode: TOP = OCR0A
      TCCR0B = TMR0PresAvr;
   #endif
  
   // enable Timer 0 compare_A interrupt
   #if defined( TIMSK0 )
      TIMSK0 = 0;
      TIMSK0 |= (1 << OCIE0A);
   #elif defined( TIMSK )
      TIMSK = 0;
      TIMSK |= (1 << OCIE0A);
   #endif
  
   sei();      // Enable interrupts



// Now in the interrupt routine:

#define numPWM 32             // Number of PWM Channels
uint8_t pwmChannel[ numPWM ]; // Array containing pwm values
uint8_t pwmCounter=0;

ISR(TIMER0_COMPA_vect)        // Timer 0 compare_A interrupt
 { 
    for( uint8_t i=0; i pwmCounter ) 
        {
            // Set the output line "i" HIGH
            // This depends on the hardware you are using
        }
        else
        {
            // Set the output line "i" LOW
        }
    }
    pwmCounter++;
    if( pwmCounter > 63 ) pwmCounter = 0;
{ 
```

Interrupciones Puerto Paralelo en C

Ejemplo de uso, espera por una interrupción, lee e imprime por pantalla el valor presente en el puerto de datos.

```c
//gcc -opport pport.c


#include <linux/ppdev.h>
#include <linux/parport.h>
#include <stropts.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/select.h>
 
#define PP_DEV_NAME "/dev/parport0"
 
int main()
{
    //Get a file descriptor for the parallel port
    int ppfd;
 
    ppfd = open(PP_DEV_NAME, O_RDWR);
    if(ppfd == -1)
    {
        printf("Unable to open parallel port!\n");
        return 1;
    }
 
    //Have to claim the device
    if(ioctl(ppfd, PPCLAIM))
    {
        printf("Couldn't claim parallel port!\n");
        close(ppfd);
        return 1;
    }
 
    while(1)
    {
        //Set up the control lines for when an interrupt happens
        int int_count;
        int busy = PARPORT_STATUS_ACK | PARPORT_STATUS_ERROR;
        int acking = PARPORT_STATUS_ERROR;
        int ready = PARPORT_STATUS_ACK | PARPORT_STATUS_ERROR;
        unsigned char value;
 
        int dir = 1;
        ioctl(ppfd, PPDATADIR, &dir);  // data port as inputs
        
        //Let ppdev know we're ready for interrupts
        ioctl(ppfd, PPWCONTROL, &ready);
 
        //Wait for an interrupt....................................................
        fd_set rfds;
        FD_ZERO(&rfds);
        FD_SET(ppfd, &rfds);

        if(select(ppfd + 1, &rfds, NULL, NULL, NULL))
        {
            printf("Received interrupt\n");
        }
        else
        {
            printf("No interrupt\n");
            continue; //Caught a signal
        }//.........................................................................
 
            //Read Data port
        ioctl(ppfd, PPRDATA, &value[i]);
        
        unsigned int int_value = value;
        printf("data =  %i\n", int_value);
        
        
        //Clear the interrupt
        ioctl(ppfd, PPCLRIRQ, &int_count);
        if(int_count > 1)
            printf("Uh oh, missed %i interrupts!\n", int_count - 1);
 
        //Acknowledge the interrupt
        //ioctl(ppfd, PPWCONTROL, &acking);
        //usleep(2);
        //ioctl(ppfd, PPWCONTROL, &busy);
    }
 
    return 0;
}
```

Fast linked list without list

If you need a very fast way to iterate over a list of objects and call the same method on all of them, then here is a posible solution. Der...