Forum: Compiler & IDEs Zugriffsstruktur für TLC5951


von Frank L. (franklink)


Lesenswert?

Hallo Zusammen,
ich benötige mal etwas Gedankenunterstüzung.

Um auf die Kontrollstrukturen des TLC5951 zugreifen zu können, in diesem 
Fall des Grayscale-Controller, möchte ich folgende Definition vornehmen:
1
#define NUMBERS_OF_TLC5951              4
2
#define NUMBERS_OF_LED_PER_TLC5951      24
3
#define NUMBERS_OF_BITS_PER_LEDS        12
4
#define NUMBERS_OF_TLC5951_GSSIN_BYTE   36
5
#define NUMBERS_OF_TLC5951_DCSIN_BYTE   27
6
#define NUMBERS_OF_LEDS  NUMBERS_OF_TLC5951 * NUMBERS_OF_LED_PER_TLC5951  
7
8
typedef struct 
9
{
10
  unsigned bit01:1;
11
  unsigned bit02:1;
12
  unsigned bit03:1;
13
  unsigned bit04:1;
14
  unsigned bit05:1;
15
  unsigned bit06:1;
16
  unsigned bit07:1;
17
  unsigned bit08:1;
18
  unsigned bit09:1;
19
  unsigned bit10:1;
20
  unsigned bit11:1;
21
  unsigned bit12:1;
22
}rgb_led_struc;
23
24
typedef union
25
{
26
  rgb_led_struc gssin_led[ NUMBERS_OF_TLC5951 * NUMBERS_OF_LED_PER_TLC5951 ];
27
  uint8_t gssin[ ( NUMBERS_OF_TLC5951 * NUMBERS_OF_LED_PER_TLC5951 * NUMBERS_OF_BITS_PER_LED ) / 8 ];
28
} rgb_leds;


Leider musste ich feststellen, dass die beiden Strukturen nicht gleich 
groß sind, was im nachhinein natürlich klar ist, da meine Struktur 
rgb_led_struc leider mit 16 Bit im Speicher abgelegt wird.

Sinn des Unions sollte sein, dass ich später in der SPI-Routine einfach 
nur über das gssin interieren muss, um die Daten zu übergeben.

Jetzt stellt sich mir die Frage, kann ich den GCC irgendwie dazu 
überreden, das Array gssin_led anders anzuordnen, sodass beide 
Strukturen gleich groß sind? Oder muss ich mein Array gssin an die Größe 
von gssin_led anpassen und in der SPI-Routine immer nur die 12 Bits 
ausgeben?

Gruß
Frank

von Karl H. (kbuchegg)


Lesenswert?

Frank Link schrieb:

> Jetzt stellt sich mir die Frage, kann ich den GCC irgendwie dazu
> überreden, das Array gssin_led anders anzuordnen, sodass beide
> Strukturen gleich groß sind?

Gar nicht.
Die kleinste Einheit in C ist ein Byte. 8 Bit
Du hast keine VIelfachen von 8 Bit

> Oder muss ich mein Array gssin an die Größe
> von gssin_led anpassen und in der SPI-Routine immer nur die 12 Bits
> ausgeben?

Du kannst du Dinge ja selbst in die Hand nehmen und dir 
Zugriffssfunktionen schreiben, die dir einen 12-Bit Wert in einem 
Byte-Array ablegen, wobei du die LEd Nummer als Index nimmst. Dann 
kannst du, so wie du das vorhattest, einfach das Byte Array an die TLC 
rausschieben.
So schwer ist das nicht.

Du könntest maximal deine Strukturen so aufblasen, dass du in einer 
struct immer 2 LED beschreibst. Das sind dann 24 Bit oder eben 3 
komplette Byte. Aber um die Zugriffsfunktionen kommst du auch so nicht 
herum. Lediglich das Bitschubsen würde dir der Compiler abnehmen. Das 
Bitschubsen ist aber ziemlich trivial, wenn man erkannt hat, dass es nur 
2 verschiedene Ausrichtungen der 12 Bit gibt.

von Falk B. (falk)


Lesenswert?


von Frank L. (franklink)


Lesenswert?

Hallo Karl Heinz,
danke für die Antwort, ich hab mir schon sowas gedacht. Leider benötige 
ich in den LOW-Level Routinen den direkten Zugriff auf ein einzelnes 
LED.

Wobei ich dann auf rgb_led_struc verzichten kann und an dieser Stelle 
ein Integer definiere. Auch wenn ich dabei einiges an Speicher 
verschwende.

Danke nochmals und Gruß
Frank

von Karl H. (kbuchegg)


Lesenswert?

Frank Link schrieb:
> Hallo Karl Heinz,
> danke für die Antwort, ich hab mir schon sowas gedacht. Leider benötige
> ich in den LOW-Level Routinen den direkten Zugriff auf ein einzelnes
> LED.

Wozu?

Du musst pro LED 12 Bit raustakten.
Jeweils 2 LED kannst du daher leicht in 3 Bytes unterbringen, so dass du 
dir beim raustakten keine Gedanken mehr um die logische Aufteilung der 
Bits in 12-er Einheiten machen musst.

> Wobei ich dann auf rgb_led_struc verzichten kann und an dieser Stelle
> ein Integer definiere.

Wozu?
Zu faul sich die Situation mal aufzumalen und auszuknobeln, welches 
Nibble wie gespeichert werden muss, wenn
  a) die Led Nummer gerade
  b) die Led Nummer ungerade
ist?

Du organisierst deinen Bytespeicher als 3 Byte Blöcke. Die Led mit der 
Nummer n wird im Block mit der Nummer n/2 gespeichert (der am Index n/2 
* 3 im Byte Array beginnt und 3 Bytes lang ist)

(Ansicht eines Blockes in Nibble)

   |   Byte 0    |  Byte 1     |  Byte 2     |
   +------+------+------+------+------+------+
   |      |      |      |      |      |      |
   +------+------+------+------+------+------+

ist die Led Nummer gerade, dann werden die 12 Bits in diese 3 Nibbles 
des jeweiligen Blocks gespeichert

   |   Byte 0    |  Byte 1     |  Byte 2     |
   +------+------+------+------+------+------+
   | #### | #### | #### |      |      |      |
   +------+------+------+------+------+------+

ist die Led Nummer ungerade, dann sind diese 3 Nibble des Blocks für die 
12 Bit zuständig

   |   Byte 0    |  Byte 1     |  Byte 2     |
   +------+------+------+------+------+------+
   |      |      |      | #### | #### | #### |
   +------+------+------+------+------+------+

und das wars dann auch schon. Das ist die ganze Idee. Der Rest ist dann 
nur noch Handwerk: Bits zurechtschieben und mit jeweils einem Byte aus 
dem Block verunden/verodern, wobei nur das mittlere der 3 Bytes eine 
Sonderbehandlung braucht, weil von diesem Byte die beiden Nibble zu 
anderen Led gehören. Die Behandlung ist aber reichlich trivial.

Ach ja: Eines hab ich vergessen. Man muss natürlich darauf achten, dass 
die Bits dann schon in der richtigen Reihenfolge sind (MSB / LSB) damit 
sie beim raustakten auf den TLC dann auch in der richtigen Reihenfolge 
rauskommen. Aber auch das lässt sich lösen, wenn man sich das alles mal 
aufmalt und durchüberlegt.

von Frank L. (franklink)


Lesenswert?

Hallo Karl Heinz,
danke für Deinen Lösungsvorschlag, es hat aber erstmal nichts mit 
Faulheit zu tun, dass ich diese Version nicht verwende, sondern damit, 
dass ich mich auf die von mir beschriebene Struktur eingeschossen hatte. 
Unabhängig von Deiner Idee bin ich jetzt auf folgende Vorgehensweise 
gekommen und möchte die mal zur Diskussion stellen.

Geplant sind 4 x TLC5951 mit jeweils 8 RGLB-Leds = 24 x 4 Einzelleds.

Ich benötige insgesamt 288 Bit Gray Scale Shift Register = 36 Byte pro 
Controller + 216 Bit DC/BC/FC/UD Shift Register = 27 Byte pro Controller 
also insgesamt 63 Byte pro Controller = 252 Byte für die gesamte 
Ansteuerung.

Von diesen 252 Bytes kann ich 4 * 6 Bytes Kontrollinformationen für die 
Controller abziehen, da diese für alle Controller gleich sein sollen und 
damit in einer eigenen Struktur von 6 Byte liegen. Ich würde damit also 
232 Byte für die Kontrollinformationen Gray Scale und Dot Correction für 
alle LEDs benötigen. Wenn ich alles linear ablegen könnte. Das geht aber 
leider nicht, da ich 12 Bit Gray Scale und 7 Bit Dot Correction habe 
also zusammen 19 Bit (wer sich das hat einfallen lassen, sollte 
erschossen werden).

Da ich aber noch 3 Statusinformationen aus dem Controller pro LED 
ablegen will, kommen also noch 3 x 24 x 4 Bit = 36 Byte hinzu.

Macht in Summe 268 Byte.

Meine Lösung sieht jetzt so aus:

Jedes LED wird mit 3 Byte beschrieben. Dabei sind die ersten 12 Bit der 
Gray Scale, dann folgen 7 Bit für die Dot Correction, verbleiben zur 
Zeit noch 5 Bit, in 3 von diesen 5 Bit werden die Statusinformationen, 
die der Chip mir liefert abgelegt, um auf Fehler reagieren zu können. 
Verbleiben zur Zeit 2 Bit je LED ohne Nutzung.

Somit komme ich auf insgesamt 3  24  4 = 288 Byte für die gesamte 
Anwendung. Ich würde also insgesamt 24 Byte ungenutzt im Speicher liegen 
haben.

Hat jemand noch eine andere Idee hierzu, wobei die Rahmenbedinungen 
erhalten bleiben sollten. Mir ist auch bewußt, dass die Daten für das 
Gray Scale Shift Register in einer anderen Reihenfolge ausgegeben werden 
müssen, als die für das DC/BC/FC/UD Shift Register. Aber das ist die 
Aufgabe der SPI-Funktionen und nicht die Aufgabe der Datenstrukturen.

Gruß
Frank

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.