Forum: Mikrocontroller und Digitale Elektronik I2S am DAC mit AVR unt Interrupt.


von C. H. (hedie)


Lesenswert?

Hallo Zusammen...

Ich habe hier einen DAC genauer gesagt einen MAX9850...

Dieser hat ein I2S Interface bzw ist auch anders konfigurierbar.

Meine Konfiguration sieht so aus, das der DAC auf die steigende Flanke 
des BitClockes (BCLK) die Daten Seriell mit MSB First am SDIN Eingang 
erwartet...

Es werden 16Bit übertragen, danach wird der Kanal (Rechts / Links) 
gewechselt (LRCLK High->Low) und das ganze beginnt von vorn!

Ich habe den MAX9850 so konfiguriert, das er im Master moder arbeitet.
Damit erzeugt er die Signale BCLK und LRCLK selbst.

Ich habe beide mit InterruptPIN's verbunden.

BCLK auf INT1 auf steigende Flanke Triggernd
LRCLK auf PCINT0 da jeder Flanken wechsel entscheidend ist!

Das BCLK Signal ist 3MHz schnell
LRCLK 8KHz

Mein Controller: Attiny2313 mit 12MHz Takt. Damit wird auch der MAX9850 
getaktet.

Meine Frage nun...
ich möchte gerne sehr einfache PCM sounds wiedergeben.
Zu beginn wollte ich einfach mal einen Test Ton erzeugen.
Dazu habe ich folgenden Code:

1
unsigned char ucData = 0xAA;
2
unsigned char ucShift = 0;
3
4
ISR(PCINT_vect)                // Kanal Wechsel
5
{
6
    ucShift = 0;
7
}
8
9
ISR(INT1_vect)                // BCLK Steigende Flanke!
10
{
11
  if((ucData << ucShift) & 0x80)
12
  {
13
    SDIN_1;  //SDIN auf high
14
  }
15
  else
16
  {
17
    SDIN_0;  //SDIN auf Low
18
  }
19
  ucShift++;
20
}

Doch leider hat SDIN immer High...
Obwohl ja eigentlich immer wieder 0xAA gesendet werden sollte.
Wo steckt hier wohl der Fehler?

Danke schonmal

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Claudio Hediger schrieb:

> Wo steckt hier wohl der Fehler?

Mindestens bei den fehlenden volatile bei der Datendefinition.

von Magnus M. (magnetus) Benutzerseite


Lesenswert?

Claudio Hediger schrieb:
> Ich habe beide mit InterruptPIN's verbunden.
>
> BCLK auf INT1 auf steigende Flanke Triggernd
> LRCLK auf PCINT0 da jeder Flanken wechsel entscheidend ist!
>
> Das BCLK Signal ist 3MHz schnell
> LRCLK 8KHz
>
> Mein Controller: Attiny2313 mit 12MHz Takt. Damit wird auch der MAX9850
> getaktet.

(...)

> Doch leider hat SDIN immer High...
> Obwohl ja eigentlich immer wieder 0xAA gesendet werden sollte.
> Wo steckt hier wohl der Fehler?

Rechne mal nach wie viele Takte zwischen zwei steigenden BCLK-Flanken 
für die Abarbeitung deines Interrupts zur Verfügung stehen...

Gruß,
Magnetus

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Damit das auch nur ansatzweise schnell genug die Daten aus dem 
Controller bekommt, würde ich versuchen, den ATtiny als SPI-Slave an den 
I2S anzuschließen. Der sollte sich so konfigurieren lassen, dass man 
zumindest 8 Bit am Stück ohne zusätzliche Softwareaktion rausschicken 
kann.

Grüße,

Peter

von Kurt H. (Firma: KHTronik) (kurtharders)


Lesenswert?

Wie magnetus schrieb: bei 3MHz BCLK und 12MHz Takt des ATTiny hast Du 
maximal 4 Zyklen Zeit für die Abfrage und Speicherung. Da die 
Interrupterkennung auch etwas Zeit braucht, und der Sprung zur 
Interruptroutine auch, wirst Du Dich mit zwei Befehlen begnügen müssen 
:-).
Aber mal zum Tempo: wenn Du mit 48kHz wandelst und 16 Bit Auflösung 
verwendest, lande ich bei 1,5MHz für BCLK. Das ist zwar auch noch knapp, 
aber ohne Interrupt durch Polling der Pins eventuell machbar.
Auf jeden Fall musst Du Dir den Assembleroutput des Compilers anschauen, 
um die Takte zu zählen.

von C. H. (hedie)


Lesenswert?

Vielen Dank für eure Antworten....


Kurt Harders schrieb:
> Aber mal zum Tempo: wenn Du mit 48kHz wandelst und 16 Bit Auflösung
> verwendest, lande ich bei 1,5MHz für BCLK. Das ist zwar auch noch knapp,
> aber ohne Interrupt durch Polling der Pins eventuell machbar.
> Auf jeden Fall musst Du Dir den Assembleroutput des Compilers anschauen,
> um die Takte zu zählen.

Theoretisch hast du recht... Ich habe übrigens nur eine Samplingfrequenz 
von 8KHz

Doch leider gibt der MAX mir die 3MHz vor...

Das Signal Sieht etwa so aus
     ___________________________
____|                             |__________ LRCLK
____||||__________________________||||_______ BCLK

Man sieht also das BCLK sehr schnell ist im vergleich zum LRCLK
Wenn ich den MAX jedoch in den Slave Mode Versetze, dann muss ich diese 
Signale ja selbst erzeugen und das würde nochmals länger dauern...

Peter Diener schrieb:
> Damit das auch nur ansatzweise schnell genug die Daten aus dem
> Controller bekommt, würde ich versuchen, den ATtiny als SPI-Slave an den
> I2S anzuschließen. Der sollte sich so konfigurieren lassen, dass man
> zumindest 8 Bit am Stück ohne zusätzliche Softwareaktion rausschicken
> kann.

Das klingt interessant... Müsste ich mal testen...
Doch da hätte ich dennoch noch das problem das ich z.B. die Daten nicht 
mehr von einer Speicherkarte holen könnte.

von Kurt H. (Firma: KHTronik) (kurtharders)


Lesenswert?

Claudio Hediger schrieb:
> Das Signal Sieht etwa so aus
>      ___________________________
> ____|                             |__________ LRCLK
> ____||||__________________________||||_______ BCLK
>
> Man sieht also das BCLK sehr schnell ist im vergleich zum LRCLK

Das sieht mir aber stark nach einer Betriebsart für >2 Kanäle aus. Mit 
welcher Master-Clock betribst Du den DAC?

von C. H. (hedie)


Lesenswert?

Kurt Harders schrieb:
> Das sieht mir aber stark nach einer Betriebsart für >2 Kanäle aus. Mit
> welcher Master-Clock betribst Du den DAC?

Hallo Kurt

Da hast du recht... Es ist ein Stereo DAC

MasterClock ist 12MHz
Der DAC erzeigt die Signale BCLK und LRCLK selbst. Ich dachte mir das 
ich damit mehr zeit zum bereitstellen der Daten habe im AVR. Da ich ja 
diese Signale nicht selbst erzeugen muss.

Wäre ja schon spannend wenn es klappen würde und der Tiny ein I2S Signal 
erzeugen könnte :)

Achjaa die 4 | Striche beim BCLK stehen für 16 Clocks dieser Leitung.
Es wird somit 16Bit Audio erwartet. Das ist das niedrigste was dieser 
DAC kann.

von Kurt H. (Firma: KHTronik) (kurtharders)


Lesenswert?

Claudio Hediger schrieb:
> Achjaa die 4 | Striche beim BCLK stehen für 16 Clocks dieser Leitung.
> Es wird somit 16Bit Audio erwartet. Das ist das niedrigste was dieser
> DAC kann.

Und wie viele Takte ist dann die Pause bis zur Flanke LRCLK?

von C. H. (hedie)


Angehängte Dateien:

Lesenswert?

Kurt Harders schrieb:
> Und wie viele Takte ist dann die Pause bis zur Flanke LRCLK?

Es sind ca. 55us

Ich habe nun mal mit dem Oszilloskop ein paar Bilder gemacht...

Bild1 zeigt das gesamte Signal
Bild2 zeigt die Pause bis zum Flankenwechsel von LRCLK nach 16 BCLK 
Clocks
Bild3 zeigt die Frequenz von BCLK

Gelb: LRCLK
Blau: BCLK

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Damit der DAC etwas damit anfangen kann, müssen BitClock, LRClock und 
MasterClock phasensynchron sein. Das erreichst Du nur, wenn der Tiny an 
derselben Taktleitung mit dem DAC hängt und der Code im Tiny absolut 
laufzeitsynchron läuft. Alle Clocks müssen immer präsent sein und dürfen 
weder aussetzen, noch einen Jitter von >1 MasterClock aufweisen.

Siehe hier:
Beitrag "SD-Karten-Wave-Recorder"

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Anbei mal eine Anwendung für den T2313, der von einem XMEGA parallel 
angesteuert wird. Stammt aus obigem Projekt.

1
.include "tn2313def.inc"
2
3
.def  Null    =r2
4
5
6
.def  Left1    =r4
7
.def  Left2    =r5
8
9
.def  Right1    =r7
10
.def  Right2    =r8
11
12
.def  Temp    =r16
13
.def  TempH    =r17
14
.def  Temp3    =r18
15
16
17
18
;PortD
19
.equ  SData    =3      ;I2S-data
20
.equ  LRCK    =4      ;I2S-wordclock, Left low, Right high
21
.equ  LED      =6      ;LED on PortD
22
23
24
25
26
27
28
29
;**********************************************************************************
30
.org $0000
31
32
33
RESET:
34
;init Stackpointer
35
 ldi  Temp, low (RAMEND)
36
 out  SPL, Temp
37
38
;init Watchdog
39
 wdr
40
 in   Temp, WDTCR
41
 ori  Temp, (1<<WDCE) | (1<<WDE)
42
 out  WDTCR, Temp
43
 ldi  Temp, 7                      ;Watchdog Time-Out ~ 2 sec.
44
 out  WDTCR, Temp
45
46
;clear SRAM 
47
 clr  XH
48
 ldi  XL, $60
49
 clr  Temp
50
51
_CLSR:
52
 st    X+, Temp
53
 cpi  XL, $DF
54
 brne  _CLSR
55
56
 clr Null
57
58
;init Ports 
59
 ldi  Temp,  0b00000000      ;Data in from main controller
60
 ldi   TempH, 0b00000000
61
 out  DDRB, Temp
62
 out   PortB, TempH                    
63
64
 ldi  Temp,  0b01001000      ;Control Lines I2S    
65
 ldi   TempH, 0b01000000
66
 out  DDRD, Temp                    
67
 out   PortD, TempH  
68
69
70
;reads I2S data 
71
GetI2S:
72
 ldi  Temp, 41
73
  
74
_GI2S1:
75
 sbic  PinD, LRCK      
76
 rjmp  _GI2S1
77
78
_GI2S2:
79
 sbis  PinD, LRCK      
80
 rjmp  _GI2S2
81
 
82
 
83
_Wait32Bit:
84
 dec  Temp
85
 brne  _Wait32Bit
86
 
87
 bst   Left2, 7
88
 bld  Temp, SDATA
89
90
 sbis  PinD, LRCK      ;Synchronize to falling edge of WordClock (left channel)
91
 rjmp  _GI2S3
92
 sbis  PinD, LRCK      
93
 rjmp  _GI2S3
94
 sbis  PinD, LRCK      
95
 rjmp  _GI2S3
96
 sbis  PinD, LRCK      
97
 rjmp  _GI2S3
98
 sbis  PinD, LRCK      
99
 rjmp  _GI2S3
100
 sbis  PinD, LRCK      
101
 rjmp  _GI2S3
102
 sbis  PinD, LRCK      
103
 rjmp  _GI2S3
104
 sbis  PinD, LRCK      
105
 rjmp  _GI2S3
106
 sbis  PinD, LRCK      
107
 rjmp  _GI2S3
108
 sbis  PinD, LRCK      
109
 rjmp  _GI2S3
110
 
111
112
_GI2S3:
113
 out  PortD, Temp
114
 clr  Temp
115
 bst   Left2, 6
116
 bld  Temp, SDATA
117
 out  PortD, Temp
118
 clr  Temp
119
 bst   Left2, 5
120
 bld  Temp, SDATA
121
 out  PortD, Temp
122
 clr  Temp
123
 bst   Left2, 4
124
 bld  Temp, SDATA
125
 out  PortD, Temp
126
 clr  Temp
127
 bst   Left2, 3
128
 bld  Temp, SDATA
129
 out  PortD, Temp
130
 clr  Temp
131
 bst   Left2, 2
132
 bld  Temp, SDATA
133
 out  PortD, Temp
134
 clr  Temp
135
 bst   Left2, 1
136
 bld  Temp, SDATA
137
 out  PortD, Temp
138
 clr  Temp
139
 bst   Left2, 0
140
 bld  Temp, SDATA
141
 out  PortD, Temp
142
143
 clr  Temp
144
 bst   Left1, 7
145
 bld  Temp, SDATA
146
 out  PortD, Temp
147
 clr  Temp
148
 bst   Left1, 6
149
 bld  Temp, SDATA
150
 out  PortD, Temp
151
 clr  Temp
152
 bst   Left1, 5
153
 bld  Temp, SDATA
154
 out  PortD, Temp
155
 clr  Temp
156
 bst   Left1, 4
157
 bld  Temp, SDATA
158
 out  PortD, Temp
159
 clr  Temp
160
 bst   Left1, 3
161
 bld  Temp, SDATA
162
 out  PortD, Temp
163
 clr  Temp
164
 bst   Left1, 2
165
 bld  Temp, SDATA
166
 out  PortD, Temp
167
 clr  Temp
168
 bst   Left1, 1
169
 bld  Temp, SDATA
170
 out  PortD, Temp
171
 clr  Temp
172
 bst   Left1, 0
173
 bld  Temp, SDATA
174
 out  PortD, Temp
175
 nop
176
 nop
177
 nop
178
 out  PortD, Null
179
 
180
 nop
181
 nop
182
 nop 
183
 nop 
184
 nop
185
 nop
186
 nop
187
 nop
188
 nop
189
 nop
190
 nop
191
 nop
192
   
193
 in    Left2, PinB
194
 nop
195
 nop
196
 nop
197
 nop
198
 nop
199
 nop
200
 in    Left1, PinB
201
 nop
202
 nop
203
 nop
204
 nop
205
 nop
206
 nop
207
 in    Right2, PinB
208
 nop
209
 nop
210
 nop
211
 nop
212
 nop
213
 nop
214
 in    Right1, PinB
215
216
217
 nop      ;synchronize to right frame
218
 nop
219
 nop
220
 nop
221
 nop
222
 nop
223
 nop
224
 nop
225
226
 nop
227
 nop
228
 nop
229
 nop
230
 nop
231
 nop
232
 nop
233
 nop
234
235
 nop
236
 nop
237
 nop
238
 nop
239
 nop
240
 nop
241
 nop
242
 nop
243
244
 nop
245
 nop
246
 
247
248
249
 
250
 clr  Temp
251
 bst   Right2, 7
252
 bld  Temp, SDATA
253
 out  PortD, Temp
254
 clr  Temp
255
 bst   Right2, 6
256
 bld  Temp, SDATA
257
 out  PortD, Temp
258
 clr  Temp
259
 bst   Right2, 5
260
 bld  Temp, SDATA
261
 out  PortD, Temp
262
 clr  Temp
263
 bst   Right2, 4
264
 bld  Temp, SDATA
265
 out  PortD, Temp
266
 clr  Temp
267
 bst   Right2, 3
268
 bld  Temp, SDATA
269
 out  PortD, Temp
270
 clr  Temp
271
 bst   Right2, 2
272
 bld  Temp, SDATA
273
 out  PortD, Temp
274
 clr  Temp
275
 bst   Right2, 1
276
 bld  Temp, SDATA
277
 out  PortD, Temp
278
 clr  Temp
279
 bst   Right2, 0
280
 bld  Temp, SDATA
281
 out  PortD, Temp
282
283
 clr  Temp
284
 bst   Right1, 7
285
 bld  Temp, SDATA
286
 out  PortD, Temp
287
 clr  Temp
288
 bst   Right1, 6
289
 bld  Temp, SDATA
290
 out  PortD, Temp
291
 clr  Temp
292
 bst   Right1, 5
293
 bld  Temp, SDATA
294
 out  PortD, Temp
295
 clr  Temp
296
 bst   Right1, 4
297
 bld  Temp, SDATA
298
 out  PortD, Temp
299
 clr  Temp
300
 bst   Right1, 3
301
 bld  Temp, SDATA
302
 out  PortD, Temp
303
 clr  Temp
304
 bst   Right1, 2
305
 bld  Temp, SDATA
306
 out  PortD, Temp
307
 clr  Temp
308
 bst   Right1, 1
309
 bld  Temp, SDATA
310
 out  PortD, Temp
311
 clr  Temp
312
 bst   Right1, 0
313
 bld  Temp, SDATA
314
 out  PortD, Temp
315
 nop
316
 nop
317
 nop
318
 out  PortD, Null
319
 
320
 sbi  PortD, LED
321
 nop
322
 nop
323
 nop
324
 nop
325
 nop
326
 nop
327
328
 nop
329
 nop
330
 nop
331
 nop
332
 nop
333
 nop
334
 nop
335
 nop
336
337
 nop
338
 nop
339
 nop
340
 nop
341
 nop
342
 nop
343
 nop
344
 nop
345
346
 nop
347
 nop
348
 nop
349
 nop
350
 nop
351
 nop
352
 nop
353
 nop
354
 
355
356
 wdr
357
358
 nop
359
 nop
360
 nop
361
 nop
362
 nop
363
 nop
364
365
 nop
366
 nop
367
 nop
368
 nop
369
 nop 
370
 nop
371
 nop
372
 nop
373
374
 nop
375
 nop
376
 nop
377
 nop
378
 cbi  PortD, LED
379
 clr  Temp
380
 
381
 bst   Left2, 7
382
 bld  Temp, SDATA
383
384
 sbis  PinD, LRCK      ;Synchronize to falling edge of WordClock (left channel)
385
 rjmp  _GI2S3
386
 sbis  PinD, LRCK      
387
 rjmp  _GI2S3
388
 sbis  PinD, LRCK      
389
 rjmp  _GI2S3
390
 sbis  PinD, LRCK      
391
 rjmp  _GI2S3
392
 sbis  PinD, LRCK      
393
 rjmp  _GI2S3
394
 sbis  PinD, LRCK      
395
 rjmp  _GI2S3
396
 sbis  PinD, LRCK      
397
 rjmp  _GI2S3
398
 sbis  PinD, LRCK      
399
 rjmp  _GI2S3
400
 sbis  PinD, LRCK      
401
 rjmp  _GI2S3
402
 sbis  PinD, LRCK      
403
 rjmp  _GI2S3

von C. H. (hedie)


Lesenswert?

Knut Ballhause schrieb:
> Damit der DAC etwas damit anfangen kann, müssen BitClock, LRClock und
> MasterClock phasensynchron sein. Das erreichst Du nur, wenn der Tiny an
> derselben Taktleitung mit dem DAC hängt

Vielen Dank für deinen Code

Ja der Tiny hängt am selben MCLK wie der DAC

von C. H. (hedie)


Lesenswert?

Claudio Hediger schrieb:
> Knut Ballhause schrieb:
>> Damit der DAC etwas damit anfangen kann, müssen BitClock, LRClock und
>> MasterClock phasensynchron sein. Das erreichst Du nur, wenn der Tiny an
>> derselben Taktleitung mit dem DAC hängt
>
> Vielen Dank für deinen Code
>
> Ja der Tiny hängt am selben MCLK wie der DAC

jetzt muss ich doch nochmal was fragen,

Also du benutzt den Attiny2313 nur als Parallel -> I2S Wandler richtig?

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Claudio Hediger schrieb:
> Also du benutzt den Attiny2313 nur als Parallel -> I2S Wandler richtig?

Genau, weil viel mehr ist nicht drin. Allerdings kannst Du in den 
"NOP"-Sequenzen auch Daten von einer anderen Quelle schaufeln und über 
I2S ausgeben. Der T2313 ist im Beispiel übrigens auch ein Slave, der 
sich an der LRCK des Masters orientiert. Der Code ist so getimed, dass 
per BitClock-Low des I2S ein Bit ausgegeben wird. Dies wird über die 
Sync-Schleife am Anfang erreicht. In der Mainloop wird diese 
Synchronität durch die exakte Laufzeit des Codes nicht mehr verlassen.

von C. H. (hedie)


Lesenswert?

Knut Ballhause schrieb:
> Genau, weil viel mehr ist nicht drin. Allerdings kannst Du in den
> "NOP"-Sequenzen auch Daten von einer anderen Quelle schaufeln und über
> I2S ausgeben. Der T2313 ist im Beispiel übrigens auch ein Slave, der
> sich an der LRCK des Masters orientiert. Der Code ist so getimed, dass
> per BitClock-Low des I2S ein Bit ausgegeben wird. Dies wird über die
> Sync-Schleife am Anfang erreicht. In der Mainloop wird diese
> Synchronität durch die exakte Laufzeit des Codes nicht mehr verlassen.

weshalb hast du kein ParallelIN SerialOut Register verwendet?

z.B. 74HC165

Das macht ja eigentlich genau das selbe... Man muss nur am Clock eingang 
den BitClock anhängen und um das Propagation Delay zu umgehen invertiert 
man den Eingang. So das auf eine Fallende BitClock Flanke das Bit 
geshiftet wird und mit der Steigenden übernimmt der DAC das Bit... Das 
müsste doch eigentlich gehen oder?

von Purzel H. (hacky)


Lesenswert?

Also, ich wuerd den Wandler als Slave laufenlassen und das Timing der 
Signale im Bitbang modus machen.

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Claudio Hediger schrieb:
> weshalb hast du kein ParallelIN SerialOut Register verwendet?
>
> z.B. 74HC165
>
> Das macht ja eigentlich genau das selbe...

Nicht ganz. Die Controller sind über die Firmware in der Lage, 
verschiedene Protokolle auszugeben/anzunehmen, zum Beispiel I2S, Left 
Justified, Right Justified oder DSP-Protokoll. Ausserdem sind 
verschiedene Bitbreiten pro Frame möglich. Erfolgreich getestet habe ich 
bis 20 Bit, die restliche Laufzeit geht für das Datenschaufeln drauf. 
Diskrete Bauelemente sind da etwas statisch und ich hatte genug T2313 
herumliegen.

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

O.. oha Jetzt ! schrieb:
> Also, ich wuerd den Wandler als Slave laufenlassen und das Timing der
> Signale im Bitbang modus machen.

Wie meinen? Es ist für den Controller einfacher, ein Slave zu sein, da 
sonst noch das Timing für die Clocks in den Code müsste, was 
laufzeitbedingt nicht geht.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.