Skocz do zawartości

[STM32F407] Próbuję zdebugować kodek WM8731


atlantis86

Pomocna odpowiedź

Kontynuuję uruchamianie projektu wykorzystującego mikrokontroler STM32F407. Z ważniejszych peryferiów został mi już tylko do uruchomienia kodek audio WM8731.

Mój testowy kod do obsługi tego układu wygląda następująco:

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include "stm32f4xx_hal.h"
#include "main.h"

#define WM8731_ADDR		(0x1A << 1)
//#define WM8731_ADDR		0x1A

extern I2C_HandleTypeDef hi2c1;
extern I2S_HandleTypeDef hi2s3;


#define AUDIO_BUFFER_SIZE		2200
static int16_t audio_data[2 * AUDIO_BUFFER_SIZE];


static void wm8731_write_reg(uint8_t reg, uint8_t value) {
	uint16_t data = 0;
	data = ((uint16_t)reg << 9) | (uint16_t) value;

	HAL_I2C_Master_Transmit(&hi2c1, WM8731_ADDR, (uint8_t*)&data, 2, HAL_MAX_DELAY);
	//HAL_I2C_Mem_Write(&hi2c1, WM8731_ADDR, reg, 1, &value, 1, HAL_MAX_DELAY);
}


static void fill_audio_buffer (void) {
    for (int i = 0; i < AUDIO_BUFFER_SIZE; i++) {
        int16_t value = (int16_t)(32000.0 * sin(2.0 * M_PI * i / 22.0));
        audio_data[i * 2] = value;
        audio_data[i * 2 + 1] = value;
    }
}


void wm8731_set_in_volume(int vol) {
    // -23 <= vol <= 8
    const unsigned involume = 0x17 + vol;
    wm8731_write_reg(0x00, 0x100 | (involume & 0x1f)); // Left line in, unmute
}

void wm_8731_set_out_volume(int voldB) {
    // -73 <= voldB <= 6
    const unsigned volume = 121 + voldB;
    wm8731_write_reg(0x02, 0x100 | (volume & 0x7f)); // Left headphone
    wm8731_write_reg(0x03, 0x100 | (volume & 0x7f)); // Right headphone
}

void wm8731_init(void) {
	wm8731_write_reg(0x0f, 0b000000000); // Reset!
	wm8731_set_in_volume(0);
    wm_8731_set_out_volume(-10);
    wm8731_write_reg(0x04, 0b000010010); // Analog path - select DAC, no bypass
#ifdef WM8731_HIGHPASS
    wm8731_write_reg(0x05, 0b000000000); // Digital path - disable soft mute
#else
    wm8731_write_reg(0x05, 0b000000001); // Digital path - disable soft mute and highpass
#endif
    wm8731_write_reg(0x06, 0b000000000); // Power down control - enable everything
    wm8731_write_reg(0x07, 0b000000010); // Interface format - 16-bit I2S
    wm8731_write_reg(0x09, 0b000000001); // Active control - engage!

    fill_audio_buffer();
    HAL_I2S_Transmit_DMA(&hi2s3, (uint16_t*)audio_data, 2 * AUDIO_BUFFER_SIZE);
}

Wzorowałem się przede wszystkim na tym kodzie z GitHuba.

W STM32CubeMX I2S skonfigurowany do pracy z częstotliwością 22 kHz, ramki 16 bitowe, dane wysyłane przez DMA (circular, half-word). Jak widać w powyższym kodzie przy inicjacji układu wypełniam bufor próbkami składającymi się (z grubsza) na sinusoidę a potem rozpoczynam wysyłanie danych z tego bufora przez DMA. Wcześniej przesyłam przez I2C trochę danych konfiguracyjnych (których jeszcze dokładnie nie porównywałem z datasheetem, ale wydają się być ok).

Niestety, w słuchawkach podłączonych do wyjścia układu niczego nie słyszę.

Podłączyłem analizator stanów logicznych do magistrali I2S. Wydaje się być ok.

i2s.thumb.png.7aeeb74f4ac513e5829192bb937b161c.png

Może poza tym jednym błędem, który pojawia się od czasu do czasu, ale to może być już kwestią analizatora. Zresztą jeśli dobrze rozumiem, to nie spowodowałby on całkowitego braku sygnału:

i2s_error.thumb.png.e33ee34a1d48c653900b4031f00d0bc5.png

 

Następną rzeczą do zrobienia było sprawdzenie jak wygląda transmisja na I2C przy konfiguracji układu:

wm8731_i2c.thumb.png.817eed93cb3ff2a6d7b538d4f963ff6c.png

W pliku zip wrzucam kompletne zestawy danych z analizatora stanów logicznych.

Schemat przyległości układu wm8731 wygląda następująco:

wm8731_sch.thumb.png.d194a602d79d67e92a953e09368f1954.png

Schemat właściwie sprawdzony - skopiowany z innego, przetestowanego układu, gdzie był używany z Raspberry Pi Zero. Nie sądzę więc, żeby to tu był problem, le wrzucam na wszelki wypadek.

Ktoś ma pomysł co może być nie tak i co jeszcze mogę sprawdzić?

analizator.zip

 

EDIT: Ok, spojrzałem jeszcze raz na dane przechwycone podczas transmisji I2C. Tym razem obejrzałem je w wersji binarnej. Zgodnie z dokumentacją układu transmisja powinna składać się z dwój bajtów.

Pierwszy z nich zwiera następujące dane:
b7..b5 - bez znaczenia
b4..b1 - adres rejestru
b0 - najbrdziej znaczący z dziewięciu bitów danych

Drugi bajt to pozostałe osiem bitów danych.

Jak widać na poniższym przykładzie, te bajty są przesyłane w odwrotnej kolejności.

i2c_rev.png.ee0799ffb15e34957ae61d17ee0dd843.png

Ktoś wie dlaczego tak się dzieje?

 

EDIT: Kolejny update. Przyglądając się kodowi zauważyłem, że popełniłem szkolny błąd - nie zwróciłem uwagi na kolejność bajtów w pamięcie (endianness). Poprawiłem funkcję wysyłającą dane, teraz wygląd ona następująco:

static void wm8731_write_reg(uint8_t reg, uint16_t value) {
	uint16_t tmp = 0;
	uint8_t data[2];

	tmp = ((uint16_t)reg << 9) | value;
	data[0] = (tmp & 0xFF00) >> 8;
	data[1] = tmp & 0x00FF;

	HAL_I2C_Master_Transmit(&hi2c1, WM8731_ADDR, data, 2, HAL_MAX_DELAY);
}

Sygnał się pojawił. Poradziłem sobie sam, ale zostawiam to tutaj w razie gdyby komuś te informacje się przydały. 😉 

Edytowano przez atlantis86
  • Lubię! 2
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.