Re: EEPROM, C++ a řetěžování operátorů

Miroslav Mraz mrazik na volny.cz
Úterý Květen 30 09:40:37 CEST 2023


C++ je hodně tvárné. Ono je to vlastně ještě jednodušší, celkem není 
potřeba přetěžovat všechny potřebné operátory, stačí vytvořit operátor, 
který vrací nějaký "rozumný" typ. Tedy pokud máte v EEPROM jen nějaké 
konstanty, se kterými pak dále počítáte. Ano, adresace EEPROM je 
problém, ale asi by šel nějak vyřešit např. pomocí linker skriptu.

#include <string.h>
#include <stdio.h>

unsigned char EEPROM [256];

static bool EEReadBytes (const size_t StartAddr, void * pval, const 
size_t len) {
   printf("Read from %zd, len=%zd\n", StartAddr, len);
   memcpy(pval, EEPROM + StartAddr, len);
   return true;
}
static bool EEWriteBytes (const size_t StartAddr, const void * pval, 
const size_t len) {
   memcpy(EEPROM + StartAddr, pval, len);
   return true;
}
static void setEEPROMdata () {
   const unsigned a = 0x12345678;
   EEWriteBytes(0, &a,  sizeof(unsigned));
   const float pi = 3.14159f;
   EEWriteBytes(4, &pi, sizeof(float));
}
/*******************************************************************/
template<typename T> class EESEG {
   T data;
   public:
     explicit EESEG (const size_t StartAddr) noexcept {
       EEReadBytes (StartAddr, & data, sizeof(T));
     }
     operator const T () const {
       return data;
     }
};

int main () {
   setEEPROMdata();
   EESEG<unsigned> x(0);
   EESEG<float>    r(4);
   const float d = 2 * r;                        // počítat s tím jde - 
operator const T dosadí překladač automaticky, pokud nemá jinou možnost
   printf("x=%X\n", static_cast<unsigned> (x));  // tady už to není 
jednoznačné, nutno explicitně přetypovat
   printf("d=%g\n", d);
   return 0;
}

Mrazík

On 30. 05. 23 1:15, Pavel Hudeček wrote:
> U Arduina to vyřešili tak, že mají prostě EEPROM.read a EEPROM.write pro 
> jednobajtové operace a pak put a get pro data různých typů. Dá se říct, 
> že je to totéž jako ta sada funkcí z normálního eeprom.h, jenže teda až 
> na to, že tam se aspoň adresy vyřeší v rámci deklarací, arduinisti si 
> musí "alokovat" ručně.
> 
> Nakonec jsem zjistil, že dosažení mého cíle je mnohem jednodušší než 
> jsem si myslel, protože nejspíš stačí vytvořit kostruktory, operátory na 
> implicitní konverzi a operátory přiřazení, když se má hodnota měnit. 
> Ostatní už pak proběhne samo. Teda kromě ++, -- a zkratek jako +=. Ale 
> dejme tomu, že to bez nich přežiju:-)
> 
> Kostruktor je ale trochu složitější, musí si alokovat místo, protože 
> uvnitř třídy nejde deklarovat proměnná typu s eemem. Ještě by teda bylo 
> super, kdyby ten konstruktor nešlo vyvolat jinou než globální deklarací, 
> ale to nevím zda nějak jde.
> 
> Oproti původní variantě z eeprom.h to teda bude mít i nevýhody:
> 1. Navíc sežraná RAM, kam konstruktory uloží adresy
> 2. Přeplnění EEPROM se nepozná při kompilaci, musí vyvolat nějakej 
> runtime errorhandler.
> 
> Mám objednáno AVR64DD32 CNANO, pak si  stím trochu víc pohraju.
> 
> Co se cout vs prinft týče, tak nejvíc by se mi líbilo něco jako je print 
> v klasickým Basicu, kdy tam napíšu seznam parametrů libovolných typů 
> oddělených čárkama. Vlastně by se toho dalo dosáhnout přetížením 
> operátoru čárka místo <<, jen to bude nestandardně vypadat:-)
> 
> printf je v podstatě taky OK, ale vlastní implementace je dost pracná a 
> donutit standardní printf k použití mých nastavení sériáku je na můj 
> vkus moc složitý, nedej Bože kdybych chtěl vlastní implementaci 
> odesílání, třeba za použití přerušení. Což chci celkem často:-)
> 
> PH


Další informace o konferenci Hw-list