MOS6581/Commodore SID Timing?

Gast #1818999
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?
#1819163
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"
Gast #1819224
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.
Angehängte Dateien:
Gast #1819225
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
}
#1819390
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
Gast #1819412
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
}
Gast #1819421
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.
#1819470
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren