Formatovany tisk pro 8bit

Martin Záruba swz na volny.cz
Sobota Duben 20 14:01:19 CEST 2024


Nojo, jenže pak s tím neuděláte tabulku. Je potřeba, aby například pokud 
je hodnota 3753, napsalo to |3753mV| ale pokud je 53, napsalo to |  
53mV| a ne |53mV|. Tedy aby celý řetězec (včetně toho mV) byl stále 
(například) 6 znaků.

Zkusil jste, kolik to zabere paměti? Podle toho, co píšete to dělá 
převod na float. To ale na osmibitu je hrůza. Já si hraju jen s 
"grafikou". Číslo stále dělím deseti, to je i na osmibitu snadné. A 
vypisuji zbytek po dělení. No a někam vrazím jakoukoli "výplň", třeba tu 
tečku. Pak to vypadá jako desetinné číslo, které ale je v celočíselném 
formátu uloženo třeba 10x 100x nebo jak se chce větší, což je myslím ten 
nejefektivnější způsob, jak na malinkém procesoru zobrazit desetinné číslo.

Zkoušel jsem také použít ultoa(). Ale je to větší a stejně musíte 
výsledek formátovat.

Napadlo mě ještě nejprve první smyčkou zjistit délku masky a pak 
nadefinovat pole buf pomocí malloc. A na konci ho uvolnit. Pak by 
většinou bylo malinké. Co si myslíte o tomto nápadu?

Martin Záruba

Dne 20.4.2024 v 12:29 Pavel Hudeček napsal(a):
> Ne, v mém příkladu je přeci stav uBat1=3753, tak uartSend("\1mV", 
> adUbat1, 0); vypíše 3753mV
> Pokud by adUbat bylo 53, vypíše 53mV
> a pokud by bylo zadáno uartSend("\1mV", adUbat1, 3);
> vyleze 3753,000mV
> nebo třeba 3753,001, pokud float hodnota nevyšla přesně 3753,000
>
> Nějak tak to fungovalo, už je to dlouho.
> Ale jak se tu o tom teď diskutuje a ještě jsme na kroužku došli k 
> sériáku, tak si asi konečně udělám tu knihovnu, kde tohle bude jedno z 
> přetížení.
>
> PH
>
> Dne 20.04.2024 v 11:27 Martin Záruba napsal(a):
>>
>> Jen dotaz: Co vypíše:
>>
>> uBat1 je 53
>>
>> uartSend("\1mV",adUbat1,0);
>>
>> nevypíše to
>>
>> 53mV      ?
>>
>> Martin Záruba
>> Dne 20.4.2024 v 10:36 Pavel Hudeček napsal(a):
>>> Tady asi došlo k mírnému nedorozumění:
>>> Oba umíme zobrazit jen jednu hodnotu.
>>> Oba umíme požadovaný počet des. míst.
>>> Oba umíme text před ním i po něm.
>>> Já nemám formátování tisíců, ale zas můžu ve výstupním textu použít #.
>>> Zas to formátování s # se asi dá ohackovat, že zobrazí třeba 2 čísla 
>>> zakódovaný do jednoho longu?
>>>
>>> // adUin je 12,3456  uBat1 je 3753
>>> // UART_sendDT je ','  UART_sendPosChr je '\1'
>>> uartSend("Uin=\1 V\n", adUin, 2);
>>> uartSend("\1mV", adUbat1, 0);
>>> výsledek je:
>>> Uin=12,34 V
>>> 3753mV
>>>
>>> Ten uartSend byl trochu prasáckej, mist nakopíruje do globální 
>>> uartSendMist a pak zavolá cislo((long)(v * m)), kde m je třeba 1000 
>>> pro mist=3. A cislo pak do požadovaného místa vnutí oddělovač a 
>>> uartSendMist vynuluje. Tohle jsem už někde měl i na ty tisíce, jen 
>>> se to nevypínalo samo.
>>>
>>> Chystám se že bych si z těhle věcí konečně udělal nějakou knihovnu, 
>>> zatím to jen kopíruju mezi projekty a nejčastějc si vystačím s 
>>> putchar2, text na poslání textu a cislo na poslání longu.
>>> takže posledně to bylo ve stylu
>>> text("Uin="); cislo(static_cast<long>(1000.0*adUin)); text(" mV\r\n");
>>>
>>> Buffer je na zásobníku, takže sám vznikne a sám zmizí.
>>> Ale 100 B, to je 20 % RAMky na ATtiny816, což je hodně, případně 
>>> 1,25 % na AVR64DD32, to už by bylo v pohodě.
>>> Mě se to obecně nelíbí, protože rád používám děje na pozadí. Funkce 
>>> cekej(uint32_t ms) je i víc než půlka programu a pokud možno všechno 
>>> čekání volá aspoň cekej(0). No a když se těch čekání sejde více 
>>> takových, kde mezitím vzniknul buffer..
>>> Takže mám snahu takové buffery nedělat.
>>> Další věc je, že mám snahu minimalizovat místa, kde je potřeba 
>>> omezovat velikost stringu. Takže mě stačí buffer na 10B celej vstup 
>>> může mít 254, výstup až 264 a ve verzi s txtPred + txtPo můžou 
>>> klidně oba texty mít do 254.
>>>
>>> Ovšem to s F a PSTR je pro mě novinka, za to díky.
>>>
>>> Byl jsem zvyklý na codevision, tam se daly deklarovat proměnné do 
>>> RAM, EEPROM i Flash, "text" byl ve flash a všechno fungovalo do 
>>> velké míry samo, včetně toho, že v EEPROM je pointer do flash. Super 
>>> věc, pokud se po kompilaci k binárce sprostě přikopírujou UTF8 texty 
>>> ve 4 jazycích a za ně bitmapa fontů. Při prvním spuštění program ve 
>>> flash najde "Tady>>>", pak dohledá začátky jazyků, hlášky v default 
>>> jazyku a nakonec font. Pointery hodí do EEPROM a odteď se může na 
>>> displeji 10 ms po zapnutí objevit třeba normální čeština.
>>> A v případě GCC jsem si myslel, že nic už takhle elegantně nepůjde.
>>> Vlastně opravdu nejde, protože si sice můžu nadeklarovat proměnnou v 
>>> EEPROM, ale nemůžu jí přímo používat, jen přes funkce na čtení a 
>>> zápis EEPROM, který maj navíc hrozně dlouhý názvy. "Super" do vzorce 
>>> se 3 kalibračníma konstantama.
>>> Tak aspoň snad zas můžu mít texty ve flash:-)
>>>
>>> PH
>>>
>>> Dne 19.04.2024 v 21:23 Martin Záruba napsal(a):
>>>>
>>>> Já to tak původně dělal, jenže byl to mnohem složitější a vlastně 
>>>> můžete takto udělat jen část než narazíte na první formátovací 
>>>> znak. Pak už je to stejně jen odeslání čísla. protože nevíte, zda 
>>>> nebude následovat další formátovací znak po libovolné počtu 
>>>> "výplní". Tvar text,val, míst se mi nelíbil, protože s ním 
>>>> neuděláte třeba 10mV. Takto je text kdekoli, dokonce je kdekoli i 
>>>> třeba \n, takže nemá smysl println. A varinta txtPred, val, míst, 
>>>> txtPo to sice umí, ale jsou 4 parametry a stejně nejde udělat třeba 
>>>> odskočené tisíce. Taky se mi líbí, že to sežere i float. 
>>>> Předpokládím, že buffer se vytvoří na zásobníku a po opuštění 
>>>> funkce zmizí. Je to tak?
>>>>
>>>> Ještě to chci doplnit o možnost mít formátovací řetězec ve flash. 
>>>> Není mi ale jasné, jaký je rozdíl mezi PSTR("V paměti flash") a 
>>>> F("V paměti flash"). Asi se mi víc líbí F(" "), je to kratší zápis 
>>>> a dovoluje přetížení funkce. Ale možná má nějakou nevýhodu, na 
>>>> kterou jsem nepřišel.
>>>>
>>>> Martin Záruba
>>>> Dne 19.4.2024 v 20:50 Pavel Hudeček napsal(a):
>>>>> Moc pěkný.
>>>>> Já bych teda akorát nekopíroval celý text do velkého bufferu a 
>>>>> místo toho text před číslem rovnou odesílal v prvním do/while, pak 
>>>>> převed a odeslal číslo a nakonec odeslal zbytek vstupního textu.
>>>>>
>>>>> Už jsem taky kdysi použil variantu, kdy se zadávají parametry 
>>>>> (text, val, mist) a v textu je pak znak pro umístění čísla a des. 
>>>>> míst se odešle podle hodnoty mist. Častějc mám ale (txtPred, val, 
>>>>> mist, txtPo).
>>>>>
>>>>> Odesílání mám teda téměř vždy rovnou průběžně po znacích a 
>>>>> odesílací funkce čeká jen na dokončení předchozího znaku, takže 
>>>>> konverze na výstupní text probíhá paralelně s odesíláním.
>>>>>
>>>>> PH
>>>>>
>>>>> Dne 19.04.2024 v 19:23 Martin Záruba napsal(a):
>>>>>> Už jsem se Vás dost natrápil na toto téma a měl jsem pocit, že 
>>>>>> nic moc úsporného a jednoduše použitelného není. Jenže jsem 
>>>>>> paličatý a zkusil jsem přece něco vymyslet. Požadavek byl:
>>>>>>
>>>>>> Výpis na požadovaný počet míst s možností textu před i za číslem.
>>>>>>
>>>>>> Potlačení nevýznamných nul.
>>>>>>
>>>>>> Co nejúspornější kód jak funkce, tak volání, vhodný pro malinky 
>>>>>> procesor.
>>>>>>
>>>>>> Přímý tisk bez nutnosti psaní Serial.print();
>>>>>>
>>>>>> Vyrobil jsem toto, posuďte a navrhněte prosím co by ještě šlo líp.
>>>>>>
>>>>>>
>>>>>> void pr(int32_t h, const char* f) {
>>>>>>   char buf[100];
>>>>>>   uint8_t i = 0xFF;
>>>>>>   int32_t x = abs(h);
>>>>>>   do {
>>>>>>     i++;
>>>>>>     buf[i] = f[i];
>>>>>>   } while (f[i] != 0);
>>>>>>
>>>>>>   do {
>>>>>>     i--;
>>>>>>     if (buf[i] == '#') {
>>>>>>       if (x != 0) {
>>>>>>         buf[i] = x % 10 + (uint8_t)'0';
>>>>>>         if (h < 0 && x < 10) {
>>>>>>           i--;
>>>>>>           buf[i] = '-';
>>>>>>         }
>>>>>>       } else {
>>>>>>         buf[i] = ' ';
>>>>>>       }
>>>>>>       x /= 10;
>>>>>>     }
>>>>>>   } while (i != 0);
>>>>>>   Serial.print(buf);
>>>>>> }
>>>>>>
>>>>>>
>>>>>> Funkce má jediný formátovací znak #
>>>>>>
>>>>>> Příklady:
>>>>>>
>>>>>> int32_t napetimV = 5432;
>>>>>> pr(napetimV, "Pokus1=###.###V\n");
>>>>>> pr(-21,      "Pokus2=### zaporne cislo\n");
>>>>>> pr(9876543,  "Pokus3=# ### ### cislo s mezerami po 1000\n");
>>>>>> float a = 54.3;
>>>>>> pr(a*10,     "Pokus4=####.# vypis float na 1 desetinne misto\n");
>>>>>>
>>>>>> Výsledek vypadá takto:
>>>>>>
>>>>>> Pokus1=  5.432V
>>>>>> Pokus2=-21 zaporne cislo
>>>>>> Pokus3=9 876 543 cislo s mezerami po 1000
>>>>>> Pokus4=   54.3 vypis float na 1 desetinne misto 
>>>
>>>
>>> _______________________________________________
>>> HW-list mailing list  -  sponsored bywww.HW.cz
>>> Hw-list na list.hw.cz
>>> http://list.hw.cz/mailman/listinfo/hw-list
>>
>> _______________________________________________
>> HW-list mailing list  -  sponsored bywww.HW.cz
>> Hw-list na list.hw.cz
>> http://list.hw.cz/mailman/listinfo/hw-list
>
>
> _______________________________________________
> HW-list mailing list  -  sponsored bywww.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list
------------- další část ---------------
HTML příloha byla odstraněna...
URL: <http://list.hw.cz/pipermail/hw-list/attachments/20240420/73e7d5e3/attachment.htm>


Další informace o konferenci Hw-list