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