Elektroda.pl
Elektroda.pl
X
Elektroda.pl
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Atmega 32 TDA 1543 odtwarzacz WAV

05 Maj 2010 21:32 4508 11
  • Poziom 13  
    Witam wszystkich :)
    Jakiś czas temu złożyłem odtwarzacz plików dźwiękowych wav korzystający z wbudowanego w atmege32 PWM 8 bit-owego, postanowiłem poprawić jakość odtwarzanego dźwięku poprzez dodanie zewnętrznego DAC-a którym jest TDA1543 . Pojawiło się kilka problemów ponieważ nie wiem w jaki sposób mogę podłączyć i odpowiednio przerobić kod programu . Czytałem ze ten przetwornik jest na szynie "i2s" i że trzeba go emulować na SPI i zastanawiam się w jaki sposób to rozwiązać ponieważ na sprzętowym spi mam podłączoną kartę SD a na programowym SPI lcd graficzny od noki 6100. Niżej zamieszczam kod programu z którego korzystałem wcześniej :
    Pozdrawiam serdecznie i proszę o pomoc :D
    Code:
    $regfile = "m32def.dat"
    
    $crystal = 16000000
    $lib "Lcd-pcf8833.lbx "                                     'special color display support                                         '8 MHz
    $hwstack = 128
    $swstack = 64
    $framesize = 64
    Config Graphlcd = Color , Controlport = Portc , Cs = 3 , Rs = 2 , Scl = 0 , Sda = 1
    '-------------------------------------------------------------------------------
    Dim Timer1_licznik As Byte
    Dim Buffer(256) As Byte At 1024                             ' bylo 256  1024
    Dim Write_position As Byte
    Dim Read_position As Byte
    Dim Write_position_word As Word
    Dim S As String * 36
    Dim A As Byte
    Dim B As Word
    '-------------------------------------------------------------------------------
    Const Blue = &B00000011                                     'predefined contants are making programming easier
    Const Yellow = &B11111100
    Const Red = &B11100000
    Const Green = &B00011100
    Const Black = &B00000000
    Const White = &B11111111
    Const Brightgreen = &B00111110
    Const Darkgreen = &B00010100
    Const Darkred = &B10100000
    Const Darkblue = &B00000010
    Const Brightblue = &B00011111
    Const Orange = &B11111000
    Glcdcmd &H36                                                'Mem_control
    Glcddata &H48                                               'My=0 Mx=0 V=1 Lao=1 Rbg=0 "00110000"
    Glcdcmd &H21
    Box(0 , 0) -(132 , 132) , White
    '-------------------------------------------------------------------------------
    On Timer1 Timer1_handler Nosave
    '-------------------------------------------------------------------------------
    'Config Porta = &B00000000
    'Config Portc = &B00000000
    'Config Portb = &B00000000
    Config Portd = &B00100000                                   'OCR1A = Output
    'Porta = &B00000000
    'Portc = &B00000000
    'Portb = &B00000000
    Portd = &B00000000
    'Config Porta.7 = Output
    'Set Porta.7
    'Porta.7 Alias Buzzer
    '-------------------------------------------------------------------------------
    Config Pinb.0 = Input : Set Portb.0 : Pinb.0 Alias S1       ' Guzik 1
    Config Pinb.1 = Input : Set Portb.1 : Pinb.1 Alias S2       ' Guzik 2
    '-------------------------------------------------------------------------------
    Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Down , Prescale = 1
    Pwm1a = 0                                                   ' Głosnik
    Pwm1b = 150                                                 ' Podświetlanie LCD
    $include "CONFIG_AVR-DOS.Bas"
    'Config Watchdog = 1024
    Config Clock = Soft
    '-------------------------------------------------------------------------------
    Const Cmmc_soft = 0                                         'SPI HARDWARE


    #if Cmmc_soft = 0

    ' --------- Start of Section for HW-SPI ----------------------------------------

       ' define Chip-Select Pin
       Config Pinb.4 = Output                                   ' define here Pin for CS of MMC/SD Card
       Mmc_cs Alias Portb.4
       Set Mmc_cs

       ' Define here SS Pin of HW-SPI of the CPU (f.e. Pinb.0 on M128)
       Config Pinb.7 = Output                                   ' define here Pin of SPI SS
       Spi_ss Alias Portb.7
       Set Spi_ss                                               ' Set SPI-SS to Output and High por Proper work of
                                                      ' SPI as Master

       ' HW-SPI is configured to highest Speed
      Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = High , Phase = 1 , Clockrate = 4 , Noss = 1       'Config Spi = Soft , Din = Pinb.3 , Dout = Portb.2 , Ss = Portb.0 , Clock = Portb.1
       Spsr.0 = 1                                               ' Double speed on ATMega128
       Spiinit                                                  ' Init SPI

    ' --------- End of Section for HW-SPI ------------------------------------------

    #else                                                       ' Config here SPI pins, if not using HW SPI

    ' --------- Start of Section for Soft-SPI --------------------------------------

       ' Chip Select Pin  => Pin 1 of MMC/SD
       Config Pinb.4 = Output
       Mmc_cs Alias Portb.4
       Set Mmc_cs

       ' MOSI - Pin  => Pin 2 of MMC/SD
       Config Pinb.5 = Output
       Set Pinb.5
       Mmc_portmosi Alias Portb
       Bmmc_mosi Alias 5

       '' MISO - Pin  => Pin 7 of MMC/SD
       Config Pinb.6 = Input
       Mmc_portmiso Alias Pinb
       Bmmc_miso Alias 6

       ' SCK - Pin  => Pin 5 of MMC/SD
       Config Pinb.7 = Output
       Set Pinb.7
       Mmc_portsck Alias Portb
       Bmmc_sck Alias 7

    ' --------- End of Section for Soft-SPI ----------------------------------------

    #endif

    ' ========== End of user definable range =======================================

    Spiinit
    ' Error
    Const Cperrdrpinb.9ivereset = 225                           ' Error response Byte at Reset command
    Const Cperrdriveinit = 226                                  ' Error response Byte at Init Command
    Const Cperrdrivereadcommand = 227                           ' Error response Byte at Read Command
    Const Cperrdrivewritecommand = 228                          ' Error response Byte at Write Command
    Const Cperrdrivereadresponse = 229                          ' No Data response Byte from MMC at Read
    Const Cperrdrivewriteresponse = 230                         ' No Data response Byte from MMC at Write
    Const Cperrdrive = 231
    Const Cperrdrivenotsupported = 232                          ' return code for DriveGetIdentity, not supported yet
    Waitms 1
    Dim Gbdriveerror As Byte                                    ' General Driver Error register
    Dim Gbdriveerrorreg As Byte                                 ' Driver load Error-Register of HD in case of error
    Dim Gbdrivestatusreg As Byte                                ' Driver load Status-Register of HD on case of error
    Dim Gbdrivedebug As Byte
    $lib "MMC.LIB"                                              ' link driver library
    $external _mmc
    'Gbdriveerror = Driveinit()                                  ' Init MMC/SD Card
    Enable Interrupts
    '-------------------------------------------------------------------------------
    B = Drivecheck()                                            'u mnie te drivechecki itp. nigdy nie dawały errora ale dałem, żeby było
    Gbdriveerror = Driveinit()
    B = Initfilesystem(1)
    S = Dir( " * .txt")
    Dim Rozmiar As Long
    Rozmiar = Disksize() \ 1000
    Dim Wolne As Long
    Wolne = Diskfree() \ 1000
    Dim Lista As String * 6
    Dim Numer As Byte
    Numer = 5
    Dim Poczatek As Byte
    Dim Ilosc As Byte
    Dim Dlugosc As Byte
    Poczatek = 1
    Ilosc = 5
    Dlugosc = 5
    '-------------------------------------------------------------------------------
    Setfont Color8x8
    Poczatek:
    '-------------------------------------------------------------------------------
    Lcdat , 10 , 2 , "AVR-DOS v 2.0" , Black , White
    Lcdat , 20 , 2 , "Atmega 32-16PU " , Black , White
    Lcdat , 30 , 2 , "CPU at 16 Mhz" , Black , White
    Lcdat , 40 , 2 , "Ram size : 2 KB" , Black , White
    Lcdat , 50 , 2 , "LCD PCF-8833" , Black , White
    Lcdat , 60 , 2 , "Karta SD info" , Black , White
    Lcdat , 70 , 2 , "Rozmiar: " ; Rozmiar ; " MB" , Black , White
    Lcdat , 80 , 2 , "Wolne  : " ; Wolne ; " MB" , Black , White
    Lcdat , 90 , 2 , "System OK" , Black , White
    Bitwait Pinb.0 , Reset
    '-------------------------------------------------------------------------------
    Cls
    Box(0 , 0) -(132 , 132) , Brightblue
    Lcdat 10 , 15 , "Playlista" , Blue , Brightblue
    Lcdat 20 , 10 , "Utwory w liscie" , Darkred , Brightblue
    'Poczatek:
    Open "lista.txt" For Input As #1
    Line Input #1 , S
    Waitms 100
    Lista = Mid(s , Poczatek , Ilosc)
    'Lista = Right(s , Numer)
    Close #1
    Waitms 100
    Lcdat 30 , 5 , S , Black , Brightblue
    Lcdat 50 , 5 , "Odtwarzam " ; Lista , Darkgreen , Brightblue
    Lcdat 60 , 7 , Lista , Darkred , White
    Open Lista For Binary As #2
    For Write_position_word = 1 To 256                          ' bylo 256
      Get #2 , Buffer(write_position_word)
    Next Write_position_word
    Write_position = 0
    Enable Timer1
    Do
        If Write_position <> Read_position Then
            Get #2 , A

           lds R16, {A}
           ldi R27, 4                                           '<------------------- Starsza połówka adresu bufora. Np. 4 = High(1024)
           lds R26, {Write_position}
           st X+, R16                                           'To powoduje zawieszanie
           sts {Write_position}, R26





            'lds R16, {A}
           ' subi R16, 128
           ' lds R17, 255                                        'Od 0 do 255
           ' mulsu R16, R17
           ' mov R16, R1
           ' subi R16, 128
           ' ldi R27, 4                                          '<------------------- Starsza połówka adresu bufora. Np. 4 = High(1024)
           ' lds R26, {Write_position}
           ' st X+, R16                                          'To powoduje zawieszanie
           ' sts {Write_position}, R26




        End If
    Loop Until Eof(#2) <> 0
    '-------------------------------------------------------------------------------
    Cls
    Lcdat 20 , 5 , "nastapi reset" , Darkred , White
    Lcdat 30 , 5 , "wcisnij s2" , Darkred , White
    Lcdat 40 , 5 , "Poczatek " ; Poczatek , Darkred , White
    Bitwait Pinb.1 , Reset
    For Write_position_word = 1 To 256                          'czyszczenie bufora
    Buffer(write_position_word) = 129
    Next Write_position_word
    Disable Timer1                                              'zatrzymanie timera1
    Close #2
    Poczatek = Poczatek + 5
    '-------------------------------------------------------------------------------
    Gosub Poczatek
    '---------------------------------------------------------------------------------
    Do
    Loop
    '-------------------------------------------------------------------------------
    Timer1_handler:
      push R16
      In R16, SREG
      push R26
      push R27


      lds R26, {Timer1_licznik}
      inc R26
      sts {Timer1_licznik}, R26
      cpi R26, 2                                                '<<<<<<<<<<<<-----------------------------------
      brlo R26_mniejsze_2
          ldi R26, 0
          sts {Timer1_licznik}, R26

          ldi R27, 4                                            '<------------------- Starsza połówka adresu bufora. Np. 4 = High(1024)
          lds R26, {Read_position}
          ld R27, X+
          !Out OCR1AH, R27                                      'Teoretycznie to też musi tutaj być.
          !Out OCR1AL, R27
          sts {Read_position}, R26
      R26_mniejsze_2:


      pop R27
      pop R26
      !Out SREG, R16
      pop R16
      Return

    End
    $include "color8x8.font"
  • Poziom 31  
  • Poziom 38  
    Jak dla mnie zawsze możesz dorzucić jeszcze jeden programowy SPI. No cóz niestety jego obsługę będziesz musiał napisać w pełni sam, bo o ile dobrze pamiętam (w bascomie nie siedzę do 3 lat) soft SPI można wykorzystać tylko 1.
  • Poziom 43  
    A ja się obawiam że wykonanie tego będzie w ogóle niemożliwe.
    I2S jest interfejsem dość szybkim a do tego niosącym zegar.
    Procesor się nie wyrobi. W jednym przerwaniu o d Timera musiał bym wysłać kilkadziesiąt bitów danych co jest już raczej niemożliwe.
    Sorki.
  • Poziom 13  
    Cześć
    Wczoraj przeglądając forum znalazłem jak jeden użytkownik napisał że udało mu się podłączyć DAC - a razem z SD na sprzętowym SPI bardzo mi zależy na tym żeby to zrobić . A może jak by do tego wykorzystać jeszcze np. Atmege8 ? Schemat zamieszczę za moment bo muszę go narysować :)


    P.S
    Atmege taktuje kwarcem o częstotliwości 16 Mhz nie próbowałem więcej bo całość zasilam z 3.6 V więc nie wiem czy więcej pójdzie.
  • Warunkowo odblokowany
    Cytat:
    I2S jest interfejsem dość szybkim a do tego niosącym zegar.

    Niesie sygnał zegarowy, jak każdy synchroniczny interfejs szeregowy, akurat w tym niewiele jest odkrywczego.
    Jest dość szybki to akurat też nie jest problem, gorzej jak by był za wolny. Nie wiem jak to wygląda w AVRach ale wiem że w 51 można było wykorzystać USART do podłączenia np. rejestru przesuwnego i wysyłania do niego danych. Natomiast nie wiem czy da sie tak skonfigurować w trybie synchronicznym USART AVR, aby nie wysyłał typowej ramki RS232 tylko sam bajt ? Jeżeli tak to jedyny problem to max szybkość jaką sie da wycisnąc, bo dla 44,1KHz trzeba by ok 1,5Mb/sek.
  • Poziom 43  
    Jacek31 napisał:
    Cytat:
    I2S jest interfejsem dość szybkim a do tego niosącym zegar.

    Niesie sygnał zegarowy, jak każdy synchroniczny interfejs szeregowy, akurat w tym niewiele jest odkrywczego.

    Owszem jest ;) Chyba nie zrozumiałeś. Niesie sygnał zegarowy do wykorzystania w DACu, a nie tylko do zsynchronizowania przesyłanych danych. A to dużo zmienia.
  • Poziom 13  
    A jeżeli bym podłączył ten przetwornik pod spi sprzętowe razem z karta SD i dane do przetwornika wysyłał bym przez polecenie SPIOUT :?: Albo jeszcze myślałem nad tym żeby kartę pamięci zostawić na sprzętowym a przetwornik dać na programowym i wtedy najwyżej zrezygnował bym z lcd i miał bym wolne programowe spi tylko nie wiem jak przełączać podczas odtwarzania muzyki odczyt z karty i wysyłanie tego co odczytane do przetwornika
  • Warunkowo odblokowany
    HM.. DAC to przetwornik C/A więc właściwie to drabinka R2R, sygnał zegarowy jest ci tylko potrzebny do wpisania danych do rejestru przesuwnego wewnątrz przetwornika do niczego więcej. Bit rejt zalerzy ci tylko od częstotliwości dostarczania danych do takiego DACa. Nawet jeżeli sygnał zegarowy jest wykorzystywany do czegoś dodatkowego ,to odbywa się to na zasadzie przetwarzania potokowego, wiec nie trzeba wytwarzać jakiś dodatkowych cykli zegarowych.
  • Specjalista - Mikrokontrolery
    Jacek31 napisał:
    HM.. DAC to przetwornik C/A więc właściwie to drabinka R2R, sygnał zegarowy jest ci tylko potrzebny do wpisania danych do rejestru przesuwnego wewnątrz przetwornika do niczego więcej. Bit rejt zalerzy ci tylko od częstotliwości dostarczania danych do takiego DACa. Nawet jeżeli sygnał zegarowy jest wykorzystywany do czegoś dodatkowego ,to odbywa się to na zasadzie przetwarzania potokowego, wiec nie trzeba wytwarzać jakiś dodatkowych cykli zegarowych.

    Problem w tym, że to nie jest SPI tylko I²S. Jak myślisz, jaki będzie efekt gdy dźwięk samplowany z częstotliwością powiedzmy 8kHz będzie zapisywany do tej drabinki R2R z inna częstotliwością lub jeszcze lepiej z całkiem przypadkową?
  • Warunkowo odblokowany
    A dla czego ma być zapisywany przypadkowo ?? To nie zależy od samego przetwornika a od tego czy CPU będzie wysyłał 8K próbek/sek tak jak należy. Interfejs jest tylko medium pośredniczącym niczym więcej, różnica miedzy SPI a I2S to tylko fakt że tu masz rozdzielczość 16 bitów na kanał, a nie 8, i nie masz zwrotnego sygnału do odbioru danych od przetwornika. Sam układ nie ma jakiś rejestrów konfiguracyjnych, więc nie ma żadnego problemu. Zadaniem CPU jest tylko dostarczać dane z odpowiednią szybkością, i tyle, a co tam sobie robi dodatkowo układ w środku to ci zwisa i dynda, to już problem jego producenta. Nota katalogowa mówi że trzeba tylko dostarczać naprzemiennie dane dla kanału lewego i prawego i wsio. Niczego nie konfigurujesz, nie ustawiasz, zwykłe wysyłanie danych do zwykłego 16 bitowego rejestru przesuwnego (właściwie 2 na przemian). Tyle od strony programisty, reszta go nie obchodzi.
    Wnikacie lub tworzycie problem który tak naprawdę nie istnieje. Mówicie coś o interfejsie, a to nie ono jest problemem tylko to czy 16MHz Avr da rady odczytać z MMC dane i przesłać je na czas do przetwornika.
  • Poziom 13  
    Ok a w jaki sposób mam wysyłać te dane do przetwornika ?

    Rozmawiajac z kilkoma osobami z forum dowiedzialem sie ze mozna emulowac kolejne spi przez specjalna wstawke w asm do bascoma ktora to umozliwi sporo szukalem w sieci ale nie znalazlem tego co mnie interesuje moze ktos z was spotkal sie z czyms takim :?: