Altera Max II SPDIF sample rate detectie

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 10:30

voodooless

Sound is no voodoo!

Topicstarter
Ik ben momenteel aan het spelen met de Altera Quartus II Web edition IDE. Morgen zal er naar alle waarschijnlijkheid een developmentkitje in de bus komen te liggen voor de Max II CPLD. Deze wil ik gebruiken om voor mijn voorversterker diverse digitale spullen aan te sturen:

- via een serieel protocol de volume regeling en analoge bron keuze aansturen
- via een LED driver een hele berg ledjes (kan ook via losse IO's, maar dan worden grijstinten wat lastiger)
- een aantal knopjes
- een rotary encoder
- eventueel IR ontvanger
- SPDIF, I2S en DSD (allemaal twee ingangen) switchen en naar de DAC sturen.
- wat relais schakelen voor power management

Uiteindelijk moet het er dan ongeveer zo uitzien:

Afbeeldingslocatie: http://voodooless.com/voodoopre/pre-amp_front_small.png

Wat ik nu heel graag wil, is de samplerate weergeven van het ontvangen digitale signaal. Ik vind het verder niet erg interessant wat de data van dat signaal is, samplerate is van belang. Bij DSD zijn we snel klaar, want dat is altijd 2.8 Mhz (in ieder geval bij consumer audio), en dat wil ik verder ook niet weergeven. I2S heeft een L/R clock signaal welk als het goed is met dubbele samplerate op en neer flipt, dus opgaande flanken zijn netjes op audio sample rate. Met de 50 Mhz reference klok op het development bordje kan ik prima kloktikken tellen en aan de hand van het getelde aantal kun je makkelijk zeggen wat de sample rate is (binnen marges natuurlijk, maar dat is goed genoeg).

Bij SPDIF is het echter een heel ander verhaal. Dit signaal heeft klok en het signaal gemultiplexed door middel van Bi-Phase mask code. Nu geldt hier dat een opvolging van 0 en 1 met maximaal 64*sample rate (32 bits per frame, twee kanalen) gaat (alleen enen) en minimaal 32 keer sample rate (alleen nullen). Dit komt in de praktijk echter nooit voor. Wat ik nu zou kunnen doen is het aantal ticks tellen van de snelste of langzaamste transitie, echter kom ik hier in de problemen als ik onderscheid wil gaan maken tussen alles hoger dan 88.2 Khz. Daar komen de delers namelijk netjes op de zelfde getallen uit (voor 88.2 en 96, 176.4 en 192). Daar heb ik dus weinig aan helaas. Ik zoek dus een andere eenvoudige methode om dit wel voor elkaar te krijgen. Misschien kan ik iets met de preamble doen. Deze heeft een lengte van 4 bits en bevat geen biphase mark code. De preamble bevat altijd een reeks van drie eentjes, dus drie snelle transities achter elkaar, iets wat eigenlijk niet zou mogen. Ook bevat deze altijd drie nullen. Het is misschien een idee om juist dit te detecteren en te tellen.

Ik hoop dat jullie misschien nog wat andere ideeën hebben? Het moet vooral niet te complex gaan worden :*)

Do diamonds shine on the dark side of the moon :?


Acties:
  • 0 Henk 'm!

  • Sprite_tm
  • Registratie: September 2002
  • Laatst online: 11-08 04:52

Sprite_tm

Semi-Chinees

Ik denk dat de preamble detecteren idd een hele goede is. Die is redelijk met dat soort sync-mogelijkheden in gedachte gemaakt waarschijnlijk :)

Relaxen und watchen das blinkenlichten. | Laatste project: Ikea Frekvens oog


Acties:
  • 0 Henk 'm!

  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 10:30

voodooless

Sound is no voodoo!

Topicstarter
Dan is de vraag hoe ik dat precies ga doen... Drie bit lengtes is een uitzonderingen op alle andere signaalovergangen die een en twee bits lang kunnen zijn:

code:
1
2
3
4
5
6
  _   _
_| |_| |   normaal
    ___
___|   |   normaal
     ___    
____|      preamble


Op de een of andere manier moet ik zien bij te houden hoe lang elk van deze drie overgangen is, en dan over een langere tijd tellen hoeveel preambles er zijn geweest.

Ik zal even proberen om iets in pseudo code te fixen:

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#define REF_CLK_TICKS_PER_SECOND 50000000;
#define 44_1_KHZ xxxxxx;
#define 48_KHZ xxxxxx;
#define 88_2_KHZ xxxxxx;
#define 96_KHZ xxxxxx;
#define 176_4_KHZ xxxxxx;
#define 192_KHZ xxxxxx;

input spdif_in;
input ref_clk;
output [0:5] sample_rate;

int clk_count = 0;
int clk_count_2 = 0;
int preamble_count = 0;
int filler = 0;
int spdif_tick_count = 0;
boolean has_short_tick = false;
int temp_spdif_clock_tick_count = 0;
int temp_spdif_preamble_tick_count = 0;
int min_spdif_clock_tick = REF_CLK_TICKS_PER_SECOND;


// process om referentie klok tikken te tellen
altijd_op(opgaande of neergaande flank van ref_clk){
   clk_count = clk_count + 1;
   clk_count_2 = clk_count_2 + 1;
}

altijd_op(opgaande of neergaande flank van ref_clk){
    // kopieer ticks sinds laatste flank naar temp var
    temp_spdif_clock_tick_count =  clk_count ;
    // we tellen ook spdif ticks
    spdif_tick_count = spdif_tick_count+1
    // begin opnieuw te tellen
    clk_count = 0;
    // als SPDIF tick kleiner is dan de voorheen minimale tick
    if(min_spdif_clock_tick > temp_spdif_clock_tick_count){
        // hebben we een nieuwe minimale tick
        min_spdif_clock_tick = temp_spdif_clock_tick_count;
        spdif_tick_count = 0;
    } else if(temp_spdif_clock_tick_count == min_spdif_clock_tick){
        has_short_tick = true;
    }
    // detectie van sample rate wisseling
    if(spdif_tick_count==128){
        if(has_short_tick){
            // niks aan de hand, we checken gewoon weer opnieuw;
            has_short_tick = false;
            spdif_tick_count = 0;
        } else {
            // sample rate wisseling, we gaan opnieuw zoeken naar de kortste tick
            min_spdif_clock_tick = REF_CLK_TICKS_PER_SECOND;
            clk_count_2 = 0;
            preamble_count = 0;
            spdif_tick_count = 0;
            filler = 0;
            sample_rate = 0;
        }
    }
    
    if(filler>128 && abs((min_spdif_clock_tick+min_spdif_clock_tick+min_spdif_clock_tick)-temp_spdif_clock_tick_count)<2){
        // we hebben een tick die ongeveer drie keer zo lang als de minimale tijd
        preamble_count = preamble_count + 1;
    } else if (filler <128){
        // om ervoor te zorgen dat we in het begin echt de minimale waarde te pakken krijgen, gaan we 128 ticks wachten met zoeken
        filler = filer +1;
    } 
    if (filler == 128){
        // na 128 ticks gaan we echt beginnen
        clk_count_2 = 0;
        preamble_count = 0;
    }
    
    
    if(preamble_count = 128){
        // aantal referentie klock tikken per 128 preambles
        temp_spdif_preamble_tick_count = clk_count_2;
        clk_count_2 = 0;
        // zet output
        switch(temp_spdif_preamble_tick_count){
            case: 44_1_KHZ:
                sample_rate = 1; break;
            case: 48_KHZ:
                sample_rate = 2; break;
            case: 88_2_KHZ:
                sample_rate = 4; break;
            case: 96_KHZ:
                sample_rate = 8; break;
            case: 176_4_KHZ:
                sample_rate = 16; break;
            case: 192_KHZ:
                sample_rate = 32; break;
        }
        // we beginnen opnieuw
        preamble_count = 0;
    }
    
}



In basis probeer ik de kleinste tick te ontdekken, en aan de hand daarvan probeer ik de tick te tellen die drie keer zo groot zijn (dat zijn de preambles). Ik tel dan de referentie klok tikken voor een vast aantal preambles. Dit aantal kun je vrijwel direct omzetten in een van de sample rates aangezien dit aantal behoorlijk statisch zou moeten zijn. Misschien moet er hier wel met wat mages gewerkt worden, maar die heb ik voor het gemak even niet meegenomen.

Verder zit er een detectie in voor sample rate verandering. De minimale tick moet minstens een keer per 128 ticks voorkomen. Zoniet begint het detectieproces opnieuw.

Helaas is dit niet zo heel makkelijk om te zetten naar Verilog of VHDL. De dingen die nu sequentieel staan worden namelijk parallel uitgevoerd en aangezien er dingen in zitten die afhankelijk zijn van elkaar, gaat dat gewoon een gigantische bende worden :( . Ik zal me eens in de literatuur gaan inlezen hoe ik hier weer HDL kaas van kan maken ;) Ik gok iets met states en opdelen in logsche blokken... Opmerkingen zijn natuurlijk welkom!

[ Voor 87% gewijzigd door voodooless op 06-01-2010 21:55 ]

Do diamonds shine on the dark side of the moon :?


Acties:
  • 0 Henk 'm!

  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 10:30

voodooless

Sound is no voodoo!

Topicstarter
Geen commentaar :?

Maar ondertussen kan het misschien op een heel wat makkelijkere manier. De DAC heeft namelijk wat I2C registers waaruit je eenvoudig de sample rate kan uitlezen. Het probleem is echter dat ik de datasheet van de DAC niet heb. Die is enkel onder NDA verkrijgbaar. Nu hoop ik dat ik deze mag tekenen zodat ik de nodige info eruit kan halen. Het leuke is dat je dan ook nog flink wat dingen in de DAC kan instellen :)

Ondertussen is het bordje nog bij FedEx... Ik vraag me serieus af waar de Ex in FedEx vandaan komt? De eerste keer komen ze niet als ik er niet ben. Dat snap ik nog. Ik heb gebeld en gezegd dat er vanmiddag na 14:00 iemand thuis zou zijn. Dat was prima volgens FedEx, zo zouden pas na 14:00 uur komen... En wanneer komen ze dan: juist, om 12:00 uur 8)7 .. En dan wil je ze bellen, zijn ze het hele weekeind dicht :X En naar een andere locatie sturen wilden ze niet omdat dat een ander district is... nu moeten ze voor de 3e keer langs... Slechte service voor zoveel verzendkosten -O-

[ Voor 3% gewijzigd door voodooless op 08-01-2010 19:34 ]

Do diamonds shine on the dark side of the moon :?