#########################################################################################################

                                Softwareimplementierter UART fuer PFS154
                                mit timergetriebenem 4-fach Oversampling

#########################################################################################################

softwareuart.h / .c ist eine C-Sourcedatei, die eine serielle Uebertragung von und zu einem PFS154
Microcontroller ermoeglicht.

Im Gegensatz zu einer Realisierung, die die Bitzeiten ueber Zaehlschleifen realisiert und von daher
haeufig instabil ist, werden die Bitzeiten in softwareuart ueber den interrupt getriebenen Timer 2
realisiert.

Ein 4-fach Oversampling ermoeglicht softwareuart ein autarkes Erkennen eines Startbits und das
Einlesen in einen Ringspeicher.

Hierdurch reduziert sich leider die moeglichen Baudraten auf 1200, 2400 und 4800 Baud. Diese sind dafuer
stabil zu erreichen, eine Uebertragung bleibt auch nach dem "Eiswuerfel-Foen-Test" stabil. Hierbei
wurde der Controller Minusgraden und erhoehte Temperaturen waehrend der Uebertragung ausgesetzt.

softwareuart benoetigt zusaetzliche Sourcen

- den Inhalt des Ordners include aus
      https://github.com/free-pdk/free-pdk-examples/tree/master

- pfs1xx_gpio3.h   fuer vereinfachte Zugriffe auf GPIO-Pins
- pdk_init.h       beinhaltet das __sdcc_external_startup
- delay.h          fuer das Demo

Alle benoetigten Dateien sowie eine Demonstrationssource sowie ein Make Buildprozess sind im Archiv
enthalten.

Grundsaetzliches:
---------------------------------------------------------------------------------------------------------

softwareuart benoetigt fuer sein Bittiming Timer 2 im Interruptbetrieb. Da es auf einem PFS154 nur einen
Interrupthandler fuer alle Interruptquellen (single-vector ISR) gibt, wurde der Interrupthandler NICHT
in softwareuart.c sondern nur die Funktion

                                 void uart_sample(void)

definiert.

Im Interrupthandler muss also ueber Dispatching die uart_sample Funktion aufgerufen werden, damit der
UART betrieben werden kann:

                void interrupt(void) __interrupt(0)
                {
                  // Timer2 Interrupt
                  if (INTRQ & INTRQ_TM2)
                  {
                    uart_sample();

                    INTRQ &= ~INTRQ_TM2;     // Interruptanforderung quittieren ....
                                             // wird im Normalfall bereits innerhalb
                                             // von uart_sample quittiert
                  }

                  // hier koennen andere Interruptquellen eingehaengt werden

                }

Eingehende Zeichen auf dem UART werden in einem Ringpuffer gespeichert.



#########################################################################################################

   softwareuart.h

#########################################################################################################

In softwareuart.h sind angaben zu machen, welche Baudrate und welche Pins fuer den UART verwendet
werden sollen:

                // --------------------------------------------------------
                //                 Receiverpin Anschluss
                // --------------------------------------------------------
                #define rxpin_init()     PB7_input_init()
                #define is_rxpin()       is_PB7()

                // --------------------------------------------------------
                //             Transmitterpin Anschluss
                // --------------------------------------------------------
                #define txpin_init()     PA7_output_init()
                #define txpin_set()      PA7_set()
                #define txpin_clr()      PA7_clr()

                // --------------------------------------------------------
                //                    Baudrate
                // --------------------------------------------------------
                #define baudrate     4800

Diese Einstellungen koennen vom Benutzer seinen Gegebenheiten angepasst werden.

softwareuart verfuegt ueber einen, wenn auch sehr kleinen, Eingangsringpuffer, in dem eingehende
Zeichen gespeichert werden und aus denen mittels uart_getchar eingegangene Zeichen gelesen
werden. Defaultmaessig werden nur 4 Bytes gespeichert, da der RAM des PFS154 sehr begrenzt ist
(nur 128 Byte). Je nach Anwendung und noch verfuegbarem Ram, kann dieser Buffer vergroessert
werden:

                // --------------------------------------------------------
                //                Ringbuffer fuer den UART
                // --------------------------------------------------------
                #define UART_BUF_SIZE 4        // mit Bedacht waehlen: PFS154 hat nur 128 Byte RAM !!!



#########################################################################################################

   Funktionen von softwareuart

#########################################################################################################

-------------------------------------------------------------
  void uart_init(void)
-------------------------------------------------------------

Initialisiert den UART mit den in softwareuart.h gemachten Einstellungen fuer die beteiligten RxD / TxD
Pins, sowie der Baudrate. Timer 2 wird im Interruptbetrieb zur Verwendung initialisiert und gestartet.

Funktionsargument:
   keines

-------------------------------------------------------------
  void uart_putchar(uint8_t ch)
-------------------------------------------------------------

sendet ein Zeichen auf dem UART

Funktionsargument:
   ch : zu sendendes Zeichen

-------------------------------------------------------------
  void uart_puts(char *p)
-------------------------------------------------------------

sendet einen Ascii-Zero String auf dem UART

Funktionsargument:
   *p : Zeiger auf den auszugebenden String

-------------------------------------------------------------
  uint8_t uart_getchar(void)
-------------------------------------------------------------

wartet auf den Eingang eines Zeichens und gibt dieses als
Funktionsergebnis zurueck

Funktionsargument:
   keines

-------------------------------------------------------------
  uint8_t uart_ischar(void)
-------------------------------------------------------------

stellt fest, ob ein eingeganges Zeichen im Receive-Buffer
vorhanden ist, liest dieses aber nicht ein.

Funktionsergebnis:
   - 1 : ein Zeichen ist verfuegbar
     0 : kein Zeichen verfuegbar

#########################################################################################################

   Anhang

#########################################################################################################

Verzeichnisbaum fuer die relevanten Dateien (im include-Verzeichnis befinden sich zudem Dateien, die
der Compiler zusätzlich fuer den Buildprozess benoetigt, diese sind hier nicht aufgefuehrt)

    ./pfs154_softwareuart/
    |-- Makefile
    |
    |-- include
    |   |-- delay.h
    |   |-- pdk_init.h
    |   |-- pfs1xx_gpio3.h
    |   `-- softwareuart.h
    |
    |-- src
    |   |-- delay.c
    |   `-- softwareuart.c
    |
    |-- makefile.mk
    |-- softwareuart.txt
    |
    `-- uartint_demo.c

Um die Funktionen von softwareuart zu demonstrieren, kann das Programm uartint_demo.c mit

                                       make

kompiliert werden. Hierfuer wird ein systemweit installierter SDCC ab Version 4.0.1 vorrausgesetzt.
Ist ein Easy PDK basierender Programmer wie in

                           https://free-pdk.github.io/
                           
vorgestellt, vorhanden, so kann mit

                                    make flash
 
ein Programmieren des Controllers erfolgen.                           

Dieser Buildprozess funktioniert nur unter Linux.

---------------------------------------------------------------------------------------------------------
11.06.2026   R. Seelig
