 So, ich würde jetzt erst mal gerne fragen, wer von euch ist ein Student? Einmal bitte kurz Handzeichen geben. Wer ist kein Student? Verdammt. Okay, stelle euch für einen kurzen Augenblick vor. Ihr seid fertig mit dem Studium. Ihr habt eure Bachelorarbeit geschrieben, vielleicht eure Masterarbeit. Oder Diplom. Manche studieren auch so lange, geht natürlich auch. Ihr habt einen neuen Job, einen richtig geilen Job. Ihr habt dem Lotto gewonnen, habt das richtig Geld, steht auf, schreibt nochmal eurem Kollegen, weil ihr macht eine Fahrgemeinschaft. Dann macht ihr Kaffee, ruft gleich nochmal eure E-Mails ab und steigt in euer Auto. Fahrt zum Kollegen. Ihr holt den Kollegen ab und fahrt zur Arbeit. So, jetzt denkt nochmal kurz drüber nach. Wie viele DSPs könnt ihr denn, mit wie vielen DSPs könnt ihr denn agiert haben? In etwa. Also ich frage jetzt mal von 0 bis 10, bitte Handzeichen. Okay, 2, 3, 4, von 10 bis 20. Okay, mehr als 20. Alles klar. Ich habe mir das gestern Nacht, als ich nicht schlafen konnte, habe ich mir das mal durchgerechnet und bin irgendwie auf 53, 54 DSPs gekommen. Weil ab dem Moment, in dem ihr in euer Auto steigt, habt ihr oder interagiert ihr unwissentlich mit 30, 40 DSPs die Fahrtenregulierung machen, die den Tempomat bedienen, die Zündung und so weiter steuern. Und das Schöne an den DSPs ist, ihr merkt es nicht. Sie tun einfach ihre Arbeit, ohne dass ihr es wisst, ohne dass ihr es bemerkt. Und das finde ich als Elektrotechniker eigentlich relativ schade, weil ich bin der Typ, der die Dinge designen. Ich bin der Typ, der die Dinge programmiert. Und meine Arbeit seht ihr einfach nicht. Sie funktioniert einfach. Dem entsprechend haben relativ wenige Leute Ahnung von DSPs. Es gibt Spezialisten auf dem Gebiet, aber die meisten haben schon mal von gehört. Einige haben es schon mal probiert. Andere haben es wieder hingeschmissen und haben einfach gesagt, das ist mir einfach zu komplex. Aber DSPs sind gar nicht so komplex. Und das versuche ich den Leuten immer und immer wieder, wenn sie fragen, hey, was machst du denn? Ich mache ein bisschen DSP, ein bisschen hier, ein bisschen funkamateur Zeug. Ich versuche es ihnen immer wieder und immer wieder zu erklären, DSPs sind nicht so hart wie sie klingen. Deswegen mache ich auch den Talk heute, um euch vielleicht ein bisschen zu motivieren, mit DSPs anzufangen oder vielleicht mal ein bisschen einzulesen in das Thema. So, für wen ist dieser Talk? Dieser Talk ist für euch. Dieser Talk ist für euch, wenn ihr interessiert seid, wenn ihr Lust habt, was zu lernen. Und dieser Talk ist eben nicht für euch, wenn ihr schon wisst, wie ein DSP funktioniert, was ein DSP ist, was ein DSP macht und vielleicht die Mathe ein bisschen dahinter versteht. Andere Spezies sind davon auch ausgeschlossen. So, was braucht man für DSPs? Ein bisschen E-Technik, wer vielleicht von Nöten immerhin arbeitet eben mit Signalen. Ich hatte den Talk ursprünglich auf 60 Folien gepusht und habe dann gestern 30 wieder rausgeschmissen. Dementsprechend ist dieses Slide in seinen Anforderungen relativ gesunken. Ihr braucht vielleicht ein bisschen Electrical Engineering Knowledge, also müsst wissen, wo Plus und Minus bei einer Batterie ist. Ein bisschen C sollte der können oder eine andere Programmiersprache. Es kommt nämlich genau ein Code-Sample vor, zwei. Und ein bisschen Mathe, weil DSP oder das Feld der digitalen Signalverarbeitung besteht auch aus ein bisschen Mathe. So, Integration, Summation und so weiter. Setz dich voraus, kann ich aber gerne noch mal erklären oder werde ich noch mal ein bisschen erklären. Also, warum wollen wir überhaupt DSPs benutzen? Wir hatten vorhin einen richtig genialen Vortrag über den Gitarrenbau von unserem Herrn Couchsurfer. Couchsurfer hat seine Gitarre gebaut, steckt die Gitarre jetzt ein und zieht, oh shit, oder hört oh shit, er hat irgendwo 50 Hertzbrummen oder 60 Hertzbrummen irgendein Stöcke-Räusch auf dem Gitarrensignal. Das heißt, wenn er spielt, hörst du irgendwo ein Brrrr, oder irgendwie sowas. Das ist eine Standardapplikation für ein DSP. Wie kann man das Ding lösen? Klar, wir legen einfach ein Filter drüber. Wie legen wir ein Filter drüber? Wir gucken einfach mal, wir nehmen mal an, er hat keine Ahnung von irgendwas. Guckt im Internet, sieht okay, Filter sind eigentlich relativ einfach. Wir haben eine Spannungsquelle, wir haben einen kleinen Widerstand und wir haben einen Kondensator. Kondensatoren sind Frequenzabhängigiewiderstände. Wie größer die Frequenz wird, desto kleiner wird der Widerstand und dementsprechend wird u0 kleiner. Das Signal, was rauskommt, wird halt kleiner mit größer werdender Frequenz. Okay, Couchsurfer denkt, jo, ist schon okay. Es reicht aber leider nicht, weil, ja, das Signal ist laut. Irgendjemand stört halt. Okay, was macht er? Er hängt nochmal zweiten Tiefpass dahinter. Er spielt seine Gitarre und denkt sich, ah, es klingt nicht so geil. Warum? Weil der zweite Tiefpass belastet den ersten Tiefpass und verändert dadurch wieder die komplette Charakteristik von dem ganzen Ding. Er sucht weiter und findet diese Schaltung. Das ist eine Standardschaltung für ein Tiefpass. Das sind einfach zwei Verstärker, die den einen Tiefpass vom anderen Tiefpass entkoppeln. So, ja, soweit, soweit ganz okay. Aber das Problem ist, es ist nur ein Channel und wir haben nur eine Frequenz und wir können einfach nichts einstellen. Gut, wir könnten mehr hinzufügen, mehr Bauteile. Das Problem ist, es wird relativ komplex. Das ist jetzt ein kleines Regelnetzwerk. Das ist ein kommerzielles Produkt. Das ist, wenn ich mich recht ins Sinne für zweischt oder für einstere Kornal eingang, bisschen Phasenregelung, bisschen Tiefen mitten und Höhen und am Ende noch die Lautstärke. Und wir sehen, es wird schon sehr komplex. Das Problem ist, was ich gerade gezeigt habe, kann wirklich nur die Funktion Tiefenregeln, die Höhenregeln und die Mittenregeln und hinten noch lauter und leiser machen. So, dementsprechend haben wir auch eine relativ festgelegte Funktionalität. Von USB brauchen wir eigentlich gar nichts zu träumen, falls wir da mal irgendwo digital aufnehmen müssen oder wiedergeben müssen oder irgendwas einspielen. Das können wir total vergessen. Dann haben wir ein Board, das ist dann irgendwie so groß. Klar, das funktioniert, wenn wir so ein Rack haben und da unsere Instrumente verstärken und so weiter einschieben können. Wenn wir allerdings ein portable Setup oder sowas haben, dann wollen wir das ganze auf diese Größe hier reduzieren und dann wird es halt schon relativ nervig, da das Platinlayout fürzumachen. Zudem haben wir relativ hohe Anforderungen an unsere Power Supply, an unsere Spannungsversorgung, weil alles, was wir hier am Power Supply an Rippeln haben, an Störungen haben, geht direkt in unser Signal ein. Zwar mit einem gewissen Faktor, aber es geht direkt ins Signal ein. Und wenn bei Analog einmal was versaut ist, dann ist es versaut. So, zum Beispiel Schallplatte. Wenn die Schallplatte irgendwo einen Sprung hat, man kann es nicht wieder reparieren. Deswegen können wir das ganze oder überlegen uns das ganze, machen wir es digital. Dadurch reduzieren wir im Prinzip die Komplexität und schieben alles, was wir haben, in die Software rein. Genauso wie beim Vortrag STR, Software Defined Radio, das macht oder das hat den gleichen Ansatz. Wir nehmen einfach diese ganze Komplexität von unserer Analogen-Elektronik und schieben es einfach in die Software. Die Software können wir ändern. Die Software können wir bearbeiten. Ja, und wir lösen uns einfach komplett von unserer Analogen-Elektronik. Ein paar Komponenten brauchen wir natürlich schon. Wir haben hier zum Beispiel den ADC. Ich habe hier jetzt mal 4 eingezeichnet. Das wäre zum Beispiel für 2 Stereokanäle gültig. Dieses Signal geht in den DSP. Der DSP macht da irgendwas mit. Und dann geht es wieder raus an den ADC, an den Digital Analogkonverter. So, unsere Couch-Sofa denkt sich jetzt zu. Ja, ist ganz cool. Aber was macht unser DSP eigentlich so speziell? Ohne weiteres Wissen schauen wir uns das jetzt mal an. Wir wollen möglichst viel Leistung. Also die brachialste Leistung, die wir kriegen können. Wie kriegen wir die? Entweder über eine hohe Clockrate oder über mehrere Kerne verteilt. Das ist der Ansatz, den wir gerade bei PC sehen. Wir haben 2, 4, 8, 16, 32, 128 Kerne. Wir wollen viel Speicher. Klar, könnt ihr mal irgendwo sein, dass wir irgendwo ein Filter speichern wollen oder ein größeres Programm oder sonst noch was. Was wollen wir noch? Wir müssen die Signale irgendwo rein und raus kriegen. Dementsprechend brauchen wir Interfaces. Interfaces für Audio, Reihen und Audio raus. Dann gibt es wieder so Chips, die haben den ADC und die DHC, also Analog, Digital und Digital Analogwandler, integriert. Rauchen wir das? Rauchen wir es nicht? Gibt es dafür spezielle Chips? Ja, die gibt es. Das heißt, eventuell brauchen wir dann noch einen weiteren Chip. Dann haben wir noch das Problem, nehmen wir jetzt fest Punkt oder Floating Point. Das wissen wir auch noch nicht so unbedingt. Und natürlich, das ganze Ding soll portable sein, soll von USB aus rennen. Dementsprechend muss das klein, leise und wenig Leistungsaufnahme haben. So, jetzt schauen wir uns den DSP kurz an. Wie sieht eine normale CPU aus? Eine normale CPU hat einen Rechenkern und hat Speicher. Das ist Standard. Wir nutzen momentan oder relativ häufig die von Neumann Architektur. Die von Neumann Architektur hat Eingabe, Ausgabe und Programmspeicher und Datenspeicher hintereinander. DSPs haben das teilweise auch, oft aber nicht. DSPs haben oben Programmspeicher und unten den Datenspeicher. Die trennen das also. Dann normale Rechner, normale Mikroprozessoren haben normalerweise einen Rechenkern, vielleicht sogar zwei. Was wir hier haben ist eine Aufteilung. Wir sehen hier L1, S1, M1 und D1. So, M sind Multiplikator, L ist die Logical Unit, S ist die Storage Unit, glaube ich, und D ist die Data Unit. Die erfüllen alle unterschiedliche Funktionen. Es sind alles ALUs, also arithmetischlogische Einheiten. Aber jede Einheit hat einen anderen Instruction Set. Die können ein bisschen was anderes. So, wie programmieren wir das Ganze? Das wird so programmiert, und zwar nehmen wir da, oder heißt das Ganze, Very Long Instruction Word. Normalerweise haben wir das so, dass wir eine Anweisung für die CPU haben und danach unsere Daten. Hier haben wir ganze acht Anweisungen, weil L1, M1, S1 und D1 haben wir und das Ganze haben wir nochmal gespiegelt. Das heißt, wir haben acht in Anführungszeichen Kerne, die wir füttern müssen. Und diese Kerne können alles parallel abarbeiten. Was wir hier tun im Gegensatz zur superscalaren Architektur, ist, wir reduzieren die Komplexität, die wir in unserem Chip auf dem Silikon selber haben und schieben die in den Compiler. Wir machen also genau das Gleiche, was wir auch vorher mit unserem Programm machen wollten. Wir lagen die ganze Hardware-Geschichten in die Software um. Warum tun wir das? Superscalare CPUs haben eine relativ lange Pipeline und entscheiden im Endeffekt aufgrund der Daten, die sie reinbekommen, was wird zuerst wie abgearbeitet und also parallel abgearbeitet. Was können wir parallel abarbeiten? Was können wir nicht parallel abarbeiten? In einem DSP-Regel ist normalerweise der Compiler, weil der Compiler zur Compile-Zeit schon weiß, okay, der Benutzer wird es so oder so machen. Es gibt mathematisch nicht unbedingt viele Möglichkeiten, wie wir da rumtrixen können. Da habe ich hier noch ein Beispiel für einen einen Assemblerbefehl angehängt. Diese Assemblerbefehl oder diese 8 Assemblerbefehle werden parallel abgearbeitet. Also so sieht im Endeffekt Assembler für ein DSP aus. Glücklicherweise haben wir mittlerweile gute Compiler und brauchen sowas nicht mehr zu schreiben. So, was haben wir noch bei einem DSP? Wir haben Multiplier Accumulate Einheiten. Es ist mathematisch so, dass wir oft Dinge multiplizieren müssen und dann addieren müssen, das Ergebnis addieren auf ein vorhergehendes Ergebnis. Dementsprechend haben wir dafür separate Hardware Einheiten. Die nennen sich eben MAC, also Multiplier Accumulate. Und es funktioniert im Prinzip so, dass wir die normalen Floating-Point-Instuktion in die Hardware-Unit-Auslagen. Das heißt, wir haben im Endeffekt ein Assemblerbefehl Multiplier und Accumulate, der wird dann in zwei Glockzickeln ausgeführt. Mehr müssen wir uns gar nicht kümmern. Diese Multiplier Accumulate Einheiten haben auch eine Spezialität oder sind ein bisschen speziell. Das Ergebnisregister ist brutal lang, das werden wir nachher auch sehen, warum. Und wenn wir zum Beispiel Nullix FF da dringeladen oder reingeladen haben, also das Ding maximal voll machen, wir addieren noch eins dazu. Was passiert bei einem normalen Register? Das Ding geht voll ins negative. Also wir haben einen Überlauf im Endeffekt. Was diese Multiplier Accumulate Register tun, ist einfach sie klippen. Das heißt, sie bleiben zum Beispiel bei Nullix FF in dem Beispiel. So, dann haben wir noch den Direkt-Memory-Access, das ist ein kleiner Co-Prozessor, der darauf spezialisiert ist, Daten von einem Speichelbereich in den anderen Speichelbereich zu laden. Warum? Überlegt euch, ihr seid auf einem normalen Rechner und ihr kopiert eine Datei. Solange ihr kopiert, könnt ihr nichts anderes tun. Würdet ihr eine Rechner kaufen? Nein, würdet ihr nicht. Ihr kopiert die Datei dadurch, dass ihr im Endeffekt einen DMA-Transfer anstößt und der dem Co-Prozessor sagt, okay, ich habe hier eine Datei von der bis zu der Memory Section, kopiere mir die mal in den Speicher. Und der Co-Prozessor macht das und befreit dadurch die CPU von irgendwelchen lästigen Kopiervorgängen. Macht Sinn, sehen wir später auch warum. DSPs haben außerdem noch ein Event-System, das relativ ausgeprägt ist. In normalen CPUs haben wir Interrupt-Systeme. So, Interrupt ist eine Ahnung, das USB-Device wird eingesteckt und der USB-Controller generiert ein Interrupt. So, hello, hey, neues USB-Device eingesteckt. So, man muss sich die CPU drum kümmern. Was ist aber, wenn sich die CPU gar nicht drum kümmern müsste? Eigentlich. Was wäre, wenn jetzt zum Beispiel das USB-Device eingesteckt werden würde und irgendeine andere Hardware-Einheit könnte es sich drum kümmern? Dafür ist dieses Event-System da. Events sind im Endeffekt Interrupts, die die CPU nicht betreffen. Also es gibt Interrupts und es gibt Events. Interrupts können von jeder Peripherie abgefeuert werden und die betreffen die CPU. Also da geht die CPU, sagt die CPU, ja, hier ausführung halten und ich muss mich jetzt um diesen Interrupt kümmern. Events gehen die CPU komplett nichts an. Also Events werden zum Beispiel von der seriellen Schnittstelle zu einer anderen seriellen Schnittstelle oder von der seriellen Schnittstelle zur DMA gefeuert und die DMA weiß dann, oh, ich solle dies das dort jenes tun. So, weiterhin haben wir die Kommunikationsschnittstelle mit Außenwelt. Da ist I2S relativ groß. I2S ist das Inter-IC-Sound. Das ist ein Standard der von, Gott weiß wem, irgendein großen Philips, der dann von Philips irgendwann mal aufgesetzt wurde. Da hat man normalerweise drei Datenleitungen. Das ist ein unidirektionaler Bus. Man hat normalerweise drei Datenleitungen. Einmal den Bit-Clock, einmal den Left-Right-Clock und einmal den Data-Line. So, der Bit-Clock ist synchron mit der Daten, mit der Data-Line. Da werden die Daten übertragen und der Left-Right-Clock sagt einfach nur, wenn er high ist, wer die linke Seite, also audiomäßig jetzt, der linke Kanal übertragen. Wenn es auf low geht, wird der rechte Kanal übertragen. So, das ganze kann man natürlich auch übertreiben und sagen, hey, warum brauche ich drei Lines für ein Stereosignal? Ich könnte drei Lines für X-Stereosignale nehmen. Da waren dann die Mac-BSP und Mac-ASP. Das sind die Multi-Channel, die Multi-Channel-I2S Kanäle oder Hardware-Einheiten, die dann im Endeffekt nichts anderes tun als parallel Daten entgegennehmen und dann serial rauszuschieben. Und dadurch kann man eben Streams multiplexen. Das heißt, man hat da nur drei Leitungen und diese drei Leitungen können dann acht Channel gleichzeitig übertragen, gleichzeitig. So, was wir vorher gesehen haben, war das ganze für zwei Kanäle. Das, was wir hier sehen, ist im Endeffekt, das große ist der DSP und die zwei kleineren Einheiten hier, das sind Codecs. Codecs beinhalten digital Analogkonverte und Analog-Digitalranter. Jeder dieser Codecs hat vier Eingänge und acht Ausgänge. Zusammen sind es also vier Stereo-Eingänge und acht Stereo-Ausgänge. Um das Analog zu realisieren, brauchen wir eine Menge, Menge an Hardware. Aber schauen wir uns erstmal an, wie das ganze Ding denn innen aussieht. Und da halte ich gern am Hackers Approach fest. Wenn ich ein Arduino bekomme, was ist das Erste, was ich implementiere? Ich lasse eine LED blinken. Was ist das Zweite, was ich implementiere? Ich lasse eine LED ein- und ausfälligen. Was ist das Dritte, was ich implementiere? Welterschaft. Genauso mache ich das auch mit dem DSP. Die meisten Codecs haben ein In-Codec-Pass-through. Dementsprechend, was reinkommt, geht direkt wieder raus. Der Codec muss aber vom DSP parametrisiert werden. Was ich also tue, ist erstmal eine Verbindung in den Codec rein und vom Codec direkt wieder raus zu schaffen. Damit verifiziere ich, dass die Kommunikation zwischen Codec und DSP funktioniert. Was ich als nächstes machen möchte, ist, ich möchte die Daten in den DSP reinbekommen. Um die Daten reinzubekommen, muss ich die Multi-Channel, also MAC-BSP, MAC-ASP oder die I2S-Schnittstelle zum Funktionieren bringen. Die muss ich natürlich auch parametrisieren und dementsprechend gehe ich kleine Schritte von nur Codec, dann nur Codec bzw. Codec in die CPU. Dann weiß ich, okay, ich habe meine Schnittstelle schon fertig parametrisiert und sie läuft. Dann schaue ich, dass ich das Interrupt-System zum Laufen bringen. Das Interrupt-System bei DSPs kann durchaus sehr verwirrend sein. Es gibt verschiedene Interrupt-Prioritäten, die je nach dem, welcher Interrupt, wo, wann gefeuert wurde, entweder funktionieren oder nicht. Meistens eben nicht. Das ist das Problem. Dementsprechend langsam aufbauen. Das Problem, was wir bis jetzt haben, ist, wir kriegen ein Sample rein, generieren den Interrupt, so, hey, da ist ein Sample. Was machen wir jetzt damit? Das dritte Schaubild sagt, okay, wir kopieren es einfach oder die CPU kopiert es einfach wieder raus. Das heißt, wir nehmen das Ding und kopieren es einfach wieder raus. Vorher hatten wir aber das Problem oder habe ich es angesprochen, dass wir, wenn wir Dateien kopieren, da haben wir das Problem, dass die CPU in der Zeit nichts machen kann. Also müssen wir das ganze auslagern und dann landen wir da. Was wir im Endeffekt tun ist, wir holen uns die Daten vom ADC. Die Peripherie im DSP sagt, hey, da ist ein neues Sample. Aber als Event nicht als Interrupt. Das heißt, die CPU kriegt davon absolut nichts mit. Die DMA nimmt sich dem Ganzen an. Die DMA sagt, oh, okay, ich nehme dieses Sample von dieser Peripherie und schiebe es in ein Speicher. Inkrementiere meinen Zähler. Und es geht eben so lange bis dieser Speicher voll ist. Der Speicher ist hier als blaue, als von der blaue Box eingezeichnet. Die zwei runden Dinger sollen Ringspeicher symbolisieren. So, und irgendwann ist dieser Speicher voll. Was machen wir dann, wenn dieser Speicher voll ist? Wir sagen die DMA, sagt der CPU, hey du, Speicher ist voll, mach mal was mit. Und da kommt unser Algorithmus ins Spiel. Dann sagt die CPU, okay, ich muss jetzt eh was berechnen. Also können wir doch die ganzen Daten vom Eingangssample Puffer in den Ausgangssample Puffer schieben und dabei gleich bearbeiten. Das heißt, wir verlieren im Endeffekt keine Rechenzeit. So, jetzt haben wir die Sache, was macht die CPU in der Zwischenzeit? Wir können es einerseits statisch programmieren oder einen eigenen Scheduler aufsetzen. Das Einfachste ist allerdings, wenn wir das AirTos nehmen, das Real-Time-Operating-System, fast jeder DSP-Hersteller entwickelt ein Real-Time-Operating-System, ganz einfach, um diese ganzen Real-Time-Conditions zu managen. Normalerweise macht man das so, dass die DMA einen Interrupt generiert. Dieser Interrupt ist ein Hardware-Interrupt. Was macht der Hardware-Interrupt? Der Hardware-Interrupt stoppt die CPU komplett. Die CPU springt dann zu der Kotstelle, die sie im Hardware-Interrupt ausführen muss. Was machen wir da als Programmierer? Wir setzen im Endeffekt einfach nur ein Flag. So, hey, mach mal ein Software-Interrupt. Ein Software-Interrupt ist im Endeffekt ein Interrupt vom Real-Time-Operating-System, der in der Priorität über den Tasks liegt. Das heißt, die normalen Operationen, wie, keine Ahnung, Display-Updaten oder lauter Leisermachen, irgendwie ein Coderabfragen, die werden über die Tasks erledigt und die Software-Interrupt-Routine, da ist dann unser Algorithmus drin. Weil die Software-Interrupt-Routine wird dann sofort ausgeführt, wenn der Hardware-Interrupt durchgelaufen ist. So, jetzt wissen wir theoretisch, wie es geht. Dann haben wir noch ein paar Probleme. Und zwar, Nicklist hat damals gesagt, wir müssen immer mit der doppelten Frequenz abtasten, mit der wir maximal hören wollen. Ich habe es versucht, zu umgehen. Es klingt scheiße. Es klingt extrem scheiße, weil wir haben dadurch Unterabtastung und wir kriegen nicht nur Rauschen drauf, wir kriegen im Endeffekt auch noch Teile unseres Signals gespiegelt wieder auf unser Signal. Das hört sich absolut beschissen an. Dann müssen wir noch ein Trade-off finden zwischen dem Workload der CPU und dem Delay. Wir haben ja Input-Puffer. Und es ist relativ ineffizient, wenn wir die CPU jedes Sample nehmen lassen und durch unseren Filter jagen. Es ist relativ bescheiden, weil wir jedes Mal in Interrupt springen müssen und da verlieren wir Clock-Zyklen oder Tag-Zyklen, weil die CPU muss Register speichern, irgendwo auf dem Stack speichern. Dann muss die den Algorithmus ausführen und dann muss die die Registe wiederholen. Es macht also Sinn, unsere Samples als Block zu bearbeiten. Dadurch wird der Aufwand dieses Pushens auf dem Stack pushen und wieder vom Stack poppen relativ klein im Gegensatz zu unserem Algorithmus. Da müssen wir allerdings je nach Applikationen schauen, okay, wir haben jetzt eine Gitarre und wir schlagen das Seite an. Wann wollen wir das Ergebnis hören, möglichst sofort? Wenn wir das Ding möglichst sofort hören wollen, müssen wir unseren Puffer klein machen. Wenn wir aber unseren Puffer klein machen, erhöhen wir die Workload der CPU, weil sie immer öfter für weniger Samples in diese Interrupt-Service-Routine springen muss. Machen wir allerdings den Puffer größer, kriegt unser Bassist oder unser Instrumentenspieler ein Problem, weil es schlägt die Seite an und er hört erst mal 10 Millisekunden nichts, wenn der Puffer zu groß ist. Normalerweise, wenn ihr Musik hört, ist es kein Problem, weil wenn ihr Musik-Server spielt, ist es ein Riesenproblem, wenn ihr irgendwas tut und dann 10 Millisekunden, 20 Millisekunden später kommt erst die Reaktion. Das kann sehr, sehr stören werden. Dementsprechend muss man da einen Trade-off finden. Typischerweise ist der Puffer 1024 Sample groß, 2048 Sample groß, je nachdem welche Abtastrate man hat. Wenn ich mir überleg, ich habe jetzt 48 Kilo Abtastrate und mache den Puffer 1024 Samples groß und verdoppelt die Abtastrate, dann ist der Puffer auch doppelt so schnell voll. So, jetzt hatten wir vorher noch das Problem, ja, nehmen wir eigentlich Floating Point oder Fix Point. Heutige DSPs können eigentlich beides. Früher war das ein ganz großes Problem. Paar DSPs konnten nur Fix Pointen, Paar DSPs konnten nur Floating Point. Heutzutage sind die Kosten so gering, man kann eine CPU für, eine Ahnung, 10, 12 Cent als Silicon Chip, also als Silikon bestellen, als Silizium Chip, sorry. Und die packen man einfach nur auf seinen Chip und vergieste. Früher hatten DSPs, der Fix Point konnte 30, 40 Euro gekostet. Einer der Floating Point konnte, hat dann so, dass das gleiche in Floating Point konnte, hat dann irgendwie so 70, 80, 100, 120 Euro gekostet. So, jetzt wissen wir theoretisch alle so bei DSPs, was es zu wissen gibt. Die wichtigen Dinge zumindest. Wie implementieren wir das jetzt? Um zur Implementation zu gehen, wollt ihr ein bisschen was über Signale wissen? Es ist Mate, klar. Es sieht auch sehr scary aus. Ist es aber im Endeffekt nicht. Was da steht ist, ein Signal setzt sich aus Sinus und Cosinus zusammen. Wir können jedes periodische Signal und das sind unsere Audiodaten auch aus einem Sinus und einem Cosinusbestimm zusammensetzen, die jeweils mit den entsprechenden Koeffizienten gewichtet sind. So, für schnelle Signale brauchen wir dann natürlich mehr Sinus und Cosinus als für langsame Signale. Die Koeffizienten sehen wir hier A0, Ak und Bk. Das sind eben unsere Koeffizienten, die dann je nach dem, was für ein Signal wir haben, größer oder kleiner sind. Und die Summe darüber, das ist das Zeichen da vorne, die Summe darüber gibt uns dann unser eigentliches Signal an. So, wenn wir jetzt ein Signal filtern, was tun wir? Wenn wir über lineare Systeme reden, machen wir nichts anderes und unsere Filter sind lineare Systeme, machen wir nichts anderes als die Koeffizienten vorne verändern. Also Ak machen wir ein bisschen größer, also Ak1 machen wir ein bisschen größer, Bk1 machen wir ein bisschen kleiner, Ak2 machen wir ein bisschen kleiner und Bk2 machen wir ein bisschen größer. Und dadurch verändert sich im Endeffekt unsere Signalform komplett. Es gibt einen Tipp von Signal, um das wir uns eigentlich gar nicht kümmern, weil das für uns keine sinnvolle Information enthält. Und das ist hier in der Summe A0, das ist der gleiche Anteil und jeder Musiker oder jeder, der schon mal einen gleiche Anteil auf seinem Klinkenstecker hatte, weiß, wie nervig es ist, wenn man es einsteckt und dann erstmal aus dem Lautsprecher ein richtiges Boom kommt. Das heißt, das können wir getrost ignorieren. Aber es gibt zwei Typen von Signal, die wir benötigen, um unsere Systeme zu charakterisieren. Und das ist einmal der Impuls und das andere ist der Sprung. Das sind die beiden Wichtigsten, die wir haben. So, wie definiert man eine Sprungfunktion? Wir sagen einfach, hey, wir haben ein Signal oder unsere Funktion, unsere Funktion ist das Signal und das Signal ist solange 0 bis T zu 0 wird. Und für T größer 0 geht das Signal einfach auf 1. So, das war es im Endeffekt. Das ist die Definition unserer Sprungfunktion. Damit haben wir schon mal die wichtige Hälfte abgedeckt. Jetzt gehen wir zu der Impulsfunktion, die ist ein bisschen komplizierter. Mehr Mathe, aber eigentlich auch nicht so schwer. Was wir hier tun, ist nichts anderes, als wir definieren unsere Impulsfunktion als die Summe von zwei Sprüngen. Und zwar einmal gehen wir Sprung und dann ziehen wir davon ein Sprung wieder ab. Dementsprechend haben wir nichts anderes als ein Rechteck. Was wir jetzt noch tun müssen, ist dieses Rechteck, so lange zusammenquetschen, also Better, in diesem Fall kleiner und kleiner und kleiner zu machen, um zu unserem Sprung zu kommen. Wenn wir Better allerdings kleiner und kleiner und kleiner machen, dann wird unser Sprung höher und höher und höher. Womit wir im Endeffekt landen, ist nichts anderes als ein unendlich schmale Signal, das unendlich hoch ist. Wie schaut das denn ein ganzes Ding aus? Das ganze Ding schaut so aus. Ich habe es jetzt verschoben, weil normalerweise wäre das Signal direkt auf T gleich 0 und damit würden sich die beiden Pfeile überlagern, was nicht so toll ist. So, warum brauchen wir diesen Mist eigentlich? Wenn wir einen Impuls auf einen System geben, der Impuls ist so kurz, wirklich so kurz, dass wir im Endeffekt theoretisch kaum sehen, dann antwortet das System mit einer Impulsantwort. Diese Impulsantwort charakterisiert das System komplett. Was wir also haben, ist die Impulsantwort auf einen Impuls, die das System komplett charakterisiert. Was haben wir aber, wenn wir ein digitales Signal haben? Ein digitales Signal ist nichts anderes als eine abgetastete Reihe von Impulsen. So, wenn wir hier jetzt ein Sinus haben und diesen Sinus abtasten, landen wir einfach bei einem Sinus mal Impuls um die Zeit verschoben. Also im Endeffekt Impuls, Impuls, Impuls, Impuls, Impuls, Impuls, Impuls, Impuls und immer so weiter. Das passiert mit jedem Audiosignal, dass wir abtasten. Und was machen wir jetzt einfach? Wir schieben das Signal durch unser System. Und was machen wir damit? Wir schieben im Endeffekt eine gewichtete Summe von Impulsen durch das System. Also Impuls 1, plus Impuls 2, plus Impuls 3, plus Impuls 4. Und unser System wird auf jeden Puls mit der entsprechenden gewichteten Impuls Antwort antworten. Das heißt, wenn wir ein kleines Signal, einen kleinen Impuls reinschieben, kriegen wir auch eine kleine Antwort dazu. Wenn wir ein großes Signal reinschieben bzw. einen großen Impuls, kriegen wir auch eine große Antwort dazu. Wenn wir das Ganze addieren, haben wir unser gefiltertes Signal. So, die mathematische Operation dazu ist die Filterung. Das sieht wieder sehr komplex aus. Im Endeffekt ist es aber nicht komplex. Was wir hier haben ist oben unser Signal Xn, unsere Samples. Die werden dann, wenn wir zum Beispiel das sieht aus wie das sechste Sample, wenn wir das sechste Sample hier berechnen wollen, müssen wir das fünfte, das vierte, das dritte, fünfte, vierte und dritte Sample nehmen, mit der entsprechenden Impuls Antwort multiplizieren und das alles addieren und dann haben wir das Sample, unser Ausgangssample. Jetzt sieht man auch, warum diese Multiplier Accumulate Peripherie so wichtig ist. Was wir hier haben ist nichts anderes als Multiplikation, Addition, Multiplikation, Addition, Multiplikation, Addition und das eben oft hintereinander. Und hier haben wir im Endeffekt vier Multiplikation und Addition für ein Sample. Gehen wir aufs nächste Sample, aber wieder vier Multiplikation und vier Addition. Deswegen müssen wir gucken, dass wir diese Multiplikation und Addition relativ schnell von statt, dass diese Multiplikation und Addition relativ schnell von statt geht. So, das war im Endeffekt die Faltung. Mit dieser Faltung können wir jetzt Filter oder Signale filtern. Oben steht wieder eine Summe, also aber nichts anderes ist als das, was wir gerade getan haben. Wir nehmen das Sample N, das ist unser Signal, X von N ist unser Signal. Für das Endesample brauchen wir das Endesample, multiplizieren es mit dem entsprechenden Kofizenten plus das N-1-Sample und multipliziert mit dem entsprechenden Kofizenten. Und je nachdem, wie lang unser Filter ist, müssen wir im Endeffekt das ganze länger aufziehen oder können es kürzer machen. Unten ist es in C nochmal geschrieben, es ist im Endeffekt einfach nur zwei Vorschleifen. Wir itirieren die äußere Vorschleife einmal über unseren kompletten Sample Puffer und die Innere itiriert im Endeffekt über jeden Kofizenten. Einmal. Und das ist im Endeffekt auch unser Filter. Das ist die ganze Magie der Signalverarbeitung. Nicht ganz, aber einiges davon. Was wir hier aufgebaut haben, ist ein FR-Filter. Dieser FR-Filter ist ein ausgeschrieben Finite Impulse Response Filter. Unsere Impulse Antwort ist hier endlich. Das heißt, wenn wir den Filter aufbauen, hört unsere Impulse Antwort irgendwann auf, wird es zu Null. Dementsprechend haben wir eine entsprechende Länge unseres Filters. Das ist immer stabil. FR-Filters sind immer stabil. Warum? Wenn unsere Impulse Antwort irgendwann Null wird, addieren wir immer Null, Null, Null auf unser Signal. Das heißt, irgendwann sind die Kofizenten einfach Null und dann addieren wir einfach Null dazu. Null mal irgendwas gibt Null. So, sie sind relativ einfach. Es sind zwei Vorschleifen, also nicht unbedingt komplex. Es gibt welche, die haben Feedback. Dieses Feedback ist aber so speziell angelegt, dass wir immer stabile Filter haben. Was nicht so ist bei den IER-Filtern. Die IER-Filter, die Infinite Impulse Response, die haben eine Impulse Antwort, die geht unendlich lang. Das heißt, wenn wir jetzt filtern wollten, müssen wir unendlich lange filtern, bis wir irgendwann mal das erste Sample kriegen. Ist technisch nicht möglich. Deswegen schnappen wir uns einfach ein Feedback Loop, nehmen unsere Ergebnisse und schieben die wieder an den Eingang zurück. Es ist natürlich auch mathematisch definiert. Das Problem ist, diese Filter können schwingen. Warum können diese Filter schwingen? Ganz einfach, wenn ihr eine 1 in Eingang schiebt und diese 1 multipliziert mit 1,5 und dieses Ergebnis wieder zurück an den Eingang schiebt und ihr multipliziert das nochmal mit 1,5, dann schwingt dieser Filter sich irgendwann auf. Dementsprechend sind diese Filter manchmal stabil, manchmal nicht stabil. Wir Ingenieure schauen, dass wir die Filter stabil hinkriegen, sonst gibt es Probleme. Zum Beispiel Systeme, die sich selber zerstören, Brücken, die sich zerstören und so weiter und so fort. So, jetzt haben wir die Filter. Jetzt schauen wir nochmal, wie können wir diese Filter berechnen? Ich will euch jetzt nicht mit der Matte quälen. Dafür gibt Matlab. Matlab kennt ein FDA Tool, das sich jetzt wieder auf dem anderen Monitor geöffnet hat. Wunderbar. Dieses FDA Tool hilft uns, unsere Filter zu bestimmen. Nehmen wir mal an, wir haben, wir spielen Bass. Unser Bass geht bis ungefähr 400 Hertz. Tragen wir hier im Passband 400 Hertz ein. Wenn ich tippen könnte, würden auch 400 Hertz stehen. Das Passband ist im Endeffekt hier oben, da, wo unser Filter dann so langsam abfallen möchte, sollte. Unsere Störungen können wir 12.000 Hertz lassen. Kann aber auch sein, dass unsere Störung auf 15.000 Hertz liegt. Tragen wir hier 15.000 Hertz ein. Wir wollen 80 dB Attenuation, 80 dB sind eine Menge, 80 dB sind schon fast nicht mehr höher. Und dann klicken wir einfach auf Design Filter. Wartende Weile kriegen dann hier unseren Filter. Das ist im Endeffekt unsere Frequenzantwort. Unsere Frequenz oder unsere Amplitude über die Frequenz fällt langsam ab, langsam ab, langsam ab und wird irgendwann zu eben minus 80 dB. Das ist das, was Sie wollten. Aber unsere Frequenz oder unsere Amplitudengang hilft uns nicht unbedingt weiter. Was wir wollen, ist unsere Impulse Antwort. Da klicken wir einfach auf unsere Impulse Antwort und kriegen unsere Koeffizienten. Das ist im Endeffekt das System oder diese Koeffizienten, diese 1, 2, 3, 4, 5, 6 Koeffizienten, mit denen wir unser Signal falten müssen, um einen Filter zu realisieren, der eben hier bis 400 Hertz gut durchlässig ist und dann ab 400 Hertz anfängt abzufallen und ab 15.000 Hertz einfach nichts mehr durchlässt. So, na, jetzt, so, damit haben wir unseren Filterkörner. Warum sind DSPs jetzt noch mal so komplex? Ihr habt es garantiert gemerkt. Es kam Mathe dazu, es kam ein bisschen Hardware dazu, es kam Software dazu. In allen drei Feldern muss man eine gewisse Ahnung haben, um wirklich im DSP-Bereich was reisen zu können. Dann hat man das Problem, embedded Systems sind wirklich hart zu debacken. Wenn ich ein Signal in meinen DSP-Bord reinschieb und rauskommt, nur rauschen, woran liegt es jetzt, liegt es an der DMA, liegt es an meinem Algorithmus, liegt es an der Mathe dahinter, habe ich irgendwo nur Mist gebaut oder habe ich irgendwo nur Samples irgendwo vergessen. Arrow-Messages gibt es beim Compile, gibt es aber leider nicht in der Inbetrieb. Und wir haben kontinuierliche Signale. Was bedeutet? Stoppen ist nicht. Das heißt, wir müssen weiterlaufen lassen und wir müssen halt gucken, okay, wo könnte dieses Arrow herkommen und dann Arrowquellen nach und nach und nach eliminieren. Zudem müssen wir noch gucken, ja, wo fangen wir eigentlich an, fangen wir jetzt mit der Mathe an oder fangen wir mit der Software an oder wie wo war es, weil das eine hängt vom anderen ab und so weiter und so fort. Unsere Abtastfrequenz hängt zum Beispiel von unserer Buffergröße ab, unsere Buffergröße hängt von der Taktgeschwindigkeit der CPU ab und so weiter und so fort. Vielleicht haben wir noch Codecs, die die entsprechende Taktrate nicht können. Wer weiß. Das Problem ist, ich kann euch hier leider keine klaren Antworten geben, weil jedes DSP-System ist einzigartig. Wenn ich einen Design für ein Audiofilter, oder wenn ich ein Audiofilter Design, hatte andere Parameter als wenn ich einen Design für zum Beispiel ein Software Define Radio mache. Beim einen habe ich eine relativ hohe Auflösung, beim Audio habe ich eine relativ hohe Auflösung, weil ich einen großen Dynamikbereich möchte, aber dafür eine niedrige Bitrate oder eine niedrige Sample Rate. Bei einem Software Define Radio zum Beispiel habe ich eine geringere Auflösung, weil ich da nicht so viel Dynamik brauche, aber dafür muss ich sehr, sehr, sehr, sehr, sehr viel schneller abtasten, damit ich brauchbare Signale kriege. Und im Endeffekt hängt es wirklich davon ab, wo, womit ich anfange, mit welchen Startparameter ich anfange. Damit bin ich erst mal am Ende meines Vortrags. Es gibt Ressourcen, zum Beispiel dieses Buch hier. Da habe ich relativ viel gelernt. Ihr könnt es euch nachher gerne mal angucken. Will keine Werbung für machen, also ein gutes Buch. Es ist meines Wissens auch frei und netzverfügbar. Können wir euch runterladen. Weitere Ressourcen ist so eine Sache. Im Internet gibt es einiges dazu. Das Problem ist, allerdings die Nomenklatur ist immer anders. Manche nutzen Omega, manche nutzen S, manche nutzen P für gewisse Dinge, beziehungsweise für die gleiche Variable. Dementsprechend kann ich da auch nicht mehr empfehlen. Bücher sind generell immer gut, so wenn man das Buch von vorne bis hinten durchliest. Ja, das ist ein Muss, weil wenn man zwischen zwei, drei Büchern switcht, hat man eben das Problem, dass es wirklich auch wieder beim einen S heißt, beim anderen T. Es ist nervig. So, da habe ich mal vier Kits rausgesucht, mit denen ihr anfangen könntet. Der einfache Weg ist das EZ-DSP von Texas Instruments. Da ist ein DSP drauf, da ist ein Codec drauf. Im Endeffekt ist es eine Plug-and-Play-Lösung. Ihr steckt das Ding ein, installiert die Software. Nachdem ihr die Software installiert habt, könnt ihr direkt mit einem Filter-Generierung anfangen. Es läuft. Dann haben wir noch den harten Weg, der ist für die Hardware-Bustler. Von Texas Instruments gibt es auch ein Launchpad. Das ist ein Cortex-M4 Mikrocontroller mit einer Floating-Point-Unit. Das ist kein DSP. Der Mikrocontroller hat eine DMA, hat aber keine genauen Digital- und Analog-Digitalwandler. Hat auch kein I2S, also Inter-IC Audio oder Inter-IC Sound. Dementsprechend müsstet ihr das alles zusammenbasteln. Ist allerdings im Preis und schlagbar günstig. Dann gibt es noch den russischen Weg, den Brutforce-Weg. Wir schmeißen einfach Geld aufs Problem, zahlen 500 Euro und holen uns ein richtiges DSP-Startup-Kit. Dann gibt es noch den komplett günstigen Weg. Wir schauen erst mal, dass wir unsere Real-Time-Conditions über Bord schmeißen und unsere Filter erst mal auf Matlab oder sonstiges implementieren und dann später auf ein DSP gehen oder auf einen normalen Mikrocontroller. So, hier wäre ich am Ende vom Vortrag. Ich danke erst mal für die Aufmerksamkeit und wenn Fragen sind, ist Ihnen garantiert einige Fragen. Mögt ihr jetzt bitte stellen. Vielen Dank. Den Talk werde ich noch weiter ausbauen. Da ist die URL dafür, macht einfach ein Foto. Der war mal 60 Seiten lang. Habe ich gestern Abend noch schnell kürzen dürfen, müssen, wollen. Er wird wieder länger. So, Fragen. Moment, Mikro kommt. Ja, hallo. Ich kenne mich ein bisschen mit PIC32 aus. Was ist in der Unterschied zwischen PIC32 und einem richtigen DSP? Die Grenzen verschwimmen in letzter Zeit. Früher gab es DSPs und Mikrocontrollers. Der PIC hat garantiert auch eine DMA. Der PIC kann aber wahrscheinlich nicht die Floating-Point-Zahlen in einem oder zwei Taktzyklen multiplizieren und dann addieren. Dementsprechend dauert diese Multiplikation und Addition länger und damit dauert auch diese gesamte Filterberechnung länger. Und das ist eben der Nachteil vom PIC. Es gibt sogenannte DSPs, die digitale Signal-PIC-Prozessoren. Die können dann wieder relativ schnell diese Multiplikation und Addition ausführen und sind dementsprechend schneller. So, weitere Fragen? Da hinten. Hi. Bei dem Matlab-Filter, den du gezeigt hast, da hatte die Kurve hinterher nochmal so zwei PICs, jetzt als den 15 Kilo Hertz. Was machen die? Du kannst einen Filter bis zu einer gewissen Steigung so designen, dass diese Rippel da hinten nicht mehr vorhanden sind. Aber ab einer gewissen Steigung, also ab einem gewissen Abfall, hast du das Problem, dass du unweigentlich durch die Mathematik begründet Rippel hinten reinkriegst. Die kannst du entweder nach oben ins sogenannte Passband verschieben oder im Stopband lassen. Wenn du die Dinge ins Passband schiebst, dann hörst du das im Endeffekt. Du versuchst natürlich die Rippel klein zu halten. Wenn du sie in den Stopband verschiebst, ist es im Endeffekt egal. Es sind Artifakte der Mathematik, die du da hast. Kriegst du auch nicht weg. Also du kriegst die mit speziellen Methoden weg, aber da wird dann halt die rechte Rechenaufwand riesig. Sie sind halt einfach da und wir müssen mit ihnen leben. Hat noch jemand eine Frage? Gut, scheint nicht so. Dann möchte ich mich für eure Aufmerksamkeit bedanken und habe noch eine schöne GPN. Dankeschön.