Forum: Digitale Signalverarbeitung / DSP / Machine Learning BF533 Eval mit AD1836, I²S, Sampling Frame bearbeiten


von Christoph G. (huecksy)


Lesenswert?

Hallo an alle,
ich bin neu hier und hoffe Ihr könnt mir zu mehr Verständnis verhelfen. 
Ich hab folgendes Problem. Ich bin gerade dabei ein ADSP-BF533 EZ-KIT 
Lite Board in Betrieb zu nehmen. Analog hat einige Beispiel Programme 
mitgeliefert und ich habe die I²S Software aufgespielt (C). Soweit 
funktioniert das auch, jedoch möchte ich nun das Signal verstärken und 
verstehe nicht in welchem Format die Audioframes vom Codec kommen.
Laut der I²S-specifications müsste das Signal in "two’s complement with 
the MSB first" übertragen werden.
Nun passieren zwei Dinge, die ich nicht verstehe:
1. Wenn ich mir beim Debugging ein Audioframe anzeigen lasse, ist der 
Wert immer positiv und hat einen Wert zwischen 30000 und 60000
2. Wenn ich den Wert eines Audioframes zur Verstärkung mit Ganzzahligen 
Werten multipliziere ist das Ergebnis ok (wird verstärkt und lauter) 
wenn ich mit einem gebrochenen Wert multipliziere hört sich das Ergebnis 
verzerrt oder übersteuert an.
Als Konsequenz muss ich sagen, das ich nicht verstehe in welchem Format 
das Signal vorliegt.
Ich habe einen Sinus programmiert und an das Codec (AD1836) geschickt 
und das wird scheinbar richtig ausgegeben (1kHz hörbar) . Hier noch der 
Quellcode, mit der das Codec Initialisiert wird.
1
//--------------------------------------------------------------------------//
2
// Function: Init1836() //
3
// //
4
// Description: This function sets up the SPI port to configure the AD1836. //
5
// The content of the array sCodec1836TxRegs is sent to the //
6
// codec. //
7
//--------------------------------------------------------------------------//
8
void Init1836(void)
9
{
10
int i;
11
int j;
12
static unsigned char ucActive_LED = 0x01;
13
// write to Port A to reset AD1836
14
*pFlashA_PortA_Data = 0x00;
15
// write to Port A to enable AD1836
16
*pFlashA_PortA_Data = ucActive_LED;
17
// wait to recover from reset
18
for (i=0; i<0xf0000; i++) asm("nop;");
19
// Enable PF4
20
*pSPI_FLG = FLS4;
21
// Set baud rate SCK = HCLK/(2*SPIBAUD) SCK = 2MHz
22
*pSPI_BAUD = 16;
23
// configure spi port
24
// SPI DMA write, 16-bit data, MSB first, SPI Master
25
*pSPI_CTL = TIMOD_DMA_TX | SIZE | MSTR;
26
// Set up DMA5 to transmit
27
// Map DMA5 to SPI
28
*pDMA5_PERIPHERAL_MAP = 0x5000;
29
// Configure DMA5
30
// 16-bit transfers
31
*pDMA5_CONFIG = WDSIZE_16;
32
// Start address of data buffer
33
*pDMA5_START_ADDR = (void *)sCodec1836TxRegs;
34
// DMA inner loop count
35
*pDMA5_X_COUNT = CODEC_1836_REGS_LENGTH;
36
// Inner loop address increment
37
*pDMA5_X_MODIFY = 2;
38
// enable DMAs
39
*pDMA5_CONFIG = (*pDMA5_CONFIG | DMAEN);
40
// enable spi
41
*pSPI_CTL = (*pSPI_CTL | SPE);
42
// wait until dma transfers for spi are finished
43
for (j=0; j<0xaff0; j++) asm("nop;");
44
// disable spi
45
*pSPI_CTL = 0x0000;
46
}
Hier noch ein paar weitere Daten:
- Datenübertragung mittels I²S
- Abtastrate 48kHz mit 16 Bit Auflösung

Vielleicht kann mir ja jemand auf die Sprünge helfen. Ich möchte später 
noch weiteren Code einfügen in dem dann einige Filter laufen sollen. 
Dazu muss ich aber erstmal verstehen wie die Daten vorliegen die ich 
dann bearbeiten möchte.
Vielen Dank schon mal fürs lesen und erst recht für jeden Hilfeversuch!

von Christoph G. (huecksy)


Lesenswert?

hmm, so richtig komme ich allein nicht weiter.

Das AD1836 legt mir das Audioframe mit 16 oder 24 Bit (je nach 
Einstellung) in den Speicher des DSP. Ich vermute das hier das MSB 
"verloren geht" bzw nicht mehr erkannt wird.
Das ist die einzige Erklärung, weshalb mir immer nur positive Zahlen 
während des Debuggings angezeigt werden.
Ist bei jemandem schon mal etwas ähnliches aufgetreten oder ist mein 
Ansatz falsch?

Ich programmiere das erste mal embedded und hab noch keine Erfahrung in 
dem Bereich.

von Christoph G. (huecksy)


Lesenswert?

So, ich habs gelöst, glaub ich :)
Beim Auslesen des vom Codec ankommenden Audioframes geht das Vorzeichen 
unter. Das liegt daran, dass das Codec AD1836 mit 24 Bit codiert, ich 
das Frame aber in eine 32 Bit Int Variable schreibe.
Die Lösung die ich jetzt nutze ist, die Daten um 8 Bit nach links zu 
shiften und ich dann eine Multiplikation zur Verstärkung oder eine 
Division zur Dämpfung rechnen kann. Anschließend shifte ich zurück und 
lass an das Codec zurück übergeben.
Ich glaube zumindest das es daran liegt?!?

von Strubi (Gast)


Lesenswert?

Hi Christoph,

klingt schluessig, also so, als ob du auf dem richtigen Weg waerst.
Arbeite zwar nur mit den GNU-Tools, aber soweit ich mich erinnere, gab 
es bei VDSP diverse Moeglichkeiten, Memory-Inhalte zu plotten.
Im Endeffekt reduzieren sich deine Probleme in diesem Fall wohl auf die 
Datenformate (Konfiguration, unsigned/signed, usw.). Fuer die 
Audio-Verarbeitung empfiehlt sich ev. fuer spaetere Optimierung, die 
Assembler-Instructionen genau zu studieren, manche davon normieren, 
runden, und begrenzen die Rechenergebnisse im gleichen Zyklus.

Viel Erfolg!

- Strubi

von Christoph G. (huecksy)


Lesenswert?

Hallo Strubi,

ich denke das es der Vorzeichenverlust Aufgrund des nicht erkannten MSB 
gewesen ist. Ich bin aufgrund dieses Forenbeitrags darauf gekommen.
http://ez.analog.com/thread/1229?tstart=0
In jedem Fall werden mir jetzt beim Debugging auch negative Zahlerwerte 
angezeigt.

> Fuer die
> Audio-Verarbeitung empfiehlt sich ev. fuer spaetere Optimierung, die
> Assembler-Instructionen genau zu studieren, manche davon normieren,
> runden, und begrenzen die Rechenergebnisse im gleichen Zyklus.

vielen Dank für den Hinweis. Momentan bin ich erstmal froh das es jetzt 
überhaupt läuft. Aber ich werde später bestimmt noch einiges Optimieren.

> bei VDSP diverse Moeglichkeiten, Memory-Inhalte zu plotten.

Das habe ich auch gelesen, bin mit dem Plotting-tool nicht so richtig 
warm geworden. Es gibt x verschiedene Einstellmöglichkeiten, aber 
irgendwie sah die resultierende Kurve immer murks aus.

Das Beispiel Programm von Analog "Audio Codec Talkthrough - I2S (C)" 
sieht vor das sämtliche Algorithmen innerhalb eines Interrupts 
abgearbeitet werden. Ist das üblich? Wenn ich einen sehr 
rechenintensiven Filter dort laufen lasse, kann es doch passieren das 
mein Zeitfenster bis zum nächsten Interrupt nicht ausreicht um den 
Interrupt "ordentlich" zu beenden, oder?

Grüße, Christoph

von Strubi (Gast)


Lesenswert?

Hi Christoph,

Die Daten wuerde ich auch nicht im Interrupt bearbeiten. Leider sind die 
Examples aus dem VDK etwas 'sparsam'. Die typische Vorgehensweise ist 
die:

1. Stichwort Ping-Pong-Buffer: zwei verkettete DMA-Buffer, die per DMA 
laufend vom SPORT gefuellt wuerden.
2. Wenn ein Buffer voll ist, wird ein Interrupt ausgeloest, in der 
IRQ-Routine fuehrst du die Zeiger nach
3. Im 'user space' holst Du die Daten aus dem vollen Buffer und 
verarbeitest sie moeglichst in Echtzeit (was beim Blackfin kein Problem 
sein sollte).

Bei der Soundverarbeitung willst Du ja moeglichst geringe Latenzen, 
deswegen kurze Buffer queues. Wenn allerdings andere Sachen das System 
ausbremsen, musst du aus dem Ping-Pong-Buffer eine laengere 
Ring-Buffer-Queue machen - damit reisst Dir der Datenstrom nicht ab, 
aber du hast halt groessere 'latencies'.

Fuer ein Effekt-Geraet, das gleichzeitig I/O macht, hat man dann 
normalerweise zwei Queues, und laesst einfach den DMA immer weiter 
laufen.
Der Gag am Blackfin ist die echt starke DMA-Engine - die Verarbeitung 
also nur mit einem Mindestbedarf an Interrupts zu loesen, spart Dir 
massiv Rechenzeit.

Gruss,

- Strubi

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.