Forum: Mikrocontroller und Digitale Elektronik MOS6581/Commodore SID Timing?


von Edward (Gast)


Lesenswert?

Moin,

Ich bin seit einigen Monaten ein Projekt mit einem Commodore SID 
(MOS6581)
aufzubauen. Der SID wird dabei mit einem Atmel AVR ATMega gesteuert.

Adressleitungen sind an PORTA angeschlossen, Daten an PORTC
und PORTD5 ist CLK und PORTD7 ist /CS. Reset ist an VCC
angeschlossen und R/W an GND.

Trotzdem kommt mit dem Testprogramm kein Ton raus.

Der C-Source (nur provisorisch zum testen) sieht folgendermaßen aus:

1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
5
// 1MHz CLK for SID on PORTD5 (OC1A)
6
void initTimer(void)
7
{
8
        TCNT0 = 0;
9
        OCR1A = 7;
10
        TCCR1B = 0b00001001;
11
        TCCR1A = 0b01000000;
12
}
13
14
void initMos(void)
15
{
16
        DDRA = 0xFF;         // ADDR
17
        DDRC = 0xFF;         // DATA
18
        DDRD |= (1 << PIND7); // CS
19
20
        PORTA = 0x00;
21
        PORTC = 0x00;
22
23
        PORTD |= (1 << PIND7);                             // Initialize with /CS on.
24
}
25
26
void writeMos(uint8_t addr, uint8_t data)
27
{
28
        PORTA = addr;
29
        PORTC = data;
30
        while(!PORTD5){};       // Wait for sync
31
        PORTD &= ~(1 << PIND7);
32
        while(PORTD5){};        // Wait for sync
33
        PORTD |= (1 << PIND7);
34
}
35
36
void testSID(void)
37
{
38
        writeMos(24, 15);
39
        writeMos(0, 196);
40
        writeMos(1, 9);
41
        writeMos(5, 105);
42
        writeMos(6, 252);
43
        writeMos(4, 33);
44
}
45
46
int main(void)
47
{
48
        _delay_ms(1000);
49
         DDRD |= (1 << PB5);
50
        initMos();
51
        initTimer();
52
        while(1)
53
        {
54
                testSID();
55
56
                _delay_ms(2000);
57
                _delay_ms(2000);
58
                _delay_ms(2000);
59
        }
60
}

Hier noch das original Timing-Diagramm:
http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#6581_.28SID.29_Timing

Oder verstehe ich das falsch?

von hp-freund (Gast)


Lesenswert?

Prüf mal:

while(!PORTD5){};       // Wait for sync

von Edward (Gast)


Lesenswert?

hp-freund schrieb:
> Prüf mal:
>
> while(!PORTD5){};       // Wait for sync


Was genau meinst du?
Auf PORTD5 liegt das CLK-Signal, welches durch den Timer0 generiert 
wird.

von Torsten S. (tse)


Lesenswert?

Probier mal

while(!(PIND >> PD5) & 0x01) {};

von Simon B. (nomis)


Lesenswert?

PORTD5 ist fest definiert auf 5, d.h. darin wird nicht der Zustand des 
5. Pins von Port D wiedergespiegelt. Das ist nur eine Hilfe um die 
Pin->Bitzuordnung wegzuabstrahieren.

Mit

  while (!(PORTD & (1<<PORTD5))) {}

bzw.
  while (PORTD & (1<<PORTD5)) {}

könnte es besser gehen.

Thorsten schlägt noch vor, PIND zu verwenden, da bin ich mir allerdings 
gerade nicht sicher. Der Port ist ja als Output konfiguriert, von daher 
klingt PORTD eigentlich schon ganz sinnvoll...

Viele Grüße,
          Simon

Nachtrag: Gerade nochmal nachgeguckt, PIND sollte funktionieren: 
"Independent of the setting of Data Direction bit DDxn, the port pin can 
be read through the PINxn Register bit"

von Jobst M. (jobstens-de)


Angehängte Dateien:

Lesenswert?

Vielleicht hilft dies weiter.


Gruß

Jobst

von Edward (Gast)


Angehängte Dateien:

Lesenswert?

Moin,

Danke für die bisherigen Tipps.

Mit:
1
void writeMos(uint8_t addr, uint8_t data)
2
{
3
        PORTA = addr;
4
        PORTC = data;
5
        while(!(PIND >> PD5) & 0x01) {};
6
        PORTD &= ~(1 << PIND7);
7
        while (PIND & (1<<PIND5)) {}
8
        PORTD |= (1 << PIND7);
9
}

Im Anhang ein Screenshot vom Logic Analyzer.

Noch leider kommt trotzdem kein Ton raus.

von Edward (Gast)


Lesenswert?

Ups.

Das war der falsche Copy&Paste-Buffer.

Hier noch mal:
1
void writeMos(uint8_t addr, uint8_t data)
2
{
3
        PORTA = addr;
4
        PORTC = data;
5
    
6
        while(!(PIND >> PIND5) & 0x01) {};
7
        PORTD &= ~(1 << PIND7);
8
9
        while (PIND & (1<<PIND5)){};
10
        PORTD |= (1 << PIND7);
11
    
12
}

von Edward (Gast)


Angehängte Dateien:

Lesenswert?

Moin,

Hier noch mal ein neuer source-code.

Das Ganze funktioniert leider immer noch nicht und ich bin langsam
am verzweifeln.

Gruß,
Edward

von Edward (Gast)


Angehängte Dateien:

Lesenswert?

Sorry, im .zip-Archiv fehlten dateien.

von Simon B. (nomis)


Lesenswert?

Also, ich lese das Datenblatt so, dass er die Daten bei fallender CLK 
sampled. Solange hältst Du aber das CS nicht.

Versuch mal hinzukriegen, dass die Pegelwechsel sauber in der Mitte der 
Clock-Pulse passieren. Sobald Du Dich da fix an die Flankenwechsel der 
CLK hängst, können sehr schnell irgendwelche Zufallseffekte die 
Kommunikation verhindern.

Viele Grüße,
        Simon

von Edward (Gast)


Lesenswert?

Simon Budig schrieb:
> Versuch mal hinzukriegen, dass die Pegelwechsel sauber in der Mitte der
> Clock-Pulse passieren. Sobald Du Dich da fix an die Flankenwechsel der
> CLK hängst, können sehr schnell irgendwelche Zufallseffekte die
> Kommunikation verhindern.

Das habe ich in der mos6581.c versucht zu erreichen:
1
void MOS6581_WriteByte(uint8_t i_addr, uint8_t i_data)
2
{
3
        PORT_ADDR = i_addr;                             // Addr on PORT_ADDR.
4
        PORT_DATA = i_data;                             // Data on PORT_DATA
5
6
        while(!(PPIN_OC1A >> PIN_OC1A) & 0x01){};       // Wait until clock
7
                                                        // state changes.
8
9
        PORT_CTL &= ~(_BV(PIN_CS));                     // Set /CS low
10
                                                        // (SID active).
11
12
        while(PPIN_OC1A & _BV(PIN_OC1A)){};             // Wait until clock
13
                                                        // state changes.
14
15
        PORT_CTL |= (_BV(PIN_CS));                      // Set /CS high
16
}

von Edward (Gast)


Lesenswert?

Bisher noch kein Erfolg. Aber trotzdem vielen Dank fuer die bisherigen
Tips.

Ich hab leider nur einen 8-Kanal Logic-Analyzer hier.
Sonst wuerde ich gerne auch einen Screenshot von
DATA + ADDR + CLK + CS zeigen.

von Simon B. (nomis)


Lesenswert?

Guck Dir mal Deinen Screenshot vom Oszi an: Da wird bei +8us das CS auf 
low gezogen. Bei +8.25 (oder so) geht der schon wieder high und das 
kommt mir komisch vor. Ich vermute, dass er frühestens bei +9us wieder 
high gehen sollte, damit der SID eine Chance hat, den Registerwert bei 
+8.75 zu samplen.

Gegebenenfalls bau das mal auf eine harte Abfolge von Befehlen mit NOPs 
dazwischen um, um das Timing sauber hinzukriegen.

Viele Grüße,
        Simon

von chris (Gast)


Lesenswert?

Hallo Edward,

kennst Du diese Seite hier?

http://roboterclub-freiburg.de/atmega_sound/atmegaSID.html

Passt vielleicht auch noch zu Deinem Projekt.

Gruß,
chris

von Edward (Gast)


Lesenswert?

Ja, die Seite kenne ich. Wollte jedoch den echten SID verwenden.

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.