Hallo,
ich suche eine Möglichkeit ein I2S Signal mit einem AVR Mega88
einzulesen.
Ich will nur den Signalpegel auswerten und über LEDs anzeigen.
Gibt es eine Möglichkeit, ausser die Pin's abzupollen?
Also sowas wie SPI, SIO in irgend einem Modus oder sonst eine Hardware
unterstützung?
Viele Grüsse,
Peter
Glaube das wird nicht gehen.
Der M88 kann doch nur mit 24MHz arbeiten und SPI braucht schon >4 Takte
um was zu empfangen. Pollen wird auch nicht gehen.
I2S ist recht flott, je nach Signal kommen da schon mal 26MHz zusammen.
Ein externes Schieberegister könnte gehen oder ein Prozessor mit I2S
Eingang.
Bis 96kHz/24Bit sollte SPI noch mitmachen. Allerdings kann es sein, daß
Du Dir noch ein paar clock-Signale erzeugen musst ... Dies ist auch der
Grenzfall und damit schon sehr Zeitkritisch.
Bei CD (44.1/16) sollte es aber keine Probleme geben.
Gruß
Jobst
Jobst M. schrieb:
> Bis 96kHz/24Bit sollte SPI noch mitmachen.
sicher? I2S läuft mit 32bit, 2 kanäle => 6.144MHz hat dann die SCLK.
gewagt, gewagt...
ich würde auch ein externes Schieberegister nehmen, oder ein CPLD.
Moin!
I2S läuft nicht immer mit 32Bit. Aber ich habe auch mit diesem Fall
gerechnet. Dann läuft der uC mit 24.576MHz das ist leicht ausserhalb
seiner Specs. Allerdings sollte der Takt aus dem Datensignal generiert
werden.
Das dies Grenzwertig ist, habe ich aber geschrieben.
Abgesehen davon, würde ich das Ganze analog machen.
Wenn es unbedingt digital sein muss, kann er ja einen SRC davor
schalten.
Gruß
Jobst
Danke für die Infos.
Ich habe zur Zeit 32Bit mit maximal 12,xxx MHz auf dem I2S Bus (192KHz
128FS).
Das kann aber sein das ich noch schneller werden muss.
Nun eine reine Software Lösung schließe ich jetzt auch aus.
Der Einwand mit der SPI habe ich nachgelesen und wird wohl auch nicht
gehen.
Bleibt wohl nur ein Schieberegister oder ein kleiner ARM Prozessor.
Dumm nur das ich mich mit den ARM Prozessoren nicht auskenne und auch
keine Tools dafür habe. Was gibt es denn vernünftiges dafür?
Eine AVR Lösung wird mit einem Schieberegister aber auch schwer. Ich
muss den Inhalt ja abholen bevor das nächste Bit rein kommt. Oder gibt
es da entsprechende Bausteine die das Ergebnis zwischen speichern?
MfG Peter
@Peter
Nimm nen ARM.
Ein AT91SAM7S256 z.b. hat direkt eine I2S Schnittstelle inkl. DMA
On-Board.
Damit wird I2S zur Nebensache. Einem AVR würd ich ohnehin nicht zutrauen
I2S Deserializing zu machen (es sei denn er macht NUR das), von der
Verarbeitung mal ganz abgesehen. Jedenfalls nicht wenns CD Qualität
aufwärts sein soll. 8kHz 16Bit mono bekommt man mit einem AVR sicherlich
noch hin. Und da wäre auch wohl Verarbeitung noch evtl drin. Aber alles
was darüber geht ... wenig Chancen.
Ich will die Daten nur einlesen und den Pegel anzeigen (LEDs).
Wenn es geht, auch noch als 8Bit Wert über I²C bereitstellen.
Das ein ARM7 das packt ist mir auch klar, aber den kenne ich nicht.
MfG, Peter
Also wenn du dir den RMS Wert anzeigen lassen willst ist es noch etwas
zu tun bis dahin ...
Du mußt jedes Sample (also jedes empfangene Datenwort) quadrieren,
aufsummieren, am Ende der Summation (alle x Werte, wobei x deine
Fenstergröße vorgibt) dann durch x teilen, die Wurzel daraus ziehen und
dann kannst du den Wert in dB umrechnen.
Bei CD-Qualität ist der Aufwand (wenn man nicht gravierende
Vereinfachungen macht) für einen AVR nicht zu schaffen.
Lösung a) :
- nur 8 von den 16 bzw 24 Bits verarbeiten.
- Fenstergröße fest auf 2'er Potenz
- Wurzelfkt. stark optimieren (Tabellen usw)
Lösung b) :
- I2S nach analog Wandeln, analog filtern und mit dem ADC des AVR's
einlesen
Wenn du es rein digital machen willst denke ich kannst du das vergessen.
Quadrieren von 24 bzw 32 Bit. Teilen einer 32 bzw 64 Bit Zahl durch 16
bzw 32 Bit. Wurzelziehen aus einer 32 Bit Zahl. Und das alles in 10-20µs
(200-400 Takte bei 20MHz pro Sample). Sehr sportlich.
Habe ich mal gemacht. Dabei taste ich nicht den kompletten Datenstrom
ab, sondern immer nur Stichproben, damit noch Zeit zum Rechnen und für
die Darstellung bleibt. Für eine LED-Anzeige gar kein Problem. Hier
waren die 12.288Mhz MasterClock auch gleich die Taktfrequenz für den
Controller, so daß man 4 Takte pro Samplebit zur Verfügung hat. Über
LRCLK wurde der Frame synchronisiert, wenn ich mich recht erinnere, habe
ich 16Bit/48kHz ausgewertet, logarithmiert und auf 2x10 LEDs angezeigt.
Nettes Gimmick ist eine Peak-Hold-Funktion. Das Projekt läuft in einer
digitalen DI-Box, Controller ist ein Mega16, der auch für die Akkuladung
zuständig ist.
TheMason schrieb:
> Wenn du es rein digital machen willst denke ich kannst du das vergessen.> Quadrieren von 24 bzw 32 Bit. Teilen einer 32 bzw 64 Bit Zahl durch 16> bzw 32 Bit. Wurzelziehen aus einer 32 Bit Zahl. Und das alles in 10-20µs> (200-400 Takte bei 20MHz pro Sample). Sehr sportlich.
Es gibt auch LookUp-Tables, die im oben beschriebenen
Stichproben-Betrieb schnell genug sind. Es kommt hier nicht auf 100,000%
Genauigkeit an. Es soll habwegs glaubhaft blinken und bei der Findung
des optimalen Pegels helfen (nehme ich an).
@travelrec
Einverstanden. Ich bin (leider) davon ausgegangen es so akkurat wie
möglich zu machen, und hab natürlich die wichtigsten
Optimierungsmöglichkeiten ausgelassen. Scheiß Perfektionismus :-)
Aber so gesehen lässt sich da schon was machen.
Ich bin auch zuversichtlich, daß der Mega88 das kann.
Ich habe gerade das Umgekehrte gebaut, eine I²S Ausgabe, 48 kHz Stereo
16 Bit. Und die Samples muß der arme Controller auch noch errechenen
(DDS mit nachgeschalteter linearer Interpolation zwischen den
Tabellenwerten).
Nimm nicht den SPI, sondern den USART im synchronen Modus. SPI hat beim
Mega88 leider keine Doppelpufferung, USART schon.
Ein weiterer "Trick" in meinem System war, nested Interrupts zuzulassen,
um die Latenz klein zu kriegen. Und die Codierung der Haupt-ISR in
Assembler...
Jörg
Naja, leider kann man den synchronen UART nur als Master-SPI gebrauchen,
was bei der vorliegenden Anwendung keine Vorteile bringt.
Hier der betreffende Codeabschnitt, es werden keine Hardware-Interfaces
benutzt. Engegen meiner Annahme werden nur je 8 obere Bits für den
linken und rechnten Kanal benutzt, was für 10 LEDs aber ausreicht.
1
;reads I2S data, 8 MSB for each channel
2
GetSoundADC:
3
cli
4
5
_GSA1:
6
sbic PinC, LRCK ;syncronize to LRCK
7
rjmp _GSA1
8
9
_GSA2:
10
sbis PinC, LRCK
11
rjmp _GSA2
12
13
nop
14
clr Temp
15
clc
16
sbic PinC, SDIN
17
sec
18
rol Temp
19
clc
20
sbic PinC, SDIN
21
sec
22
rol Temp
23
clc
24
sbic PinC, SDIN
25
sec
26
rol Temp
27
clc
28
sbic PinC, SDIN
29
sec
30
rol Temp
31
clc
32
sbic PinC, SDIN
33
sec
34
rol Temp
35
clc
36
sbic PinC, SDIN
37
sec
38
rol Temp
39
clc
40
sbic PinC, SDIN
41
sec
42
rol Temp
43
clc
44
sbic PinC, SDIN
45
sec
46
rol Temp
47
clc
48
sbic PinC, SDIN
49
sec
50
rol Temp
51
52
brcc _TCLeft ;convert 2s complement to positive value
53
neg Temp
54
55
_TCLeft:
56
sts LeftLow, Temp
57
58
59
_GSA4:
60
sbic PinC, LRCK
61
rjmp _GSA4
62
63
nop
64
clr Temp
65
clc
66
sbic PinC, SDIN
67
sec
68
rol Temp
69
clc
70
sbic PinC, SDIN
71
sec
72
rol Temp
73
clc
74
sbic PinC, SDIN
75
sec
76
rol Temp
77
clc
78
sbic PinC, SDIN
79
sec
80
rol Temp
81
clc
82
sbic PinC, SDIN
83
sec
84
rol Temp
85
clc
86
sbic PinC, SDIN
87
sec
88
rol Temp
89
clc
90
sbic PinC, SDIN
91
sec
92
rol Temp
93
clc
94
sbic PinC, SDIN
95
sec
96
rol Temp
97
clc
98
sbic PinC, SDIN
99
sec
100
rol Temp
101
102
brcc _TCRight ;convert 2s complement to positive value
Ja, mach mal. Die erhaltenen Daten mußt Du eigentlich nur maximieren
(Peak detection) und diesen Maximalwert relativ langsam (10%
Laufbandlänge /100ms) herunterzählen. Neue Peaks werden sofort
übernommen. Das sieht dann optisch schon gut aus. Aufwerten läßt sich
das durch ein Peak-Hold, bei dem die Spitzenpunkte 2s lang auf der
Anzeige bleiben, bevor sie mit kleineren Werten geladen werden. Dabei
kann dann die Release-Zeit des Gesamtbandes wieder etwas zügiger sein,
so daß man schnellere Reaktionen sieht. Viel Spaß beim Proggen! Ich mach
mal gelegentlich ein Filmchen von meinen Anzeigen ;-)