diff --git a/20211115/Makefile b/20211115/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..7ae33df99f68fcf460324cfbb008f3f7a3863638
--- /dev/null
+++ b/20211115/Makefile
@@ -0,0 +1,8 @@
+%.elf: %.c
+	avr-gcc -Wall -Os -mmcu=atmega328p $< -o $@
+
+%.hex: %.elf
+	avr-objcopy -O ihex $< $@
+
+download:
+	./download.sh
diff --git a/20211115/aufgabe-2.c b/20211115/aufgabe-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..1afa7b1260506cb307aff5f929c6357c7bdcb708
--- /dev/null
+++ b/20211115/aufgabe-2.c
@@ -0,0 +1,15 @@
+#include <avr/io.h>
+
+int main (void)
+{
+  DDRA = 0xff;
+  DDRB = 0xff;
+  DDRC = 0xff;
+  DDRD = 0xff;
+  PORTA = 0x1f;
+  PORTB = 0x10;
+  PORTD = 0x10;
+  PORTC = 0xfc;
+  while (1);
+  return 0;
+}
diff --git a/20211115/aufgabe-3.c b/20211115/aufgabe-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..9ae72941b931c04f3c380cb3bbcd64bec7f08c20
--- /dev/null
+++ b/20211115/aufgabe-3.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include <string.h>
+
+void insert_into_string (char src, char *target, int pos)
+{
+  int len = strlen (target);
+  for (int i = pos; i < len; i++)
+    target[i+1] = target[i];
+  target[pos] = src;
+}
+
+int main (void)
+{
+  char test[100] = "Hochshule Bochum";
+  insert_into_string ('c', test, 5);
+  printf ("%s\n", test);
+  return 0;
+}
diff --git a/20211115/blink-0.c b/20211115/blink-0.c
new file mode 100644
index 0000000000000000000000000000000000000000..b0022c681fd1482ed0a6d9fded7bb0a54699de32
--- /dev/null
+++ b/20211115/blink-0.c
@@ -0,0 +1,9 @@
+#include <avr/io.h>
+
+int main (void)
+{
+  DDRD = 0x40;   /* binär: 0100 0000 */
+  PORTD = 0x40;  /* binär: 0100 0000 */
+  while (1);
+  return 0;
+}
diff --git a/20211115/blink-1.c b/20211115/blink-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..6d28dce84f94375094c98479c30a54ace1b2a9d9
--- /dev/null
+++ b/20211115/blink-1.c
@@ -0,0 +1,18 @@
+#include <avr/io.h>
+
+#define F_CPU 16000000l
+#include <util/delay.h>
+
+int main (void)
+{
+  DDRD = 0x01;
+  PORTD |= 0x01;
+  while (1)
+    {
+      _delay_ms (500);
+      PORTD &= ~0x01;
+      _delay_ms (500);
+      PORTD |= 0x01;
+    }
+  return 0;
+}
diff --git a/20211115/blink-2.c b/20211115/blink-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..b00eaf522563b1e8fa75f80e784de5b9f1af58e9
--- /dev/null
+++ b/20211115/blink-2.c
@@ -0,0 +1,16 @@
+#include <avr/io.h>
+
+#define F_CPU 16000000l
+#include <util/delay.h>
+
+int main (void)
+{
+  DDRD = 0x02;
+  PORTD = 0x02;
+  while (1)
+    {
+      _delay_ms (250);
+      PORTD ^= 0x02;
+    }
+  return 0;
+}
diff --git a/20211115/blink-3.c b/20211115/blink-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..5268e7977f0f2a99b2005a81a2fa7560dfea481f
--- /dev/null
+++ b/20211115/blink-3.c
@@ -0,0 +1,17 @@
+#include <avr/io.h>
+
+#define F_CPU 16000000
+#include <util/delay.h>
+
+int main (void)
+{
+  DDRD = 0x01;
+  PORTD = 0x01;
+  while (1)
+    {
+      while ((PIND & 0x02) == 0)
+        ; /* just wait */
+      PORTD ^= 0x01;
+    }
+  return 0;
+}
diff --git a/20211115/blink-4.c b/20211115/blink-4.c
new file mode 100644
index 0000000000000000000000000000000000000000..7344aa7ce19086d6e0a0dc4f8de78499f280931b
--- /dev/null
+++ b/20211115/blink-4.c
@@ -0,0 +1,18 @@
+#include <avr/io.h>
+
+#define F_CPU 16000000
+#include <util/delay.h>
+
+int main (void)
+{
+  DDRD = 0x01;
+  PORTD = 0x01;
+  while (1)
+    {
+      while ((PIND & 0x02) == 0)
+        ; /* just wait */
+      PORTD ^= 0x01;
+      _delay_ms (200);
+    }
+  return 0;
+}
diff --git a/20211115/download.sh b/20211115/download.sh
new file mode 100755
index 0000000000000000000000000000000000000000..770c3b5dca74ac09778be055c9d6f5adb0df293b
--- /dev/null
+++ b/20211115/download.sh
@@ -0,0 +1,3 @@
+port=$(ls -rt /dev/ttyACM* | tail -1)
+echo avrdude -P $port -c arduino -p m328p -U flash:w:$(ls -rt *.hex | tail -1)
+avrdude -P $port -c arduino -p m328p -U flash:w:$(ls -rt *.hex | tail -1) 2>/dev/null
diff --git a/20211115/hp-20211115.pdf b/20211115/hp-20211115.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..d8829973c09d12dd155894ae248cd1938f9c2685
Binary files /dev/null and b/20211115/hp-20211115.pdf differ
diff --git a/20211115/hp-20211115.tex b/20211115/hp-20211115.tex
new file mode 100644
index 0000000000000000000000000000000000000000..5494681e9d2eb0569d24e5f7971e90f2bef9034c
--- /dev/null
+++ b/20211115/hp-20211115.tex
@@ -0,0 +1,1122 @@
+% hp-20211115.pdf - Lecture Slides on Low-Level Programming
+% Copyright (C) 2012, 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021  Peter Gerwinski
+%
+% This document is free software: you can redistribute it and/or
+% modify it either under the terms of the Creative Commons
+% Attribution-ShareAlike 3.0 License, or under the terms of the
+% GNU General Public License as published by the Free Software
+% Foundation, either version 3 of the License, or (at your option)
+% any later version.
+%
+% This document is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this document.  If not, see <http://www.gnu.org/licenses/>.
+%
+% You should have received a copy of the Creative Commons
+% Attribution-ShareAlike 3.0 Unported License along with this
+% document.  If not, see <http://creativecommons.org/licenses/>.
+
+% README: I/O-Ports, Interrupts
+
+\documentclass[10pt,t]{beamer}
+
+\usepackage{pgslides}
+\usepackage{pdftricks}
+\usepackage{tikz}
+
+\begin{psinputs}
+  \usepackage[utf8]{inputenc}
+  \usepackage[german]{babel}
+  \usepackage[T1]{fontenc}
+  \usepackage{helvet}
+  \renewcommand*\familydefault{\sfdefault}
+  \usepackage{pstricks,pst-grad}
+\end{psinputs}
+
+\title{Hardwarenahe Programmierung}
+\author{Prof.\ Dr.\ rer.\ nat.\ Peter Gerwinski}
+\date{15.\ November 2021}
+
+\begin{document}
+
+\maketitleframe
+
+\nosectionnonumber{\inserttitle}
+
+\begin{frame}
+
+  \shownosectionnonumber
+
+  \begin{itemize}
+    \item[\textbf{1}] \textbf{Einführung}
+      \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}}
+    \item[\textbf{2}] \textbf{Einführung in C}
+      \begin{itemize}
+        \vspace*{-\smallskipamount}
+        \item[\dots]
+        \item[2.12] Strukturen
+        \item[2.13] Dateien und Fehlerbehandlung
+        \color{medgreen}
+        \item[2.14] Parameter des Hauptprogramms
+        \item[2.15] String-Operationen
+      \end{itemize}
+    \item[\textbf{3}] \textbf{Bibliotheken}
+    \item[\textbf{4}] \textbf{Hardwarenahe Programmierung}
+      \begin{itemize}
+        \color{medgreen}
+        \item[4.1] Bit-Operationen
+        \color{orange}
+        \item[4.2] I/O-Ports
+        \color{red}
+        \item[4.3] Interrupts
+        \vspace*{-0.1cm}
+        \item[\dots]
+      \end{itemize}
+    \item[\textbf{5}] \textbf{Algorithmen}
+    \vspace*{-\smallskipamount}
+    \item[\textbf{\dots}]
+  \end{itemize}
+
+\end{frame}
+
+\setcounter{section}{1}
+\section{Einführung in C}
+\setcounter{subsection}{13}
+\subsection{Parameter des Hauptprogramms}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  \vspace*{-\bigskipamount}
+
+  \begin{lstlisting}
+    #include <stdio.h>
+
+    int main (int argc, char **argv)
+    {
+      printf ("argc = %d\n", argc);
+      for (int i = 0; i < argc; i++)
+        printf ("argv[%d] = \"%s\"\n", i, argv[i]);
+      return 0;
+    }
+  \end{lstlisting}
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  \vspace*{-\bigskipamount}
+
+  \begin{lstlisting}
+    #include <stdio.h>
+
+    int main (int argc, char **argv)
+    {
+      printf ("argc = %d\n", argc);
+      for (int i = 0; *argv; i++, argv++)
+        printf ("argv[%d] = \"%s\"\n", i, *argv);
+      return 0;
+    }
+  \end{lstlisting}
+
+\end{frame}
+
+\subsection{String-Operationen}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  \vspace*{-\bigskipamount}
+
+  \begin{lstlisting}
+    #include <stdio.h>
+    #include <string.h>
+
+    int main (void)
+    {
+      char hello[] = "Hello, world!\n";
+
+      printf ("%s\n", hello);
+      printf ("%zd\n", strlen (hello));
+
+      printf ("%s\n", hello + 7);
+      printf ("%zd\n", strlen (hello + 7));
+
+      hello[5] = 0;
+      printf ("%s\n", hello);
+      printf ("%zd\n", strlen (hello));
+
+      return 0;
+    }
+  \end{lstlisting}
+  \vspace*{-1cm}
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  \vspace*{-\bigskipamount}
+
+  \begin{lstlisting}
+    #include <stdio.h>
+    #include <string.h>
+
+    int main (void)
+    {
+      char *anton = "Anton";
+      char *zacharias = "Zacharias";
+
+      printf ("%d\n", strcmp (anton, zacharias));
+      printf ("%d\n", strcmp (zacharias, anton));
+      printf ("%d\n", strcmp (anton, anton));
+
+      char buffer[100] = "Huber ";
+      strcat (buffer, anton);
+      printf ("%s\n", buffer);
+
+      return 0;
+    }
+  \end{lstlisting}
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  \vspace*{-\bigskipamount}
+
+  \begin{lstlisting}
+    #include <stdio.h>
+    #include <string.h>
+
+    int main (void)
+    {
+      char buffer[100] = "";
+      sprintf (buffer, "Die Antwort lautet: %d", 42);
+      printf ("%s\n", buffer);
+
+      char *answer = strstr (buffer, "Antwort");
+      printf ("%s\n", answer);
+      printf ("found at: %zd\n", answer - buffer);
+
+      return 0;
+    }
+  \end{lstlisting}
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  \vspace*{-\bigskipamount}
+
+  \begin{lstlisting}
+    #include <stdio.h>
+    #include <string.h>
+
+    int main (void)
+    {
+      char buffer[100] = "";
+      snprintf (buffer, 100, "Die Antwort lautet: %d", 42);
+      printf ("%s\n", buffer);
+
+      char *answer = strstr (buffer, "Antwort");
+      printf ("%s\n", answer);
+      printf ("found at: %zd\n", answer - buffer);
+
+      return 0;
+    }
+  \end{lstlisting}
+
+\end{frame}
+
+\begin{frame}
+
+  \showsection
+
+  Sprachelemente weitgehend komplett
+
+  \bigskip
+  Es fehlen:
+  \begin{itemize}
+    \item
+      Ergänzungen (z.\,B.\ ternärer Operator, \lstinline{union}, \lstinline{unsigned}, \lstinline{volatile})
+    \item
+      Bibliotheksfunktionen (z.\,B.\ \lstinline{malloc()})
+    \arrowitem
+      werden eingeführt, wenn wir sie brauchen
+    \bigskip
+    \item
+      Konzepte (z.\,B.\ rekursive Datenstrukturen, Klassen selbst bauen)
+    \arrowitem
+      werden eingeführt, wenn wir sie brauchen, oder:
+    \arrowitem
+      Literatur\\[\smallskipamount]
+      (z.\,B.\ Wikibooks: C-Programmierung,\\
+      Dokumentation zu Compiler und Bibliotheken)
+    \bigskip
+    \item
+      Praxiserfahrung
+    \arrowitem
+      Übung und Praktikum: nur Einstieg
+    \arrowitem
+      selbständig arbeiten
+  \end{itemize}
+\end{frame}
+
+\nosectionnonumber{\inserttitle}
+
+\begin{frame}
+
+  \shownosectionnonumber
+
+  \begin{itemize}
+    \item[\textbf{1}] \textbf{Einführung}
+      \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp.git}}}
+    \item[\textbf{2}] \textbf{Einführung in C}
+    \item[\textbf{3}] \textbf{Bibliotheken}
+    \item[\textbf{4}] \textbf{Hardwarenahe Programmierung}
+      \begin{itemize}
+        \color{medgreen}
+        \item[4.1] Bit-Operationen
+        \color{orange}
+        \item[4.2] I/O-Ports
+        \color{red}
+        \item[4.3] Interrupts
+        \item[4.4] volatile-Variable
+        \item[4.6] Byte-Reihenfolge -- Endianness
+        \item[4.7] Binärdarstellung negativer Zahlen
+        \item[4.8] Speicherausrichtung -- Alignment
+      \end{itemize}
+    \item[\textbf{5}] \textbf{Algorithmen}
+    \item[\textbf{\dots}]
+%    \item[\textbf{4}] \textbf{Hardwarenahe Programmierung}
+%    \item[\textbf{5}] \textbf{Algorithmen}
+%    \item[\textbf{6}] \textbf{Ergänzungen und Ausblicke}
+  \end{itemize}
+  \vspace*{-1cm}
+
+\end{frame}
+
+\setcounter{section}{4}
+\section{Hardwarenahe Programmierung}
+\subsection{Bit-Operationen}
+\subsubsection{Zahlensysteme}
+
+\begin{frame}[fragile]
+
+  \showsection
+  \vspace*{-\smallskipamount}
+  \showsubsection
+  \vspace*{-\medskipamount}
+  \showsubsubsection
+
+  \begin{tabular}{rlrl}
+    Basis & Name & Beispiel & Anwendung \\[\smallskipamount]
+      2 & Binärsystem & 1\,0000\,0011 & Bit-Operationen \\
+      8 & Oktalsystem & \lstinline,0403, & Dateizugriffsrechte (Unix) \\
+     10 & Dezimalsystem & \lstinline,259, & Alltag \\
+     16 & Hexadezimalsystem & \lstinline,0x103, & Bit-Operationen \\
+    256 & (keiner gebräuchlich) & 0.0.1.3 & IP-Adressen (IPv4)
+  \end{tabular}
+
+  \bigskip
+
+  \begin{itemize}
+    \item
+      Computer rechnen im Binärsystem.
+    \item
+      Für viele Anwendungen (z.\,B.\ I/O-Ports, Grafik, \dots) ist es notwendig,\\
+      Bits in Zahlen einzeln ansprechen zu können.
+  \end{itemize}
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsubsubsection
+
+  \begin{tabular}{rlrlrc}
+    \qquad 000 & \bf 0 \hspace*{1.5cm} & 0000 & \bf 0 & \quad 1000 & \bf 8\\
+           001 & \bf 1                 & 0001 & \bf 1 &       1001 & \bf 9\\
+           010 & \bf 2                 & 0010 & \bf 2 &       1010 & \bf A\\
+           011 & \bf 3                 & 0011 & \bf 3 &       1011 & \bf B\\[\smallskipamount]
+           100 & \bf 4                 & 0100 & \bf 4 &       1100 & \bf C\\
+           101 & \bf 5                 & 0101 & \bf 5 &       1101 & \bf D\\
+           110 & \bf 6                 & 0110 & \bf 6 &       1110 & \bf E\\
+           111 & \bf 7                 & 0111 & \bf 7 &       1111 & \bf F\\
+  \end{tabular}
+
+  \medskip
+
+  \begin{itemize}
+    \item
+      Oktal- und Hexadezimalzahlen lassen sich ziffernweise\\
+      in Binär-Zahlen umrechnen.
+    \item
+      Hexadezimalzahlen sind eine Kurzschreibweise für Binärzahlen,\\
+      gruppiert zu jeweils 4 Bits.
+    \item
+      Oktalzahlen sind eine Kurzschreibweise für Binärzahlen,\\
+      gruppiert zu jeweils 3 Bits.
+    \item
+      Trotz Taschenrechner u.\,ä.\ lohnt es sich,\\
+      die o.\,a.\ Umrechnungstabelle \textbf{auswendig} zu kennen.
+  \end{itemize}
+
+\end{frame}
+
+\subsubsection{Bit-Operationen in C}
+
+\begin{frame}[fragile]
+
+  \showsubsubsection
+
+  \begin{tabular}{lll}
+    C-Operator     & Verknüpfung              & Anwendung                \\[\smallskipamount]
+    \lstinline,&,  & Und                      & Bits gezielt löschen     \\
+    \lstinline,|,  & Oder                     & Bits gezielt setzen      \\
+    \lstinline,^,  & Exklusiv-Oder            & Bits gezielt invertieren \\
+    \lstinline,~,  & Nicht                    & Alle Bits invertieren    \\[\smallskipamount]
+    \lstinline,<<, & Verschiebung nach links  & Maske generieren         \\
+    \lstinline,>>, & Verschiebung nach rechts & Bits isolieren
+  \end{tabular}
+
+  \bigskip
+
+  Numerierung der Bits: von rechts ab 0
+
+  \medskip
+
+  \begin{tabular}{ll}
+    Bit Nr.\ 3 auf 1 setzen: &
+    \lstinline,a |= 1 << 3;, \\
+    Bit Nr.\ 4 auf 0 setzen: &
+    \lstinline,a &= ~(1 << 4);, \\
+    Bit Nr.\ 0 invertieren: &
+    \lstinline,a ^= 1 << 0;,
+  \end{tabular}
+
+  \smallskip
+
+  ~~Abfrage, ob Bit Nr.\ 1 gesetzt ist:\quad
+  \lstinline{if (a & (1 << 1))}
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsubsubsection
+
+  C-Datentypen für Bit-Operationen:
+  \smallskip\par
+  \lstinline{#include <stdint.h>}
+  \medskip\par
+  \begin{tabular}{lllll}
+                    & 8 Bit & 16 Bit & 32 Bit & 64 Bit \\
+    mit Vorzeichen  & \lstinline,int8_t,
+                    & \lstinline,int16_t,
+                    & \lstinline,int32_t,
+                    & \lstinline,int64_t, \\
+    ohne Vorzeichen & \lstinline,uint8_t,
+                    & \lstinline,uint16_t,
+                    & \lstinline,uint32_t,
+                    & \lstinline,uint64_t,
+  \end{tabular}
+
+  \bigskip
+  \bigskip
+
+  Ausgabe:
+  \smallskip\par
+  \begin{lstlisting}
+    #include <stdio.h>
+    #include <stdint.h>
+    #include <inttypes.h>
+    ...
+    uint64_t x = 42;
+    printf ("Die Antwort lautet: %" PRIu64 "\n", x);
+  \end{lstlisting}
+
+\end{frame}
+
+\subsection{I/O-Ports}
+
+\begin{frame}[fragile]
+
+%  \showsection
+  \showsubsection
+  \vspace*{-1.5\medskipamount}
+  {\large\textbf{\color{structure}5.3\quad Interrupts}}
+
+  \bigskip
+
+  Kommunikation mit externen Geräten
+
+  \bigskip
+
+  \begin{center}
+    \includegraphics{io-ports-and-interrupts.pdf}
+  \end{center}
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  In Output-Port schreiben = Aktoren ansteuern
+
+  Beispiel: LED
+
+  \medskip
+
+  \begin{lstlisting}
+    #include <avr/io.h>
+    ...
+    DDRC = 0x70;
+    PORTC = 0x40;
+  \end{lstlisting}
+  \begin{picture}(0,0)
+    \put(3,0.67){\begin{minipage}{3cm}
+                \color{red}%
+                binär: 0111\,0000\\
+                binär: 0100\,0000
+              \end{minipage}}
+    \put(10,0.67){\makebox(0,0)[r]{\color{red}Herstellerspezifisch!}}
+  \end{picture}
+
+  \bigskip
+
+  \lstinline{DDR} = Data Direction Register\\
+  Bit = 1 für Output-Port\\
+  Bit = 0 für Input-Port
+
+  \bigskip
+
+  \emph{Details: siehe Datenblatt und Schaltplan}
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Aus Input-Port lesen = Sensoren abfragen
+
+  Beispiel: Taster
+
+  \medskip
+
+  \begin{lstlisting}
+    #include <avr/io.h>
+    ...
+    DDRC = 0xfd;
+    while ((PINC & 0x02) == 0)
+      ; /* just wait */
+  \end{lstlisting}
+  \begin{picture}(0,0)(-1.5,-0.42)
+    \put(3,0.67){\begin{minipage}{3cm}
+                \color{red}%
+                binär: 1111\,1101\\
+                binär: 0000\,0010
+              \end{minipage}}
+    \put(10,0.67){\makebox(0,0)[r]{\color{red}Herstellerspezifisch!}}
+  \end{picture}
+
+  \bigskip
+
+  \lstinline{DDR} = Data Direction Register\\
+  Bit = 1 für Output-Port\\
+  Bit = 0 für Input-Port
+
+  \bigskip
+
+  \emph{Details: siehe Datenblatt und Schaltplan}
+  
+  \bigskip
+
+  Praktikumsaufgabe: Druckknopfampel
+
+\end{frame}
+
+\subsection{Interrupts}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Externes Gerät ruft (per Stromsignal) Unterprogramm auf
+
+  Zeiger hinterlegen: "`Interrupt-Vektor"'
+
+  Beispiel: eingebaute Uhr\hfill
+  \makebox(0,0)[tr]{%
+    \only<1->{\begin{minipage}[t]{4.7cm}
+        \vspace*{-0.3cm}%
+        statt Zählschleife (\lstinline{_delay_ms}):\\
+        Hauptprogramm kann\\
+        andere Dinge tun
+      \end{minipage}}%
+    }
+
+  \medskip
+
+  \begin{lstlisting}
+    #include <avr/interrupt.h>
+
+    ...
+
+
+    ISR (TIMER0B_COMP_vect)
+    {
+      PORTD ^= 0x40;
+    }
+  \end{lstlisting}
+  \begin{picture}(0,0)
+    \color{red}
+    \put(1.9,3.1){\makebox(0,0)[tr]{\tikz{\draw[-latex](0,0)--(-1.4,-1.0);}}}
+    \put(2.0,3.2){\makebox(0,0)[l]{"`Dies ist ein Interrupt-Handler."'}}
+    \put(2.3,2.6){\makebox(0,0)[tr]{\tikz{\draw[-latex](0,0)--(-0.6,-0.55);}}}
+    \put(2.4,2.6){\makebox(0,0)[l]{Interrupt-Vektor darauf zeigen lassen}}
+  \end{picture}
+
+  Initialisierung über spezielle Ports:
+  \lstinline{TCCR0B}, \lstinline{TIMSK0}
+
+  \bigskip
+
+  \emph{Details: siehe Datenblatt und Schaltplan}
+
+  \vspace*{-2.5cm}\hfill
+  {\color{red}Herstellerspezifisch!}%
+  \hspace*{1cm}
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Externes Gerät ruft (per Stromsignal) Unterprogramm auf
+
+  Zeiger hinterlegen: "`Interrupt-Vektor"'
+
+  Beispiel: Taster\hfill
+  \makebox(0,0)[tr]{%
+    \begin{minipage}[t]{4.7cm}
+      \vspace*{-0.3cm}%
+      statt \newterm{Busy Waiting\/}:\\
+      Hauptprogramm kann\\
+      andere Dinge tun
+    \end{minipage}}
+
+  \medskip
+
+  \begin{lstlisting}
+    #include <avr/interrupt.h>
+    ...
+
+    ISR (INT0_vect)
+    {
+      PORTD ^= 0x40;
+    }
+  \end{lstlisting}
+
+  \medskip
+
+  Initialisierung über spezielle Ports:
+  \lstinline{EICRA}, \lstinline{EIMSK}
+
+  \bigskip
+
+  \emph{Details: siehe Datenblatt und Schaltplan}
+
+  \vspace*{-2.5cm}\hfill
+  {\color{red}Herstellerspezifisch!}%
+  \hspace*{1cm}
+
+\end{frame}
+
+\subsection{volatile-Variable}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Externes Gerät ruft (per Stromsignal) Unterprogramm auf
+
+  Zeiger hinterlegen: "`Interrupt-Vektor"'
+
+  Beispiel: Taster
+
+  \vspace*{-2.5pt}
+
+  \begin{minipage}[t]{5cm}
+    \begin{onlyenv}<1>
+      \begin{lstlisting}[gobble=8]
+        ¡#include <avr/interrupt.h>
+        ...
+
+        uint8_t key_pressed = 0;
+
+        ISR (INT0_vect)
+        {
+          key_pressed = 1;
+        }¿
+      \end{lstlisting}
+    \end{onlyenv}
+    \begin{onlyenv}<2>
+      \begin{lstlisting}[gobble=8]
+        ¡#include <avr/interrupt.h>
+        ...
+
+        volatile uint8_t key_pressed = 0;
+
+        ISR (INT0_vect)
+        {
+          key_pressed = 1;
+        }¿
+      \end{lstlisting}
+    \end{onlyenv}
+  \end{minipage}\hfill
+  \begin{minipage}[t]{6cm}
+    \begin{lstlisting}[gobble=6]
+      ¡int main (void)
+      {
+        ...
+
+        while (1)
+          {
+            while (!key_pressed)
+              ;  /* just wait */
+            PORTD ^= 0x40;
+            key_pressed = 0;
+          }
+        return 0;
+      }¿
+    \end{lstlisting}
+  \end{minipage}
+
+  \pause
+  \begin{picture}(0,0)
+    \color{red}
+    \put(10.3,4.0){\makebox(0,0)[b]{\begin{minipage}{6cm}
+        \begin{center}
+          \textbf{volatile}:\\
+          Speicherzugriff\\
+          nicht wegoptimieren
+        \end{center}
+      \end{minipage}}}
+    \put(10.3,3.95){\makebox(0,0)[tr]{\tikz{\draw[-latex](0,0)--(-0.5,-0.9);}}}
+  \end{picture}
+
+\end{frame}
+
+\iffalse
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Was ist eigentlich \lstinline{PORTD}?
+
+  \bigskip
+  \pause
+
+  \lstinline[style=cmd]{avr-gcc -Wall -Os -mmcu=atmega328p blink-3.c -E}
+
+  \bigskip
+  \pause
+  \lstinline{PORTD = 0x01;}\\
+  \textarrow\quad
+  \lstinline[style=terminal]{(*(volatile uint8_t *)((0x0B) + 0x20)) = 0x01;}\\
+  \pause
+  \begin{picture}(0,2)(0,-1.7)
+    \color{red}
+    \put(5.75,0.3){$\underbrace{\rule{2.95cm}{0pt}}_{\mbox{Zahl: \lstinline|0x2B|}}$}
+    \pause
+    \put(1.55,0.3){$\underbrace{\rule{4.0cm}{0pt}}_{\mbox{\shortstack[t]{Umwandlung in Zeiger\\
+      auf \lstinline|volatile uint8_t|}}}$}
+    \pause
+    \put(1.32,-1){\makebox(0,0)[b]{\tikz{\draw[-latex](0,0)--(0,1.3)}}}
+    \put(1.12,-1.1){\makebox(0,0)[tl]{Dereferenzierung des Zeigers}}
+  \end{picture}
+
+  \pause
+  \textarrow\quad
+  \lstinline|volatile uint8_t|-Variable an Speicheradresse \lstinline|0x2B|
+
+  \pause
+  \bigskip
+  \bigskip
+
+  \textarrow\quad
+  \lstinline|PORTA = PORTB = PORTC = PORTD = 0| ist eine schlechte Idee.
+
+\end{frame}
+
+\fi
+
+\subsection{Byte-Reihenfolge -- Endianness}
+\subsubsection{Konzept}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+  \showsubsubsection
+
+  Eine Zahl geht über mehrere Speicherzellen.\\
+  Beispiel: 16-Bit-Zahl in 2 8-Bit-Speicherzellen
+
+  \smallskip
+
+  Welche Bits liegen wo?
+
+  \pause
+  \bigskip
+
+  $1027 = 1024 + 2 + 1 = 0000\,0100\,0000\,0011_2 = 0403_{16}$
+
+  \pause
+  \bigskip
+  Speicherzellen:
+
+  \medskip
+  \begin{tabular}{|c|c|l}\cline{1-2}
+    \raisebox{-0.25ex}{04} & \raisebox{-0.25ex}{03} & \strut Big-Endian "`großes Ende zuerst"' \\\cline{1-2}
+    \multicolumn{2}{c}{} & \pause für Menschen leichter lesbar \pause \\
+    \multicolumn{3}{c}{} \\[-5pt]\cline{1-2}
+    \raisebox{-0.25ex}{03} & \raisebox{-0.25ex}{04} & \strut Little-Endian "`kleines Ende zuerst"' \\\cline{1-2}
+    \multicolumn{2}{c}{} & \pause bei Additionen effizienter
+  \end{tabular}
+
+  \pause
+  \medskip
+  \textarrow\ Geschmackssache
+  \pause\\
+  \quad\textbf{\dots\ außer bei Datenaustausch!}
+
+%  \pause
+%  \bigskip
+%
+%  Aber: nicht verwechseln! \qquad $0304_{16} = 772$
+
+\end{frame}
+
+\begin{frame}
+
+  \showsubsection
+  \showsubsubsection
+
+  Eine Zahl geht über mehrere Speicherzellen.\\
+  Beispiel: 16-Bit-Zahl in 2 8-Bit-Speicherzellen
+
+  \smallskip
+
+  Welche Bits liegen wo?
+
+  \medskip
+
+  \textarrow\ Geschmackssache\\
+  \textbf{\dots\ außer bei Datenaustausch!}
+
+  \begin{itemize}
+    \item
+      Dateiformate
+    \item
+      Datenübertragung
+  \end{itemize}
+
+\end{frame}
+
+\subsubsection{Dateiformate}
+
+\begin{frame}
+
+  \showsubsection
+  \showsubsubsection
+
+  Audio-Formate: Reihenfolge der Bytes in 16- und 32-Bit-Zahlen
+  \begin{itemize}
+    \item
+      RIFF-WAVE-Dateien (\file{.wav}): Little-Endian
+    \item
+      Au-Dateien (\file{.au}): Big-Endian
+    \pause
+    \item
+      ältere AIFF-Dateien (\file{.aiff}): Big-Endian
+    \item
+      neuere AIFF-Dateien (\file{.aiff}): Little-Endian
+  \end{itemize}
+
+  \pause
+  \bigskip
+
+  Grafik-Formate: Reihenfolge der Bits in den Bytes
+  \begin{itemize}
+    \item
+      PBM-Dateien: Big-Endian\only<4->{, MSB first}
+    \item
+      XBM-Dateien: Little-Endian\only<4->{, LSB first}
+  \end{itemize}
+  \only<4->{MSB/LSB = most/least significant bit}
+
+\end{frame}
+
+\subsubsection{Datenübertragung}
+
+\begin{frame}
+
+  \showsubsection
+  \showsubsubsection
+
+  \begin{itemize}
+    \item
+      RS-232 (serielle Schnittstelle): LSB first
+    \item
+      I$^2$C: MSB first
+    \item
+      USB: beides
+    \pause
+    \medskip
+    \item
+      Ethernet: LSB first
+    \item
+      TCP/IP (Internet): Big-Endian
+  \end{itemize}
+
+\end{frame}
+
+\subsection{Binärdarstellung negativer Zahlen}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Speicher ist begrenzt!\\
+  \textarrow\ feste Anzahl von Bits
+
+  \medskip
+
+  8-Bit-Zahlen ohne Vorzeichen: \lstinline{uint8_t}\\
+  \textarrow\ Zahlenwerte von \lstinline{0x00} bis \lstinline{0xff} = 0 bis 255\\
+  \pause
+  \textarrow\ 255 + 1 = 0
+
+  \pause
+  \medskip
+
+  8-Bit-Zahlen mit Vorzeichen: \lstinline{int8_t}\\
+  \lstinline{0xff} = 255 ist die "`natürliche"' Schreibweise für $-1$.\\
+  \pause
+  \textarrow\ Zweierkomplement
+
+  \pause
+  \medskip
+
+  Oberstes Bit = 1: negativ\\
+  Oberstes Bit = 0: positiv\\
+  \textarrow\ 127 + 1 = $-128$
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Speicher ist begrenzt!\\
+  \textarrow\ feste Anzahl von Bits
+
+  \medskip
+
+  16-Bit-Zahlen ohne Vorzeichen:
+  \lstinline{uint16_t}\hfill\lstinline{uint8_t}\\
+  \textarrow\ Zahlenwerte von \lstinline{0x0000} bis \lstinline{0xffff}
+  = 0 bis 65535\hfill 0 bis 255\\
+  \textarrow\ 65535 + 1 = 0\hfill 255 + 1 = 0
+
+  \medskip
+
+  16-Bit-Zahlen mit Vorzeichen:
+  \lstinline{int16_t}\hfill\lstinline{int8_t}\\
+  \lstinline{0xffff} = 66535 ist die "`natürliche"' Schreibweise für $-1$.\hfill
+  \lstinline{0xff} = 255 = $-1$\\
+  \textarrow\ Zweierkomplement
+
+  \medskip
+
+  Oberstes Bit = 1: negativ\\
+  Oberstes Bit = 0: positiv\\
+  \textarrow\ 32767 + 1 = $-32768$
+
+  \bigskip
+  Literatur: \url{http://xkcd.com/571/}
+
+\end{frame}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  Frage: \emph{Für welche Zahl steht der Speicherinhalt\,
+  \raisebox{2pt}{%
+    \tabcolsep0.25em
+    \begin{tabular}{|c|c|}\hline
+      \rule{0pt}{11pt}a3 & 90 \\\hline
+    \end{tabular}}
+  (hexadezimal)?}
+  
+  \pause
+  \smallskip
+  Antwort: \emph{Das kommt darauf an.} ;--)
+
+  \pause
+  \medskip
+  Little-Endian:
+
+  \smallskip
+
+  \begin{tabular}{lrl}
+    als \lstinline,int8_t,: & $-93$ & (nur erstes Byte)\\
+    als \lstinline,uint8_t,: & $163$ & (nur erstes Byte)\\
+    als \lstinline,int16_t,: & $-28509$\\
+    als \lstinline,uint16_t,: & $37027$\\
+    \lstinline,int32_t, oder größer: & $37027$
+      & (zusätzliche Bytes mit Nullen aufgefüllt)
+  \end{tabular}
+
+  \pause
+  \medskip
+  Big-Endian:
+
+  \smallskip
+
+  \begin{tabular}{lrl}
+    als \lstinline,int8_t,:   & $-93$ & (nur erstes Byte)\\
+    als \lstinline,uint8_t,:  & $163$ & (nur erstes Byte)\\
+    als \lstinline,int16_t,:  & $-23664$\\
+    als \lstinline,uint16_t,: & $41872$\\ als \lstinline,int32_t,:  & $-1550843904$ & (zusätzliche Bytes\\
+    als \lstinline,uint32_t,: & $2744123392$  & mit Nullen aufgefüllt)\\
+    als \lstinline,int64_t,:  & $-6660823848880963584$\\
+    als \lstinline,uint64_t,: & $11785920224828588032$\\
+  \end{tabular}
+
+  \vspace*{-1cm}
+
+\end{frame}
+
+\subsection{Speicherausrichtung -- Alignment}
+
+\begin{frame}[fragile]
+
+  \showsubsection
+
+  \begin{lstlisting}
+    #include <stdint.h>
+
+    uint8_t a;
+    uint16_t b;
+    uint8_t c;
+  \end{lstlisting}
+
+  \pause
+  \bigskip
+
+  Speicheradresse durch 2 teilbar -- "`16-Bit-Alignment"'
+  \begin{itemize}
+    \item
+      2-Byte-Operation: effizienter
+    \pause
+    \item
+      \dots\ oder sogar nur dann erlaubt
+    \pause
+    \arrowitem
+      Compiler optimiert Speicherausrichtung
+  \end{itemize}
+
+  \medskip
+
+  \pause
+  \begin{minipage}{3cm}
+    \begin{lstlisting}[gobble=6]
+      ¡uint8_t a;
+      uint8_t dummy;
+      uint16_t b;
+      uint8_t c;¿
+    \end{lstlisting}
+  \end{minipage}
+  \pause
+  \begin{minipage}{3cm}
+    \begin{lstlisting}[gobble=6]
+      ¡uint8_t a;
+      uint8_t c;
+      uint16_t b;¿
+    \end{lstlisting}
+  \end{minipage}
+
+  \pause
+  \vspace{-1.75cm}
+  \strut\hfill
+  \begin{minipage}{6.5cm}
+    Fazit:
+    \begin{itemize}
+      \item
+        \textbf{Adressen von Variablen\\
+        sind systemabhängig}
+      \item
+        Bei Definition von Datenformaten\\
+        Alignment beachten \textarrow\ effizienter
+    \end{itemize}
+  \end{minipage}
+
+\end{frame}
+
+\nosectionnonumber{\inserttitle}
+
+\begin{frame}
+
+  \shownosectionnonumber
+
+  \begin{itemize}
+    \item[\textbf{1}] \textbf{Einführung}
+      \hfill\makebox(0,0)[br]{\raisebox{2.25ex}{\url{https://gitlab.cvh-server.de/pgerwinski/hp}}}
+    \item[\textbf{2}] \textbf{Einführung in C}
+      \begin{itemize}
+        \vspace*{-\smallskipamount}
+        \item[\dots]
+        \item[2.14] Parameter des Hauptprogramms
+        \item[2.15] String-Operationen
+      \end{itemize}
+    \item[\textbf{3}] \textbf{Bibliotheken}
+    \item[\textbf{4}] \textbf{Hardwarenahe Programmierung}
+      \begin{itemize}
+        \item[4.1] Bit-Operationen
+        \color{medgreen}
+        \item[4.2] I/O-Ports
+        \item[4.3] Interrupts
+        \item[4.4] volatile-Variable
+        \color{red}
+        \item[4.6] Byte-Reihenfolge -- Endianness
+        \item[4.7] Binärdarstellung negativer Zahlen
+        \item[4.8] Speicherausrichtung -- Alignment
+      \end{itemize}
+    \item[\textbf{5}] \textbf{Algorithmen}
+    \item[\textbf{\dots}]
+  \end{itemize}
+
+\end{frame}
+
+\end{document}
diff --git a/20211115/hp-musterloesung-20211115.pdf b/20211115/hp-musterloesung-20211115.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..df7200de50936fd484c8353512876f910317bf5b
Binary files /dev/null and b/20211115/hp-musterloesung-20211115.pdf differ
diff --git a/20211115/hp-musterloesung-20211115.tex b/20211115/hp-musterloesung-20211115.tex
new file mode 100644
index 0000000000000000000000000000000000000000..c9dc97835ada978af0da32a80219a01c97e8257d
--- /dev/null
+++ b/20211115/hp-musterloesung-20211115.tex
@@ -0,0 +1,554 @@
+% hp-musterloesung-20211115.pdf - Solutions to the Exercises on Low-Level Programming
+% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021  Peter Gerwinski
+%
+% This document is free software: you can redistribute it and/or
+% modify it either under the terms of the Creative Commons
+% Attribution-ShareAlike 3.0 License, or under the terms of the
+% GNU General Public License as published by the Free Software
+% Foundation, either version 3 of the License, or (at your option)
+% any later version.
+%
+% This document is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this document.  If not, see <http://www.gnu.org/licenses/>.
+%
+% You should have received a copy of the Creative Commons
+% Attribution-ShareAlike 3.0 Unported License along with this
+% document.  If not, see <http://creativecommons.org/licenses/>.
+
+% README: Zahlensysteme, Mikrocontroller, Einfügen in Strings
+
+\documentclass[a4paper]{article}
+
+\usepackage{pgscript}
+
+\begin{document}
+
+  \section*{Hardwarenahe Programmierung\\
+            Musterlösung zu den Übungsaufgaben -- l5.\ November 2021}
+
+  \exercise{Zahlensysteme}
+
+  Wandeln Sie ohne Hilfsmittel
+
+  \begin{minipage}[t]{0.3\textwidth}
+    \begin{itemize}
+      \item
+        nach Dezimal:
+        \begin{itemize}
+          \item[(a)]
+            0010\,0000$_2$
+          \item[(b)]
+            42$_{16}$
+          \item[(c)]
+            17$_8$
+        \end{itemize}
+    \end{itemize}
+  \end{minipage}\hfill
+  \begin{minipage}[t]{0.3\textwidth}
+    \begin{itemize}
+      \item
+        nach Hexadezimal:
+        \begin{itemize}
+          \item[(d)]
+            0010\,0000$_2$
+          \item[(e)]
+            42$_{10}$
+          \item[(f)]
+            192.168.20.254$_{256}$
+        \end{itemize}
+    \end{itemize}
+  \end{minipage}\hfill
+  \begin{minipage}[t]{0.3\textwidth}
+    \begin{itemize}
+      \item
+        nach Binär:
+        \begin{itemize}
+          \item[(g)]
+            750$_8$
+          \item[(h)]
+            42$_{10}$
+          \item[(i)]
+            AFFE$_{16}$
+        \end{itemize}
+    \end{itemize}
+  \end{minipage}
+  
+  \medskip
+
+  Berechnen Sie ohne Hilfsmittel:
+  \begin{itemize}
+    \item[(j)]
+      750$_8$ \& 666$_8$
+    \item[(k)]
+      A380$_{16}$ + B747$_{16}$
+    \item[(l)]
+      AFFE$_{16} >> 1$
+  \end{itemize}
+
+  Die tiefgestellte Zahl steht für die Basis des Zahlensystems.
+  Jede Teilaufgabe zählt 1 Punkt. \addtocounter{points}{12}
+
+  (In der Klausur sind Hilfsmittel zugelassen,
+  daher ist dies \emph{keine\/} typische Klausuraufgabe.)
+
+  \solution
+
+  Wandeln Sie ohne Hilfsmittel
+
+  \begin{itemize}
+    \item
+      nach Dezimal:
+      \begin{itemize}
+        \item[(a)]
+          $0010\,0000_2 = 32_{10}$
+
+          Eine Eins mit fünf Nullen dahinter steht binär für $2^5 = 32$:\\
+          mit $1$ anfangen und fünfmal verdoppeln.
+        \item[(b)]
+          $42_{16} = 4 \cdot 16 + 2 \cdot 1 = 64 + 2 = 66$
+        \item[(c)]
+          $17_8 = 1 \cdot 8 + 7 \cdot 1 = 8 + 7 = 15$
+      \end{itemize}
+      Umwandlung von und nach Dezimal ist immer rechenaufwendig.
+      Umwandlungen zwischen Binär, Oktal und Hexadezimal gehen ziffernweise
+      und sind daher wesentlich einfacher.
+    \item
+      nach Hexadezimal:
+      \begin{itemize}
+        \item[(d)]
+          $0010\,0000_2 = 20_{16}$
+
+          Umwandlung von Binär nach Hexadezimal geht ziffernweise:\\
+          Vier Binärziffern werden zu einer Hex-Ziffer.
+        \item[(e)]
+          $\rm 42_{10} = 32_{10} + 10_{10} = 20_{16} + A_{16} = 2A_{16}$
+        \item[(f)]
+          $\rm 192.168.20.254_{256} = C0\,A8\,14\,FE_{16}$
+
+          Umwandlung von der Basis 256 nach Hexadezimal geht ziffernweise:\\
+          Eine 256er-Ziffer wird zu zwei Hex-Ziffern.
+
+          Da die 256er-Ziffern dezimal angegeben sind,
+          müssen wir viermal Dezimal nach Hexadezimal umwandeln.
+          Hierfür bieten sich unterschiedliche Wege an.
+
+          $\rm 192_{10} = 128_{10} + 64_{10} = 1100\,0000_{2} = C0_{16}$
+
+          $\rm 168_{10} = 10_{10} \cdot 16_{10} + 8_{10} = A_{16} \cdot 10_{16} + 8_{16} = A8_{16}$
+
+          $20_{10} = 16_{10} + 4_{10} = 10_{16} + 4_{16} = 14$
+          
+          $\rm 254_{10} = 255_{10} - 1_{10} = FF_{16} - 1_{16} = FE_{16}$
+      \end{itemize}
+    \item
+      nach Binär:
+      \begin{itemize}
+        \item[(g)]
+          $750_8 = 111\,101\,000_2$
+
+          Umwandlung von Oktal nach Binär geht ziffernweise:\\
+          Eine Oktalziffer wird zu drei Binärziffern.
+        \item[(h)]
+          $\rm 42_{10} = 2A_{16}$ (siehe oben) $= 0010\,1010_{16}$
+
+          Umwandlung von Hexadezimal nach Binär geht ziffernweise:\\
+          Eine Hex-Ziffer wird zu vier Binärziffern.
+        \item[(i)]
+          $\rm AFFE_{16} = 1010\,1111\,1111\,1110_2$
+
+          Umwandlung von Hexadezimal nach Binär geht ziffernweise:\\
+          Eine Hex-Ziffer wird zu vier Binärziffern.
+      \end{itemize}
+  \end{itemize}
+  
+  \medskip
+
+  Berechnen Sie ohne Hilfsmittel:
+  \begin{itemize}
+    \item[(j)]
+      $750_8\,\&\,666_8
+      = 111\,101\,000_2\,\&\,110\,110\,110_2
+      = 110\,100\,000_2
+      = 640_8$
+
+      Binäre Und-Operationen lassen sich am leichtesten
+      in binärer Schreibweise durchführen.
+      Umwandlung zwischen Oktal und Binär geht ziffernweise:
+      Eine Oktalziffer wird zu drei Binärziffern und umgekehrt.
+
+      Mit etwas Übung funktionieren diese Operationen
+      auch direkt mit Oktalzahlen im Kopf.
+
+    \item[(k)]
+      $\rm\phantom{+}A380_{16}$\\
+      $\rm+\kern2ptB747_{16}$\\[-\medskipamount]
+      \rule{1.4cm}{0.5pt}\\
+      $\rm 15AC7_{16}$
+      \begin{picture}(0,0)
+        \put(-1.4,0.35){\mbox{\scriptsize\bf 1}}
+      \end{picture}
+
+      Mit Hexadezimalzahlen (und Binär- und Oktal- und sonstigen Zahlen)
+      kann man genau wie mit Dezimalzahlen schriftlich rechnen.
+      Man muß nur daran denken, daß der "`Zehner"'-Überlauf nicht bei
+      $10_{10}$ stattfindet, sondern erst bei $10_{16} = 16_{10}$
+      (hier: $\rm 8_{16} + 4_{16} = C_{16}$ und
+      $\rm 3_{16} + 7_{16} = A_{16}$, aber
+      $\rm A_{16} + B_{16} = 10_{10} + 11_{10}
+      = 21_{10} = 16_{10} + 5_{10} = 10_{16} + 5_{16} =  15_{16}$).
+
+    \item[(l)]
+      $\rm AFFE_{16} >> 1
+      = 1010\,1111\,1111\,1110_2 >> 1
+      = 0101\,0111\,1111\,1111_2
+      = 57FF_{16}$
+
+      Bit-Verschiebungen lassen sich am leichtesten
+      in binärer Schreibweise durchführen.
+      Umwandlung zwischen Hexadezimal und Binär geht ziffernweise:
+      Eine Hex-Ziffer wird zu vier Binärziffern und umgekehrt.
+
+      Mit etwas Übung funktionieren diese Operationen
+      auch direkt mit Hexadezimalzahlen im Kopf.
+
+  \end{itemize}
+
+  \exercise{Mikrocontroller}
+
+  \begin{minipage}[t]{10cm}
+    An die vier Ports eines ATmega16-Mikrocontrollers sind Leuchtdioden angeschlossen:
+    \begin{itemize}
+      \item
+        von links nach rechts an die Ports A, B, C und D,
+      \item
+        von oben nach unten an die Bits Nr.\ 0 bis 7.
+    \end{itemize}
+
+    Wir betrachten das folgende Programm (\gitfile{hp}{2021ws/20211115}{aufgabe-2.c}):
+
+    \begin{lstlisting}[gobble=6]
+      #include <avr/io.h>
+
+      int main (void)
+      {
+        DDRA = 0xff;
+        DDRB = 0xff;
+        DDRC = 0xff;
+        DDRD = 0xff;
+        PORTA = 0x1f;
+        PORTB = 0x10;
+        PORTD = 0x10;
+        PORTC = 0xfc;
+        while (1);
+        return 0;
+      }
+    \end{lstlisting}
+  \end{minipage}\hfill
+  \begin{minipage}[t]{3cm}
+    \strut\\[-\baselineskip]
+    \includegraphics[width=3cm]{leds.jpg}
+  \end{minipage}
+
+  \vspace*{-3cm}
+
+  \strut\hfill
+  \begin{minipage}{11.8cm}
+    \begin{itemize}
+      \item[(a)]
+        Was bewirkt dieses Programm? \points{4}
+      \item[(b)]
+        Wozu dienen die ersten vier Zeilen des Hauptprogramms? \points{2}
+      \item[(c)]
+        Was würde stattdessen die Zeile \lstinline{DDRA, DDRB, DDRC, DDRD = 0xff;} bewirken?
+        \points{2}
+      \item[(d)]
+        Schreiben Sie das Programm so um,
+        daß die durch das Programm dargestellte Figur spiegelverkehrt erscheint. \points{3}
+      \item[(e)]
+        Wozu dient das \lstinline{while (1)}? \points{2}
+      \item
+        Alle Antworten bitte mit Begründung.
+    \end{itemize}
+  \end{minipage}
+
+  \solution
+
+  \begin{itemize}
+    \item[(a)]
+      \textbf{Was bewirkt dieses Programm?}
+
+      \newcommand{\x}{$\bullet$}
+      \renewcommand{\o}{$\circ$}
+
+      \begin{minipage}[t]{0.75\textwidth}\parskip\smallskipamount
+        Es läßt die LEDs in dem rechts abgebildeten Muster aufleuchten,\\
+        das z.\,B.\ als die Ziffer 4 gelesen werden kann.
+
+        (Das Zeichen \x\ steht für eine leuchtende, \o\ für eine nicht leuchtende LED.)
+
+        Die erste Spalte (Port A) von unten nach oben gelesen (Bit 7 bis 0)\\
+        entspricht der Binärdarstellung von \lstinline{0x1f}: 0001\,1111.
+
+        Die dritte Spalte (Port C) von unten nach oben gelesen (Bit 7 bis 0)\\
+        entspricht der Binärdarstellung von \lstinline{0xfc}: 1111\,1100.
+
+        Die zweite und vierte Spalte (Port B und D) von unten nach oben gelesen\\
+        (Bit 7 bis 0) entsprechen der Binärdarstellung von \lstinline{0x10}: 0001\,0000.
+
+        Achtung: Die Zuweisung der Werte an die Ports erfolgt im Programm\\
+        \emph{nicht\/} in der Reihenfolge A B C D, sondern in der Reihenfolge A B D C.
+      \end{minipage}\hfill
+      \begin{minipage}[t]{0.15\textwidth}
+        \vspace*{-0.5cm}%
+        \begin{tabular}{cccc}
+          \x & \o & \o & \o \\
+          \x & \o & \o & \o \\
+          \x & \o & \x & \o \\
+          \x & \o & \x & \o \\
+          \x & \x & \x & \x \\
+          \o & \o & \x & \o \\
+          \o & \o & \x & \o \\
+          \o & \o & \x & \o \\
+        \end{tabular}
+      \end{minipage}
+
+    \item[(b)]
+      \textbf{Wozu dienen die ersten vier Zeilen des Hauptprogramms?}
+
+      Mit diesen Zeilen werden alle jeweils 8 Bits aller 4 Ports
+      als Output-Ports konfiguriert.
+
+    \item[(c)]
+      \textbf{Was würde stattdessen die Zeile \lstinline{DDRA, DDRB, DDRC, DDRD = 0xff;} bewirken?}
+
+      Der Komma-Operator in C bewirkt, daß der erste Wert berechnet
+      und wieder verworfen wird und stattdessen der zweite Wert weiterverarbeitet wird.
+      Konkret hier hätte das zur Folge,
+      daß \lstinline{DDRA}, \lstinline{DDRB} und \lstinline{DDRC}
+      gelesen und die gelesenen Werte ignoriert werden;
+      anschließend wird \lstinline{DDRD} der Wert \lstinline{0xff} zugewiesen.
+      Damit würde also nur einer von vier Ports überhaupt konfiguriert.
+
+      Da es sich bei den \lstinline{DDR}-Variablen
+      um \lstinline{volatile}-Variable handelt,
+      nimmt der Compiler an, daß der Lesezugriff schon irgendeinen Sinn hätte.
+      Der Fehler bliebe also unbemerkt.
+
+    \item[(d)]
+      \textbf{Schreiben Sie das Programm so um,
+      daß die durch das Programm dargestellte Figur spiegelverkehrt erscheint.}
+
+      Hierzu vertauschen wir die Zuweisungen
+      an \lstinline{PORTA} und \lstinline{PORTD}
+      sowie die Zuweisungen
+      an \lstinline{PORTB} und \lstinline{PORTC}:
+
+      \begin{lstlisting}[gobble=8]
+          PORTD = 0x1f;
+          PORTC = 0x10;
+          PORTA = 0x10;
+          PORTB = 0xfc;
+      \end{lstlisting}
+
+      Damit ergibt sich eine Spiegelung an der vertikalen Achse.
+
+      Alternativ kann man auch an der horizontalen Achse spiegeln.
+      Dafür muß man die Bits in den Hexadezimalzahlen umdrehen:
+
+      \begin{lstlisting}[gobble=8]
+          PORTA = 0xf8;
+          PORTB = 0x08;
+          PORTD = 0x08;
+          PORTC = 0x3f;
+      \end{lstlisting}
+
+      Die Frage, welche der beiden Spiegelungen gewünscht ist,
+      wäre übrigens \emph{auch in der Klausur zulässig}.
+
+    \item[(e)]
+      \textbf{Wozu dient das \lstinline{while (1)}?}
+
+      Mit dem \lstinline{return}-Befehl am Ende des Hauptprogramms
+      gibt das Programm die Kontrolle an das Betriebssystem zurück.
+
+      Dieses Programm jedoch läuft auf einem Mikrocontroller,
+      auf dem es kein Betriebssystem gibt.
+      Wenn das \lstinline{return} ausgeführt würde,
+      hätte es ein undefiniertes Verhalten zur Folge.
+
+      Um dies zu verhindern, endet das Programm in einer Endlosschleife,
+      mit der wir den Mikrocontroller anweisen,
+      nach der Ausführung des Programms \emph{nichts mehr\/} zu tun
+      (im Gegensatz zu: \emph{irgendetwas Undefiniertes\/} zu tun).
+
+  \end{itemize}
+
+  \exercise{Einfügen in Strings}
+
+  Wir betrachten das folgende Programm (\gitfile{hp}{2021ws/20211115}{aufgabe-2.c}):
+%  \begin{lstlisting}[style=numbered]
+  \begin{lstlisting}
+    #include <stdio.h>
+    #include <string.h>
+
+    void insert_into_string (char src, char *target, int pos)
+    {
+      int len = strlen (target);
+      for (int i = pos; i < len; i++)
+        target[i+1] = target[i];
+      target[pos] = src;
+    }
+
+    int main (void)
+    {
+      char test[100] = "Hochshule Bochum";
+      insert_into_string ('c', test, 5);
+      printf ("%s\n", test);
+      return 0;
+    }
+  \end{lstlisting}
+  Die Ausgabe des Programms lautet:
+  \lstinline[style=terminal]{Hochschhhhhhhhhhh}
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      Erklären Sie, wie die Ausgabe zustandekommt.
+      \points{3}
+%      \workspace{12}
+    \item
+      Schreiben Sie die Funktion \lstinline|insert_into_string()| so um,
+      daß sie den Buchstaben \lstinline{src} an der Stelle \lstinline{pos}
+      in den String \lstinline{target} einfügt.\par
+      Die Ausgabe des Programms müßte dann
+      \lstinline[style=terminal]{Hochschule Bochum} lauten.
+      \points{2}
+%      \workspace{13}
+    \item
+      Was kann passieren, wenn Sie die Zeile
+      \lstinline{char test[100] = "Hochshule Bochum";}\\
+      durch
+      \lstinline{char test[] = "Hochshule Bochum";} ersetzen?
+      Begründen Sie Ihre Antwort.
+      \points{2}
+%      \workspace{10}
+    \item
+      Was kann passieren, wenn Sie die Zeile
+      \lstinline{char test[100] = "Hochshule Bochum";}\\
+      durch
+      \lstinline{char *test = "Hochshule Bochum";} ersetzen?
+      Begründen Sie Ihre Antwort.
+      \points{2}
+%      \workspace{10}
+%    \item
+%      Schreiben Sie eine Funktion
+%      \lstinline{void insert_into_string_sorted (char src, char *target)},
+%      die voraussetzt, daß der String \lstinline{target} alphabetisch sortiert ist
+%      und den Buchstaben \lstinline{src} an der alphabetisch richtigen Stelle
+%      einfügt. Diese Funktion darf die bereits vorhandene Funktion
+%      \lstinline|insert_into_string()| aufrufen.\\
+%      \points{4}\par
+%      Zum Testen eignen sich die folgenden Zeilen im Hauptprogramm:
+%      \begin{lstlisting}[gobble=8]
+%        char test[100] = "";
+%        insert_into_string_sorted ('c', test);
+%        insert_into_string_sorted ('a', test);
+%        insert_into_string_sorted ('d', test);
+%        insert_into_string_sorted ('b', test);
+%      \end{lstlisting}
+%      Danach sollte \lstinline{test[]} die Zeichenfolge \lstinline{"abcd"} enthalten.
+%      \workspace{14}
+%    \item
+%      Wie schnell (Landau-Symbol in Abhängigkeit von der Länge $n$ des Strings)
+%      arbeitet Ihre Funktion
+%      \lstinline{void insert_into_string_sorted (char src, char *target)}
+%      und warum?
+%      \points{1}
+%      \workspace{10}
+%    \item
+%      Beschreiben Sie -- in Worten oder als C-Quelltext --, wie man die Funktion\\
+%      \lstinline{void insert_into_string_sorted (char src, char *target)}
+%      so gestalten kann,\\
+%      daß sie in $\mathcal{O}(\log n)$ arbeitet.
+%      \points{3}
+%      \workspace{35}
+  \end{enumerate}
+
+  \solution
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      \textbf{Erklären Sie, wie die Ausgabe zustandekommt.}
+
+      In der Schleife wird \emph{zuerst\/} der nächste Buchstabe \lstinline{target[i + 1]}
+      gleich dem aktuellen gesetzt
+      und \emph{danach\/} der Zähler \lstinline{i} erhöht.
+      Dadurch wird im nächsten Schleifendurchlauf der bereits verschobene Buchstabe
+      noch weiter geschoben und letztlich alle Buchstaben in \lstinline{target[]}
+      durch den an der Stelle \lstinline{pos} ersetzt.
+
+    \item
+      \textbf{Schreiben Sie die Funktion \lstinline|insert_into_string()| so um,
+      daß sie den Buchstben \lstinline{src} an der Stelle \lstinline{pos}
+      in den String \lstinline{target} einfügt.}\par
+      \textbf{Die Ausgabe des Programms müßte dann
+      \lstinline[style=terminal]{Hochschule Bochum} lauten.}
+
+      Um im String "`Platz zu schaffen"', muß man von hinten beginnen,
+      also die Schleife umdrehen\\
+      (siehe: \gitfile{hp}{2021ws/20211115}{loesung-3.c}):
+      \begin{lstlisting}{gobble=8}
+        for (int i = len; i >= pos; i--)
+          target[i + 1] = target[i];
+      \end{lstlisting}
+
+    \item
+      \textbf{Was kann passieren, wenn Sie die Zeile
+      \lstinline{char test[100] = "Hochshule Bochum";}\\
+      durch
+      \lstinline{char test[] = "Hochshule Bochum";}
+      ersetzen und warum?}
+
+      Die Schreibweise \lstinline{test[]} bedeutet,
+      daß der Compiler selbst zählt, wieviel Speicherplatz der String benötigt,
+      un dann genau die richtige Menge Speicher reserviert
+      (anstatt, wie wir es manuell getan haben, pauschal Platz für 100 Zeichen).
+
+      Wenn wir nun in den String ein zusätzliches Zeichen einfügen,
+      ist dafür kein Speicherplatz reserviert worden,
+      und wir \textbf{überschreiben} dann Speicher, an dem sich andere Variable befinden,
+      was zu einem \textbf{Absturz} führen kann.
+
+      Da wir hier nur ein einziges Zeichen schreiben,
+      wird dieser Fehler nicht sofort auffallen.
+      Dies ist schlimmer, als wenn das Programm direkt beim ersten Test abstürzt,
+      denn dadurch entsteht bei uns der Eindruck, es sei in Ordnung.
+      Wenn danach der Fehler in einer Produktivumgebung auftritt,
+      kann dadurch Schaden entstehen -- je nach Einsatzgebiet der Software
+      u.\,U.\ erheblicher Vermögens-, Sach- und/oder Personenschaden
+      (z.\,B.\ Absturz eines Raumflugkörpers).
+
+    \item
+      \textbf{Was kann passieren, wenn Sie 
+      \lstinline{char test[100] = "Hochshule Bochum";}\\
+      durch
+      \lstinline{char *test = "Hochshule Bochum";}
+      ersetzen und warum?}
+
+      In diesem Fall wird der Speicher für den eigentlichen String
+      in einem unbenannten, \textbf{nicht schreibbaren} Teil des Speichers reserviert.
+      Unser Versuch, dorthin ein zusätzliches Zeichen zu schreiben,
+      fürt dann normalerweise zu einem \textbf{Absturz}.
+
+      In manchen Systemen (Betriebssystem, Compiler, \dots)
+      ist der Speicherbereich tatsächlich sehr wohl schreibbar.
+      In diesem Fall tritt der Absturz nicht immer und nicht immer sofort auf --
+      genau wie in Aufgabenteil (c).
+     
+  \end{enumerate}
+
+\end{document}
diff --git a/20211115/hp-uebung-20211115.pdf b/20211115/hp-uebung-20211115.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..e6f02edcd4c7a85b62499452779465c42256e74b
Binary files /dev/null and b/20211115/hp-uebung-20211115.pdf differ
diff --git a/20211115/hp-uebung-20211115.tex b/20211115/hp-uebung-20211115.tex
new file mode 100644
index 0000000000000000000000000000000000000000..5bf88f85f23462397d24d1d4d784909bdfcdd852
--- /dev/null
+++ b/20211115/hp-uebung-20211115.tex
@@ -0,0 +1,262 @@
+% hp-uebung-20211115.pdf - Exercises on Low-Level Programming
+% Copyright (C) 2013, 2015, 2016, 2017, 2018, 2019, 2020, 2021  Peter Gerwinski
+%
+% This document is free software: you can redistribute it and/or
+% modify it either under the terms of the Creative Commons
+% Attribution-ShareAlike 3.0 License, or under the terms of the
+% GNU General Public License as published by the Free Software
+% Foundation, either version 3 of the License, or (at your option)
+% any later version.
+%
+% This document is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this document.  If not, see <http://www.gnu.org/licenses/>.
+%
+% You should have received a copy of the Creative Commons
+% Attribution-ShareAlike 3.0 Unported License along with this
+% document.  If not, see <http://creativecommons.org/licenses/>.
+
+% README: Zahlensysteme, Mikrocontroller, Einfügen in Strings (Ergänzung)
+
+\documentclass[a4paper]{article}
+
+\usepackage{pgscript}
+
+\begin{document}
+
+%  \thispagestyle{empty}
+
+  \section*{Hardwarenahe Programmierung\\
+            Übungsaufgaben -- 15.\ November 2021}
+
+  Diese Übung enthält Punkteangaben wie in einer Klausur.
+  Um zu "`bestehen"', müssen Sie innerhalb von 85 Minuten
+  unter Verwendung ausschließlich zugelassener Hilfsmittel
+  17 Punkte (von insgesamt \totalpoints) erreichen.
+
+  \exercise{Zahlensysteme}
+
+  Wandeln Sie ohne Hilfsmittel
+
+  \begin{minipage}[t]{0.3\textwidth}
+    \begin{itemize}
+      \item
+        nach Dezimal:
+        \begin{itemize}
+          \item[(a)]
+            0010\,0000$_2$
+          \item[(b)]
+            42$_{16}$
+          \item[(c)]
+            17$_8$
+        \end{itemize}
+    \end{itemize}
+  \end{minipage}\hfill
+  \begin{minipage}[t]{0.3\textwidth}
+    \begin{itemize}
+      \item
+        nach Hexadezimal:
+        \begin{itemize}
+          \item[(d)]
+            0010\,0000$_2$
+          \item[(e)]
+            42$_{10}$
+          \item[(f)]
+            192.168.20.254$_{256}$
+        \end{itemize}
+    \end{itemize}
+  \end{minipage}\hfill
+  \begin{minipage}[t]{0.3\textwidth}
+    \begin{itemize}
+      \item
+        nach Binär:
+        \begin{itemize}
+          \item[(g)]
+            750$_8$
+          \item[(h)]
+            42$_{10}$
+          \item[(i)]
+            AFFE$_{16}$
+        \end{itemize}
+    \end{itemize}
+  \end{minipage}
+  
+  \medskip
+
+  Berechnen Sie ohne Hilfsmittel:
+  \begin{itemize}
+    \item[(j)]
+      750$_8$ \& 666$_8$
+    \item[(k)]
+      A380$_{16}$ + B747$_{16}$
+    \item[(l)]
+      AFFE$_{16} >> 1$
+  \end{itemize}
+
+  Die tiefgestellte Zahl steht für die Basis des Zahlensystems.
+  Jede Teilaufgabe zählt 1 Punkt. \addtocounter{points}{12}
+
+  (In der Klausur sind Hilfsmittel zugelassen,
+  daher ist dies \emph{keine\/} typische Klausuraufgabe.)
+
+  \exercise{Mikrocontroller}
+
+  \begin{minipage}[t]{10cm}
+    An die vier Ports eines ATmega16-Mikrocontrollers sind Leuchtdioden angeschlossen:
+    \begin{itemize}
+      \item
+        von links nach rechts an die Ports A, B, C und D,
+      \item
+        von oben nach unten an die Bits Nr.\ 0 bis 7.
+    \end{itemize}
+
+    Wir betrachten das folgende Programm (\gitfile{hp}{2021ws/20211115}{aufgabe-2.c}):
+
+    \begin{lstlisting}[gobble=6]
+      #include <avr/io.h>
+
+      int main (void)
+      {
+        DDRA = 0xff;
+        DDRB = 0xff;
+        DDRC = 0xff;
+        DDRD = 0xff;
+        PORTA = 0x1f;
+        PORTB = 0x10;
+        PORTD = 0x10;
+        PORTC = 0xfc;
+        while (1);
+        return 0;
+      }
+    \end{lstlisting}
+  \end{minipage}\hfill
+  \begin{minipage}[t]{3cm}
+    \strut\\[-\baselineskip]
+    \includegraphics[width=3cm]{leds.jpg}
+  \end{minipage}
+
+  \vspace*{-3cm}
+
+  \strut\hfill
+  \begin{minipage}{11.8cm}
+    \begin{itemize}
+      \item[(a)]
+        Was bewirkt dieses Programm? \points{4}
+      \item[(b)]
+        Wozu dienen die ersten vier Zeilen des Hauptprogramms? \points{2}
+      \item[(c)]
+        Was würde stattdessen die Zeile \lstinline{DDRA, DDRB, DDRC, DDRD = 0xff;} bewirken?
+        \points{2}
+      \item[(d)]
+        Schreiben Sie das Programm so um,
+        daß die durch das Programm dargestellte Figur spiegelverkehrt erscheint. \points{3}
+      \item[(e)]
+        Wozu dient das \lstinline{while (1)}? \points{2}
+      \item
+        Alle Antworten bitte mit Begründung.
+    \end{itemize}
+  \end{minipage}
+
+  \exercise{Einfügen in Strings}
+
+  Wir betrachten das folgende Programm (\gitfile{hp}{2021ws/20211115}{aufgabe-3.c}):
+%  \begin{lstlisting}[style=numbered]
+  \begin{lstlisting}
+    #include <stdio.h>
+    #include <string.h>
+
+    void insert_into_string (char src, char *target, int pos)
+    {
+      int len = strlen (target);
+      for (int i = pos; i < len; i++)
+        target[i+1] = target[i];
+      target[pos] = src;
+    }
+
+    int main (void)
+    {
+      char test[100] = "Hochshule Bochum";
+      insert_into_string ('c', test, 5);
+      printf ("%s\n", test);
+      return 0;
+    }
+  \end{lstlisting}
+  Die Ausgabe des Programms lautet:
+  \lstinline[style=terminal]{Hochschhhhhhhhhhh}
+
+  \begin{enumerate}[\quad(a)]
+    \item
+      Erklären Sie, wie die Ausgabe zustandekommt.
+      \points{3}
+%      \workspace{12}
+    \item
+      Schreiben Sie die Funktion \lstinline|insert_into_string()| so um,
+      daß sie den Buchstaben \lstinline{src} an der Stelle \lstinline{pos}
+      in den String \lstinline{target} einfügt.\par
+      Die Ausgabe des Programms müßte dann
+      \lstinline[style=terminal]{Hochschule Bochum} lauten.
+      \points{2}
+%      \workspace{13}
+    \item
+      Was kann passieren, wenn Sie die Zeile
+      \lstinline{char test[100] = "Hochshule Bochum";}\\
+      durch
+      \lstinline{char test[] = "Hochshule Bochum";} ersetzen?
+      Begründen Sie Ihre Antwort.
+      \points{2}
+%      \workspace{10}
+    \item
+      Was kann passieren, wenn Sie die Zeile
+      \lstinline{char test[100] = "Hochshule Bochum";}\\
+      durch
+      \lstinline{char *test = "Hochshule Bochum";} ersetzen?
+      Begründen Sie Ihre Antwort.
+      \points{2}
+%      \workspace{10}
+%    \item
+%      Schreiben Sie eine Funktion
+%      \lstinline{void insert_into_string_sorted (char src, char *target)},
+%      die voraussetzt, daß der String \lstinline{target} alphabetisch sortiert ist
+%      und den Buchstaben \lstinline{src} an der alphabetisch richtigen Stelle
+%      einfügt. Diese Funktion darf die bereits vorhandene Funktion
+%      \lstinline|insert_into_string()| aufrufen.\\
+%      \points{4}\par
+%      Zum Testen eignen sich die folgenden Zeilen im Hauptprogramm:
+%      \begin{lstlisting}[gobble=8]
+%        char test[100] = "";
+%        insert_into_string_sorted ('c', test);
+%        insert_into_string_sorted ('a', test);
+%        insert_into_string_sorted ('d', test);
+%        insert_into_string_sorted ('b', test);
+%      \end{lstlisting}
+%      Danach sollte \lstinline{test[]} die Zeichenfolge \lstinline{"abcd"} enthalten.
+%      \workspace{14}
+%    \item
+%      Wie schnell (Landau-Symbol in Abhängigkeit von der Länge $n$ des Strings)
+%      arbeitet Ihre Funktion
+%      \lstinline{void insert_into_string_sorted (char src, char *target)}
+%      und warum?
+%      \points{1}
+%      \workspace{10}
+%    \item
+%      Beschreiben Sie -- in Worten oder als C-Quelltext --, wie man die Funktion\\
+%      \lstinline{void insert_into_string_sorted (char src, char *target)}
+%      so gestalten kann,\\
+%      daß sie in $\mathcal{O}(\log n)$ arbeitet.
+%      \points{3}
+%      \workspace{35}
+  \end{enumerate}
+
+  \begin{flushright}
+    \textit{Viel Erfolg!}
+  \end{flushright}
+
+  \makeatletter
+    \immediate\write\@mainaux{\string\gdef\string\totalpoints{\arabic{points}}}
+  \makeatother
+
+\end{document}
diff --git a/20211115/io-ports-and-interrupts.pdf b/20211115/io-ports-and-interrupts.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..bcd46f7afb35605b20bdb05637e6de0a039893ec
--- /dev/null
+++ b/20211115/io-ports-and-interrupts.pdf
@@ -0,0 +1 @@
+../common/io-ports-and-interrupts.pdf
\ No newline at end of file
diff --git a/20211115/leds.jpg b/20211115/leds.jpg
new file mode 120000
index 0000000000000000000000000000000000000000..5e66b77c5c428129f6f4abcc80ae48f0c9a53c35
--- /dev/null
+++ b/20211115/leds.jpg
@@ -0,0 +1 @@
+../common/leds.jpg
\ No newline at end of file
diff --git a/20211115/loesung-3.c b/20211115/loesung-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..85abfcf3e1e4bacf454acd10f6832b757a64ac35
--- /dev/null
+++ b/20211115/loesung-3.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include <string.h>
+
+void insert_into_string (char src, char *target, int pos)
+{
+  int len = strlen (target);
+  for (int i = len; i >= pos; i--)
+    target[i + 1] = target[i];
+  target[pos] = src;
+}
+
+int main (void)
+{
+  char test[100] = "Hochshule Bochum";
+  insert_into_string ('c', test, 5);
+  printf ("%s\n", test);
+  return 0;
+}
diff --git a/20211115/logo-hochschule-bochum-cvh-text-v2.pdf b/20211115/logo-hochschule-bochum-cvh-text-v2.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..4aa99b8f81061aca6dcaf43eed2d9efef40555f8
--- /dev/null
+++ b/20211115/logo-hochschule-bochum-cvh-text-v2.pdf
@@ -0,0 +1 @@
+../common/logo-hochschule-bochum-cvh-text-v2.pdf
\ No newline at end of file
diff --git a/20211115/logo-hochschule-bochum.pdf b/20211115/logo-hochschule-bochum.pdf
new file mode 120000
index 0000000000000000000000000000000000000000..b6b9491e370e499c9276918182cdb82cb311bcd1
--- /dev/null
+++ b/20211115/logo-hochschule-bochum.pdf
@@ -0,0 +1 @@
+../common/logo-hochschule-bochum.pdf
\ No newline at end of file
diff --git a/20211115/pgscript.sty b/20211115/pgscript.sty
new file mode 120000
index 0000000000000000000000000000000000000000..95c888478c99ea7fda0fd11ccf669ae91be7178b
--- /dev/null
+++ b/20211115/pgscript.sty
@@ -0,0 +1 @@
+../common/pgscript.sty
\ No newline at end of file
diff --git a/20211115/pgslides.sty b/20211115/pgslides.sty
new file mode 120000
index 0000000000000000000000000000000000000000..5be1416f4216f076aa268901f52a15d775e43f64
--- /dev/null
+++ b/20211115/pgslides.sty
@@ -0,0 +1 @@
+../common/pgslides.sty
\ No newline at end of file
diff --git a/README.md b/README.md
index 303e60b0bd2da78bdb310474fd1ee9ee9ae216b9..0fdab69c32b1a9723c599b401766c4c8a0200cac 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,7 @@ Vortragsfolien und Beispiele:
  * [18.10.2021: Einführung in C: Arrays und Strings, Strukturen](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211018/hp-20211018.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2021ws/20211018/)
  * [25.10.2021: Einführung in C: Arrays und Strings und Zeichen, Strukturen, Dateien und Fehlerbehandlung](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211025/hp-20211025.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2021ws/20211025/)
  * [08.11.2021: Parameter des Hauptprogramms, String-Operationen, Bit-Operationen, I/O-Ports](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211108/hp-20211108.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2021ws/20211108/)
+ * [15.11.2021: I/O-Ports, Interrupts](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211115/hp-20211115.pdf) [**(Beispiele)**](https://gitlab.cvh-server.de/pgerwinski/hp/tree/2021ws/20211115/)
  * [alle in 1 Datei](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/hp-slides-2021ws.pdf)
 
 Übungsaufgaben:
@@ -31,6 +32,7 @@ Vortragsfolien und Beispiele:
  * [18.10.2021: Seltsame Programme, Kalender-Berechnung](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211018/hp-uebung-20211018.pdf)
  * [25.10.2021: Strings, Programm analysieren, fehlerhaftes Primzahl-Programm](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211025/hp-uebung-20211025.pdf)
  * [08.11.2021: Arrays mit Zahlen, Datum-Bibliothek](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211108/hp-uebung-20211108.pdf)
+ * [15.11.2021: Zahlensysteme, Mikrocontroller, Einfügen in Strings (Ergänzung)](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211115/hp-uebung-20211115.pdf)
 
 Musterlösungen:
 ---------------
@@ -38,10 +40,11 @@ Musterlösungen:
  * [18.10.2021: Seltsame Programme, Kalender-Berechnung](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211018/hp-musterloesung-20211018.pdf)
  * [25.10.2021: Strings, Programm analysieren, fehlerhaftes Primzahl-Programm](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211025/hp-musterloesung-20211025.pdf)
  * [08.11.2021: Arrays mit Zahlen, Datum-Bibliothek](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211108/hp-musterloesung-20211108.pdf)
+ * [15.11.2021: Zahlensysteme, Mikrocontroller, Einfügen in Strings](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211115/hp-musterloesung-20211115.pdf)
 
 Tafelbilder:
 ------------
- * [08.11.2021: Beispiele für Bit-Manipulation](https://gitlab.cvh-server.de/pgerwinski/hp/raw/2021ws/20211108/photo-20211108-172458.jpg)
+(keine)
 
 Praktikumsunterlagen:
 ---------------------
diff --git a/hp-slides-2021ws.pdf b/hp-slides-2021ws.pdf
index 049705c884b363245e198c6404a0218f5241d431..e6892010ce91be1cafd3621c238bcbaf11fff821 100644
Binary files a/hp-slides-2021ws.pdf and b/hp-slides-2021ws.pdf differ
diff --git a/hp-slides-2021ws.tex b/hp-slides-2021ws.tex
index f6723f56f017a470d18843c67c3ee2222b3b8bf1..cfd6bb634dd89821a8d4c9c39f78ae50fad24711 100644
--- a/hp-slides-2021ws.tex
+++ b/hp-slides-2021ws.tex
@@ -20,4 +20,6 @@
   \includepdf[pages=-]{20211025/hp-20211025.pdf}
   \pdfbookmark[1]{08.11.2021: Parameter des Hauptprogramms, String-Operationen, Bit-Operationen, I/O-Ports}{20211108}
   \includepdf[pages=-]{20211108/hp-20211108.pdf}
+  \pdfbookmark[1]{15.11.2021: I/O-Ports, Interrupts}{20211115}
+  \includepdf[pages=-]{20211115/hp-20211115.pdf}
 \end{document}