Formatovany tisk pro 8bit C++

Pavel Hudeček edizon na seznam.cz
Neděle Duben 21 13:58:15 CEST 2024


A ještě jsem voliteně přidal ty taby:

putcharTabsPoss[0] = 8;
putcharTabsPoss[1] = 16;
putcharTabsPoss[2] = 24;

uartSendF(F("tt \t1 \t2 \t 3\r\n"));
uartSendF(F("ttt \t1111 \t2222 \t333333\r\n"));
uartSendF(F("ttt \t1111111 \t2222222 \t333333333\n\n\r\n"));

putcharTabsPoss[0] = 10;
putcharTabsPoss[1] = 20;
putcharTabsPoss[2] = 30;

uartSendF(F("tt \t1 \t2 \t3\r\n"));
uartSendF(F("ttt \t1111 \t2222 \t333333\r\n"));
uartSendF(F("ttt \t1111111 \t2222222 \t333333333\n\n\r\n"));

výsledek je:
tt     1       2        3
ttt    1111    2222    333333
ttt    1111111         2222222 333333333

tt       1         2         3
ttt      1111      2222      333333
ttt      1111111   2222222   333333333

a takhle vypadá putchar a související:

------------------------
#define UART_sendTabExt    3

#ifndef UART_sendTabExt    // >0 Použít tabulku zadané velikosti, s 
pozicema pro \t v putcharu
#define UART_sendTabExt    0
#endif

#if (UART_sendTabExt==0)
void putchar2(char c) { // 
===============================================================
     #if (UART_num == 1) // 0 DPS / 1 kit
     while ((USART1.STATUS & USART_DREIF_bm) == 0);
     USART1.TXDATAL=c;
     #else
     while ((USART0.STATUS & USART_DREIF_bm) == 0);
     USART0.TXDATAL=c;
     #endif
}
#else //(UART_sendTabExt==0)

#ifndef putcharTabsPoss
uint8_t putcharTabsPoss[UART_sendTabExt];
#endif

void putchar2(char c) { // ==============================
     static volatile uint8_t lastPos = 0;


     if (c=='\n' || c=='\r') lastPos=0;
     else if (c=='\t') {
         uint8_t n;
         for (n=0; n<UART_sendTabExt; n++) if 
(putcharTabsPoss[n]>lastPos) break;
         if (n<UART_sendTabExt) {
             while (lastPos < putcharTabsPoss[n]) putchar2(' ');
         }
         return;
     }

     #if (UART_num == 1) // 0 DPS / 1 kit
     while ((USART1.STATUS & USART_DREIF_bm) == 0);
     USART1.TXDATAL=c;
     if (c=='\n' || c=='\r') lastPos=0;
     #else // (UART_num == 1)
     while ((USART0.STATUS & USART_DREIF_bm) == 0);
     USART0.TXDATAL=c;
     #endif // (UART_num == 1)
     lastPos++;
}

#endif //(UART_sendTabExt==0)
----------------------

Poznámka:
Zajímavé je, že na PORTA, PORTB, ... funguje define, ale USART0, USART1, 
... přes define nefunguje, tak je tam vopičárna s UART_num.

PH

Dne 21.04.2024 v 11:24 Pavel Hudeček napsal(a):
> Tak jsem si s tím pohrál, podařilo se, ale byl to porod, protože 
> avr-g++ je asi nějaký nedodělaný.
>
> Nějakou dobu to vypadalo, že v něm správně nefunguje ani přetížení funkcí
> uartSendF(F("long  \1---\r\n"), 123456L, 2);
> uartSendF(F("float \1---\r\n"), 98765.4321, 2);
> funkce deklarována pro long a float
> u řádku s 98765.4321 error, že overload je ambignous
>
> Takže následovala laborace s templaty a detekcí typu
> //#include <type_traits>
> //#include <typeinfo>
> File not found, takže normálně to nejde jedním ani druhým způsobem.
>
> Nakonec jsem vytvořil:
> template <typename T> class clDetTyp {
> public:
>     char det();
> };
>
> template <> char clDetTyp<unsigned int>::det() {
>     return 'u';
> }
> template <> char clDetTyp<int>::det() {
>     return 'i';
> }
> template <> char clDetTyp<long>::det() {
>     return 'l';
> }
> template <> char clDetTyp<float>::det() {
>     return 'f';
> }
> template <> char clDetTyp<double>::det() {
>     return 'd';
> }
>
> a použil:
>
> template<typename T>
> void uartSendF(const char *t, T val, uint8_t mist) {
>     clDetTyp<T> d;
>     if (d.det()=='f' ...
>
> To funguje.
> Ale vedlejším produktem je zjištění, že *když napíšu 123.456 není to 
> float, ale double*:-)
> A teda ten "double" má sizeof 4 stejně jako float, což je na 8bitu 
> očekávané.
> Ale WTF proč z des. čísla dělá "double" a ne float?
>
> Takže zpátky na stromy: *Funguje i normální overload*:-)
> avr-g++ teda není až takovej krám
>
> uartSendF(F("long  \1---\r\n"), 123456L, 2);
> uartSendF(F("float \1---\r\n"), 98765.4321, 2);
> uartSendF(F("text  \1---\r\n"), "blabla");
> uartSendF(F("textF blablabla\r\n"));
> uartSend("textR blablabla\r\n");
>
> Teď normálně vyplivne:
> long  1234,56---
> float 98765,43---
> text  blabla---
> textF blablabla
> textR blablabla
>
> Jen je škoda, že ten *PSTR *(kterej jsem si předefinoval na F) *se 
> nedá rozpoznat*, takže mám uartSend na texty v RAM a uartSendF na flash.
> ------------------------ #include <avr/pgmspace.h> #define UART_sendDT 
> ',' #define UART_sendPosChr 1 #define F PSTR // Poslat číslo na 
> sériák, na konci oddělit mist desetinným oddělovačem void cisloDT(long 
> x, uint8_t mist) { // 
> ================================================= char t[10]; uint8_t 
> n; if (x==0) {putchar2('0'); return;} for (n=0; n<10 && x>0; n++) { 
> t[n]=x % 10 + '0'; x/=10; } //uint8_t dp = n-1-mist; for (n-=1; n<255; 
> n--) { if (mist>0 && n==mist-1) putchar2(UART_sendDT); putchar2(t[n]); 
> } } // Poslat char* na sériák void uartSend(char *c) { // 
> ========================================= for (signed char n=0; 
> c[n]!=0; n++) putchar2(c[n]); } // Poslat PSTR na sériák void 
> uartSendF(const char *t) { // ---------------------------------- char 
> c; for (signed char n=0; (c=pgm_read_byte(&t[n]))!=0; n++) 
> putchar2(c); } // Poslat na sériák PSTR s vloženým char* void 
> uartSendF(const char *tFlash, char *tRam) { // ----------------- char 
> c; for (char n=0; n<255; n++) { c = pgm_read_byte(&tFlash[n]); if 
> (c==0) break; else if (c==UART_sendPosChr) uartSend(tRam); else 
> putchar2(c); } } // Poslat na sériák PSTR s vloženým cisloDT void 
> uartSendF_(const char *t, long val, uint8_t mist) { // --------- char 
> c; for (char n=0; n<255; n++) { c = pgm_read_byte(&t[n]); if (c==0) 
> break; else if (c==UART_sendPosChr) cisloDT(val, mist); else 
> putchar2(c); } } // post-test overload - taky funguje void 
> uartSendFt(const char *t, float val, uint8_t mist) { float m = 1.0; 
> for (uint8_t n=0; n<mist; n++) m*=10.0; uartSendF_(t, 
> static_cast<long>(val*m), mist); } void uartSendFt(const char *t, 
> double val, uint8_t mist) { float m = 1.0; for (uint8_t n=0; n<mist; 
> n++) m*=10.0; uartSendF_(t, static_cast<long>(val*m), mist); } void 
> uartSendFt(const char *t, long val, uint8_t mist) { uartSendF_(t, val, 
> mist); } template <typename T> class clDetTyp { // 
> =========================== public: char det(); }; template <> char 
> clDetTyp<unsigned int>::det() { return 'u'; } template <> char 
> clDetTyp<int>::det() { return 'i'; } template <> char 
> clDetTyp<long>::det() { return 'l'; } template <> char 
> clDetTyp<float>::det() { return 'f'; } template <> char 
> clDetTyp<double>::det() { return 'd'; } template<typename T> void 
> uartSendF(const char *t, T val, uint8_t mist) { // ============== 
> clDetTyp<T> d; if (d.det()=='f' || d.det()=='d') { float m = 1.0; for 
> (uint8_t n=0; n<mist; n++) m*=10.0; uartSendF_(t, 
> static_cast<long>(val*m), mist); } else if (d.det()=='l') 
> uartSendF_(t, val, mist); else uartSendF_(t, static_cast<long>(val), 
> mist); } ---------------------------------- cisloDT přejmenuju taky na 
> uartSend. uartSendF_přejmenuju na uartSendF.
> Mám radši nechat ten template s detekcí typů, nebo udělat jen 
> overloady? PH
------------- další část ---------------
HTML příloha byla odstraněna...
URL: <http://list.hw.cz/pipermail/hw-list/attachments/20240421/2e8b3d9a/attachment.htm>


Další informace o konferenci Hw-list