Re: Ukazka C++ pro děti

Pavel Brychta pavel.brychta na duhasys.eu
Čtvrtek Duben 1 10:15:16 CEST 2021


Jistě, alespoň jeden za všechny:

Mějme dva vývody mikrokontroléru, nazvané obecně GPIO1 a GPIO2, na které 
se připojují různé RFID čtečky rozhraní Wiegand, MG, nebo sériový port. 
Původní řešení bylo v C++, kde pro obsluhu každé čtečky byl vytvořený 
objekt, jehož konstruktor vypadal řekněme takto:

WIEGAND::WIEGAND(int pinD0, int pinD1) {

...

}

MGTrack::MGTrack(int pinDta, int pinClk) {

...

}

V aplikaci pak bylo použité:

WIEGAND rdrWie(GPIO1, GPIO2);

MGTrack rdrMg(GPIO1, GPO2);

Tady bych jen chtěl zvýraznit to, co jsem psal o konstruktorech - v obou 
objektech jsou použité stejné GPIO, takže konstruktory nesmí ty GPIO 
žádným způsobem nastavovat co se týče hardware. To se děje až v begin()...

Inicializace čteček pak probíhala ve stylu:

if (RT_WIEGAND == rdrType) {

   rdrWie.begin();

} else if (RT_MAGSTRIPE == rdrType) {

   rdrMg.begin();

}.....

A vlastní obsluha vlastního čtení pak probíhala ve stylu:

bool haveCard;

if (RT_WIEGAND == rdrType) {

   haveCard = rdrWie.haveCard();

} else if (RT_MAGSTRIPE == rdrType) {

   haveCard = rdrMg.haveCard();

} ...

Nevýhoda je jasná - objekty jsou statické, takže sežerou RAM i v 
případě, že nejsou používané a přidání dalšího typu čtečky je opruz. 
Přepsal jsem to tedy na polymorfní tím, že jsem vytvpřil třídu RdrBase, 
kterou jsem použil jako předka pro všechny čtečky. Současná varianta pak 
vypadá takto:

class rdrBase

{

public:

   virtual void begin(void);

   virtual bool haveCard(void);

...

};

...

rdrBase *reader = nullptr;

Inicializace pak vypadá takto:

if (RT_WIEGAND == rdrType) {

   reader = new WIEGAND(GPIO1, GPIO2);

} else if (RT_MAGSTRIPE == rdrType) {

   reader = new MGTrack(GPIO1, GPIO2);

}.....

if (reader) {

   reader->begin();

}

A obsluha pak vypadá takto:

bool haveCard = false;

if (reader) {

   haveCard = reader->haveCard();

}

Už v tomto jednoduchém příkladu obsazení paměti RAM výrazně kleslo a 
výhoda tohoto řešení se ukázala ještě více v okamžiku, kdy bylo třeba 
obsluhovat více čteček na jednom zařízení. Cena za to je dynamická 
alokace new, ale - protože si toho jsem vědom, tak vím, kdy ji můžu 
udělat, aby nezpůsobila fragmentaci heapu. Stejným způsobem mám řešené 
například pravidla pro dekódování karet, respektive jejich převod do 
interního formátu systému, stejným způsobem mám řešené různé formáty 
exportů/komunikace, nebo například typy výkonových prvků (relé na zámek, 
flip/flop relé, impulz pro turniket, relé přes UDP, ...).

Tohle řešení používám v různých obměnách na platformě AVR(atmega328, 
32U8), ESP8266, ESP32 a SAMD21.

Pavel Brychta

Dne 01. 04. 21 v 9:35 Jan Waclawek napsal(a):
>
>> právě polymorfní objekty v praxi
>>
>> pomohly pár věcí vyřešit hodně elegantní cestou
> Mozete prosim uviest priklady?
>
> Dakujem
>
> wek
>
>
>
> On 1 April 2021 06:38:54 CEST, Pavel Brychta <pavel.brychta na duhasys.eu> wrote:
>> Když už jsme se dostali k přetěžování operátorů, tak by bylo dobré
>> zmínit i šablony (templates), které s přetížením můžou souviset a
>> umožní
>> vytvořit konverze mezi jednotlivými datovými typy. No a odtud je pak už
>>
>> jen krůček k polymorfním objektům, které, jak jsem se zde dozvěděl, by
>> měly na 8-bitech "vadit", což považuji za blábol, protože je běžně
>> používám a paradoxně paměť RAM jejich použitím spíš šetřím (asi to
>> používám "v míře menší, než zanedbatelné", nebo to prostě to AVRko
>> neví,
>> tak mu to nevadí). V každém případě mi právě polymorfní objekty v praxi
>>
>> pomohly pár věcí vyřešit hodně elegantní cestou, takže bych je
>> neopomenul zmínit...
>>
> _______________________________________________
> HW-list mailing list  -  sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list


Další informace o konferenci Hw-list