From a20e3d98368bb98d9d481c3c72befcb72c666a83 Mon Sep 17 00:00:00 2001
From: jimmy <git@jimmy.nz>
Date: Sat, 20 Apr 2024 09:37:55 +1200
Subject: [PATCH] Add ATtiny2313. Implement printf

---
 src/usart.cpp | 92 ++++++++++++++++++++++++++++++++++++++++++---------
 src/usart.h   |  1 +
 2 files changed, 78 insertions(+), 15 deletions(-)

diff --git a/src/usart.cpp b/src/usart.cpp
index 4758601..5b230c3 100644
--- a/src/usart.cpp
+++ b/src/usart.cpp
@@ -3,14 +3,8 @@
 #include "usart.h"
 
 namespace usart
-{
-    namespace {
-        static FILE mystdout;
-    }
-    
+{   
     void init( unsigned long baud) {
-        fdev_setup_stream(&mystdout, put_printf, NULL, _FDEV_SETUP_WRITE);
-        stdout = &mystdout;
         const unsigned int ubrr =  F_CPU/8/baud-1;
 
         /*Set baud rate */
@@ -34,6 +28,15 @@ namespace usart
             //UCSRB |= (1<< RXCIE)|(1<<TXCIE);
             /* Set frame format: 8data, 2stop bit */
             UCSRC = (1 << URSEL)|(3<<UCSZ0);
+        #elif defined __AVR_ATtiny2313__
+            UBRRH = (unsigned char)(ubrr>>8);
+            UBRRL = (unsigned char)ubrr;
+            UCSRA |= (1<<U2X);
+            //Enable receiver and transmitter 
+            UCSRB = (1<<RXEN)|(1<<TXEN);
+            //UCSRB |= (1<< RXCIE)|(1<<TXCIE);
+            /* Set frame format: 8data, 2stop bit */
+            UCSRC = (1<<USBS)|(3<<UCSZ0);
         #endif
     
     }
@@ -43,23 +46,82 @@ namespace usart
             while ( !( UCSR0A & (1<<UDRE0)) ); UDR0 = data;
         #elif defined  __AVR_ATmega32__ || defined __AVR_ATmega16__
             while ( !( UCSRA & (1<<UDRE)) ); UDR = data;
-        #endif
-        
-       
+        #elif defined __AVR_ATtiny2313__
+            while ( !( UCSRA & (1<<UDRE)) ); UDR = data;
+        #endif   
     }
 
     char get( void ) {
         #if defined __AVR_ATmega328P__
             while ( !(UCSR0A & (1<<RXC0)) ); return UDR0;
-        #elif defined  __AVR_ATmega32__ || defined __AVR_ATmega16__
+        #elif defined  __AVR_ATmega32__ || defined __AVR_ATmega16__ || defined __AVR_ATtiny2313__
             while ( !(UCSRA & (1<<RXC)) ); return UDR;
         #endif
     }       
-   
-    int put_printf(char var, FILE *stream) {
-        put(var);
-        return 0;
+
+    void itoa(int n, char s[], int base) {
+        int i = 0;
+        int sign = n;
+
+        if (sign < 0) {
+            n = -n;
+        }
+
+        do {
+            s[i++] = n % base + '0';
+        } while ((n /= base) > 0);
+
+        if (sign < 0) {
+            s[i++] = '-';
+        }
+
+        s[i] = '\0';
+
+        // Reverse the string
+        for (int j = 0, k = i - 1; j < k; j++, k--) {
+            char temp = s[j];
+            s[j] = s[k];
+            s[k] = temp;
+        }
     }
+
+    void printf(const char *fmt, ...) {
+        va_list args;
+        va_start(args, fmt);
+
+        for (const char *p = fmt; *p != '\0'; p++) {
+            if (*p == '%') {
+                switch (*(++p)) {
+                    case 's': {
+                        const char *s = va_arg(args, const char *);
+                        for (; *s; s++) put(*s);
+                        break;
+                    }
+                    case 'd':
+                    case 'i': {
+                        char buf[10];
+                        itoa(va_arg(args, int), buf, 10);
+                        for (char *s = buf; *s; s++) put(*s);
+                        break;
+                    }
+                    case 'c':
+                        put(va_arg(args, int));
+                        break;
+                    case 'x': {
+                        char buf[10];
+                        itoa(va_arg(args, int), buf, 16);
+                        for (char *s = buf; *s; s++) put(*s);
+                        break;
+                    }
+                }
+            } else {
+                put(*p);
+            }
+        }
+        va_end(args);
+    }
+
+    
 } // namespace usart
 
 
diff --git a/src/usart.h b/src/usart.h
index ffad848..ba5ba00 100644
--- a/src/usart.h
+++ b/src/usart.h
@@ -8,6 +8,7 @@ namespace usart
     void put(char data );
     char get();
     int put_printf(char var, FILE *stream);
+    void printf(const char *var, ...);
 } // namespace usart