ich baue gerade ein LED Display mit einer Matrix von 80 x 10 LEDs. Die
Zeilen werden über 10 Schieberegister per Hardware SPI angesteuert, das
funktioniert auch schon. Für einen laufenden Text muss ich jetzt die
Zeilendaten von 80Bit um eine Stelle schieben. Das habe ich auch mit
inline Assembler hinbekommen:
1
void
2
_rol_array(uint8_t*__data)
3
{
4
__asm__volatile(
5
"ld r0,%a0""\n\t"
6
"sec""\n\t"
7
"rol r0""\n\t"
8
"st %a0+,r0""\n\t"
9
10
"ld r0,%a0""\n\t"
11
"rol r0""\n\t"
12
"st %a0+,r0""\n\t"
13
14
"ld r0,%a0""\n\t"
15
"rol r0""\n\t"
16
"st %a0+,r0""\n\t"
17
18
"ld r0,%a0""\n\t"
19
"rol r0""\n\t"
20
"st %a0+,r0""\n\t"
21
22
"ld r0,%a0""\n\t"
23
"rol r0""\n\t"
24
"st %a0+,r0""\n\t"
25
26
"ld r0,%a0""\n\t"
27
"rol r0""\n\t"
28
"st %a0+,r0""\n\t"
29
30
"ld r0,%a0""\n\t"
31
"rol r0""\n\t"
32
"st %a0+,r0""\n\t"
33
34
"ld r0,%a0""\n\t"
35
"rol r0""\n\t"
36
"st %a0+,r0""\n\t"
37
38
"ld r0,%a0""\n\t"
39
"rol r0""\n\t"
40
"st %a0+,r0""\n\t"
41
42
"ld r0,%a0""\n\t"
43
"rol r0""\n\t"
44
"st %a0+,r0""\n\t"
45
46
"ld r0,%a0""\n\t"
47
"rol r0""\n\t"
48
"st %a0+,r0""\n\t"
49
50
:/* void */
51
:"e"(__data)
52
:"memory"
53
);
54
}
55
56
void
57
_ror_array(uint8_t*__data)
58
{
59
__asm__volatile(
60
"adiw %0,11""\n\t"
61
62
"ld r0,-%a0""\n\t"
63
"sec""\n\t"
64
"ror r0""\n\t"
65
"st %a0,r0""\n\t"
66
67
"ld r0,-%a0""\n\t"
68
"ror r0""\n\t"
69
"st %a0,r0""\n\t"
70
71
"ld r0,-%a0""\n\t"
72
"ror r0""\n\t"
73
"st %a0,r0""\n\t"
74
75
"ld r0,-%a0""\n\t"
76
"ror r0""\n\t"
77
"st %a0,r0""\n\t"
78
79
"ld r0,-%a0""\n\t"
80
"ror r0""\n\t"
81
"st %a0,r0""\n\t"
82
83
"ld r0,-%a0""\n\t"
84
"ror r0""\n\t"
85
"st %a0,r0""\n\t"
86
87
"ld r0,-%a0""\n\t"
88
"ror r0""\n\t"
89
"st %a0,r0""\n\t"
90
91
"ld r0,-%a0""\n\t"
92
"ror r0""\n\t"
93
"st %a0,r0""\n\t"
94
95
"ld r0,-%a0""\n\t"
96
"ror r0""\n\t"
97
"st %a0,r0""\n\t"
98
99
"ld r0,-%a0""\n\t"
100
"ror r0""\n\t"
101
"st %a0,r0""\n\t"
102
103
"ld r0,-%a0""\n\t"
104
"ror r0""\n\t"
105
"st %a0,r0""\n\t"
106
107
:/* void */
108
:"e"(__data)
109
:"memory"
110
);
111
}
(Bei Syntaxfehlern stürzt das AVRStudio hier übrigens gerne ab wenn es
keinen Output vom GCC bekommt.)
Jetzt habe ich noch überlegt das ich eigentlich garnicht soviel schieben
muß weil ich ja schon ein HW Schieberegister habe. Das SPI kann immer
nur 8 Bit am Stück ausgeben (ATMega32), oder gibt es einen Trick 1..7
Bits auszugeben? Wenn nicht mit dem HW-SPI, kann ich dann die 1..7 Bits
vom letzten Byte 'von Hand' hinterherschieben? Ich meine funkt mir das
Hardware SPI nicht dazwischen wenn ich den SPI Port manuell setze?
Hrm. Einfach per Software-SPI 1..7 bits rausshiften, und danach erst das
Hardware-SPI Einschalten und mit ganzen Bytes füttern?
Bzw, für ne Schieberegisterreihe ists warscheinlich andersrum besser:
Per HW-SPI die ganzen Bytes schicken, dann die fehlenden Bits per
Software-SPI hinterher, danach RCK pulsen.
/Ernst
danke, endlich mal jemand der es gelesen hat.
Ich bin erstmal beim Hardware SPI geblieben und schiebe die Daten im
Inline asm. Da stolpere ich gerade über die kryptische inline Syntax
(eigentlich ein Grund das doch nicht zu verwenden).
1
uint8_t*p=&disp[0];
2
for(r=0;r<DIGITS;r++)
3
{
4
_rol_array(p);
5
//p+=11;
6
}
das funktioniert mit auskommentierter Zeile wenn gcc Optimierung -Os
ein, wenn Optimierung aus muss der Pointer inkrementiert werden.
Ich habe auch probiert die funktion _rol_array() mit Returnwert zu
versorgen, aber das klappt auch nicht so recht:
1
staticinlineuint8_t*
2
_rol_array(uint8_t*__data)
3
{
4
__asm__volatile(
5
"sec""\n\t"
6
7
"ld __tmp_reg__,%a0"
8
"rol __tmp_reg__"
9
"st %a0+,__tmp_reg__"
10
11
"ld __tmp_reg__,%a0"
12
"rol __tmp_reg__"
13
"st %a0+,__tmp_reg__"
14
15
:"=e"(__data)/* "=&e" geht auch nicht */
16
:"e"(__data)
17
:"memory");
18
19
return__data;
20
}
der Pointer __data wird in der Funktion durch 'st %a+, r0' manipuliert,
daher wohl der Unterschiedliche Effekt bei mit/ohne Optimierung. Aber
auch wenn ich den return Wert verwende wie er hier rauskommt ist der
nicht richtig. Kann man auf einen Blick sagen das ist def. falsch oder
ist das eher ein Randbereich des gcc?