Array[1..8] of Byte um 90° "kippen" - wie?

  • 1
  • 2
  • Page 1 of 2
Harry
Moderator
Avatar
Gender:
Location: zwischen Augsburg und Ulm
Age: 59
Posts: 2090
Registered: 03 / 2003
Subject:

Array[1..8] of Byte um 90° "kippen" - wie?

 · 
Posted: 29.01.2017 - 12:53  ·  #1
Hallo @ all,

ich muß ein Array[1..8] of Byte um 90° nach links kippen. Hört sich kompliziert an .....

Code

Data[1]:=%00000001;
Data[2]:=%00000001;
Data[3]:=%00010001;
Data[4]:=%00010001;
Data[5]:=%00010001;
Data[6]:=%00000001;
Data[7]:=%01000001;
Data[8]:=%01000001;

soll danach also so aussehen:
Code

Data[1]:=%11111111;
Data[2]:=%00000000;
Data[3]:=%00000000;
Data[4]:=%00000000;
Data[5]:=%00111000;
Data[6]:=%00000000;
Data[7]:=%00000011;
Data[8]:=%00000000;


Irgendeine Idee, wie man das schnell und einfach hin bekommt?

Gruss
Harry
Harry
Moderator
Avatar
Gender:
Location: zwischen Augsburg und Ulm
Age: 59
Posts: 2090
Registered: 03 / 2003
Subject:

Re: Array[1..8] of Byte um 90° "kippen" - wie?

 · 
Posted: 29.01.2017 - 13:13  ·  #2
Jetzt ist mir was eingefallen :D ..... kann es aber momentan nicht testen:
wenn ich ein Grafikdisplay mit 8x8Pixeln definiere und horizontale Linien mit 8 Pixeln Länge und dem Bitmuster der Ursprungsdaten zeichne:
Code

For Counter:=1 to 8 do
  gDrawLine(0,Counter-1,7,Counter-1,Data[Counter]);
  EndFor;

.... müßte ich doch in den Daten des Displayarrays (die ja senkrecht gelesen werden) die gekippten Daten haben - oder?

Harry

[Edit] also 1. kann ich kein Display mit 8x8 Pixeln definieren. Minimum ist 32x32 und 2. funktioniert es leider nicht :(
Harry
Moderator
Avatar
Gender:
Location: zwischen Augsburg und Ulm
Age: 59
Posts: 2090
Registered: 03 / 2003
Subject:

Re: Array[1..8] of Byte um 90° "kippen" - wie?

 · 
Posted: 29.01.2017 - 16:23  ·  #3
Also ich habs zwar, aber die optimierte Funktion (SetBits2) ist deutlich langsamer (siehe die Zeitangaben/Kommentar im Procedurekopf rechts. 42s bis 50000 heißt 42 Sekunden Programmstart bis auf 50000 gezählt wurde). SetBit und SetBit2 haben die gleiche Funktion.
Code
Program DTest;
{ MAX7219-Test                                                                 }

{$NOSHADOW}
{ $WG}                     {global Warnings off}

Device = mega644, VCC=5;
{ $BOOTRST $07000}         {Reset Jump to $07000}

Import SysTick, SPIDriver1;

From System Import LongWord;


Define
  ProcClock      = 20000000;       {Hertz}
  SysTick        = 10;             {msec}
  StackSize      = $0064, iData;
  FrameSize      = $0064, iData;

  SPIdriver1     = PortB, 0, 1, 2;  // SCK, MOSI, MISO
  SPIorder1      = MSB;
  SPIcPHA1       = 0;
  SPIcPol1       = 0;
  
Implementation

{$IDATA}

{------------------------------------------------------------------------------}
{ Type Declarations }
Type
{------------------------------------------------------------------------------}
{ Const Declarations }
Const                                                          // PGFEDCBA
  ShowNum        : Array[0..14] of Byte = (%00111111, %00000110, %01011011,  //0,1,2
                                           %01001111, %01100110, %01101101,  //3,4,5
                                           %01111101, %00000111, %01111111,  //6,7,8
                                           %01101111, %01100011, %00100000,  //9,°,`
                                           %00100010, %00000000, %00000000); //", ,
{------------------------------------------------------------------------------}
{ Var Declarations }
Var
  DispData       : Array[1..8] of Byte;
  Count1         : Byte;
  Count2         : LongWord;
  
{$IDATA}
{------------------------------------------------------------------------------}
{ functions }
{ **************************************************************************** }
Procedure InitPorts;
  Begin
    DDRB:=  %00001011;                      // xxxx /CS MISO MOSI SCK
    PortB:= %00001000;                      //
  End InitPorts;

{------------------------------------------------------------------------------}
{ Main Program }
{$IDATA}
Procedure SetBits(Num,Digit:Byte);             // Zahl Num auf Stelle Digit
  Var DigVal  : Byte;                          // 31s bis 50000
  Begin                                        // 25s bis 50000 mit Optimizer
    Case Digit of
      1:DigVal:=  1;|
      2:DigVal:=  2;|
      3:DigVal:=  4;|
      4:DigVal:=  8;|
      5:DigVal:= 16;|
      6:DigVal:= 32;|
      7:DigVal:= 64;|
      8:DigVal:=128;|
      EndCase;

    If (ShowNum[Num] and $01)=$01
      then
        DispData[1]:=DispData[1] or DigVal;
      EndIf;
    If (ShowNum[Num] and $02)=$02
      then
        DispData[2]:=DispData[2] or DigVal;
      EndIf;
    If (ShowNum[Num] and $04)=$04
      then
        DispData[3]:=DispData[3] or DigVal;
      EndIf;
    If (ShowNum[Num] and $08)=$08
      then
        DispData[4]:=DispData[4] or DigVal;
      EndIf;
    If (ShowNum[Num] and $10)=$10
      then
        DispData[5]:=DispData[5] or DigVal;
      EndIf;
    If (ShowNum[Num] and $20)=$20
      then
        DispData[6]:=DispData[6] or DigVal;
      EndIf;
    If (ShowNum[Num] and $40)=$40
      then
        DispData[7]:=DispData[7] or DigVal;
      EndIf;
    If (ShowNum[Num] and $80)=$80
      then
        DispData[8]:=DispData[8] or DigVal;
      EndIf;
  End SetBits;


Procedure SetBits2(Num,Digit:Byte);             // Zahl Num auf Stelle Digit
  Var Counter : Integer;                        // 42s bis 50000
      DigVal  : Byte;                           // 32s bis 50000 mit Optimizer
      CompVal : Byte;
  Begin
    DigVal:=$01 SHL (Digit-1);
    CompVal:=$01;
    For Counter:=1 to 8 do
      If (ShowNum[Num] and CompVal)=CompVal
        then
          DispData[Counter]:=DispData[Counter] or DigVal;
        EndIf;
      CompVal:=CompVal SHL 1;
      EndFor;
  End SetBits2;
  
  
Procedure SetDigit(OutString:String[8]);       // Digit v.l.n.r. 1-8
  Var Counter  : Byte;
      StrHelp  : String[1];
  Begin
    For Counter:=1 to 8 do
      DispData[Counter]:=0;
      EndFor;
    For Counter:=1 to 8 do
      StrHelp:=Copy(OutString,Counter,1);
      Case StrHelp[1] of
        '0':SetBits2( 0,Counter);|
        '1':SetBits2( 1,Counter);|
        '2':SetBits2( 2,Counter);|
        '3':SetBits2( 3,Counter);|
        '4':SetBits2( 4,Counter);|
        '5':SetBits2( 5,Counter);|
        '6':SetBits2( 6,Counter);|
        '7':SetBits2( 7,Counter);|
        '8':SetBits2( 8,Counter);|
        '9':SetBits2( 9,Counter);|
        '°':SetBits2(10,Counter);|
        '´':SetBits2(11,Counter);|
        '"':SetBits2(12,Counter);|
        ' ':SetBits2(13,Counter);|
        EndCase;
      EndFor;
  End SetDigit;
  
  
Procedure SPIODB(Command,Data:Byte);        // SPIOut Double Byte
  Begin
    PortB:=PortB and %11110111;             // /CS
    SPIOutByte1(Command);
    SPIOutByte1(Data);
    PortB:=PortB or %00001000;
  End SPIODB;
  
  
Begin
  InitPorts;
  EnableInts;
  Count2:=0;
  
  // Init MAX7219
  SPIODB(%00001100,%00000001);                // Normal Operation
  mDelay(10);
  SPIODB(%00001111,%00000001);                // Display Test on
  mDelay(2000);
  SPIODB(%00001111,%00000000);                // Display Test off
  mDelay(10);
  SPIODB(%00001001,%00000000);                // Decode Mode: none
  mDelay(10);
  SPIODB(%00001010,%00000111);                // Intensity $07/$0F
  mDelay(10);
  SPIODB(%00001011,%00000111);                // Scan Limit 8 Digits
  mDelay(10);
  // End Init MAX7219
  
  Loop
    SetDigit(LongToStr(Count2:8));            // Zahl --> String --> Display-Array
    For Count1:=1 to 8 do                     // Displayausgabe via SPI
      SPIODB(Count1,DispData[Count1]);
      EndFor;
    If Count2<99999999
      then
        Inc(Count2);
      else
        Count2:=0;
      EndIf;
    EndLoop;
End DTest.

Falls es jemand interessiert, was das soll: Ich habe mir einen Sack voll MAX7219 aus China bestellt (30 Stück für ca. 14€) und einen Sack voll Displays hatte ich schon. Dummerweise sind alle meine Displays mit gemeinsamer Anode, der MAX benötigt aber gemeinsame Kathode. Ich habe dann den Tip bekommen meine Segmente an die Digit-Anschlüsse des MAX und die Digit-Anschlüsse an die Segmentanschlüsse des MAX anzuschliessen. Dadurch ist aber ein Datenbyte nicht mehr eine Displaystelle, sondern jeweils die gleichen Bits der 8 Datenbytes sind für eine Stelle zuständig. In meinem Beispiel ist Bit0 Digit1, Bit1 Digit2, usw. Achso: Das Display ist momentan 8-stellig und soll letztendlich 32 Stellen (2 Zeilen je 16 Stellen) haben.
Code
  // Digit         87654321
  // DispData[1]:=%11101101; // Segment A
  // DispData[2]:=%10011111; // Segment B
  // DispData[3]:=%11111011; // Segment C
  // DispData[4]:=%01101101; // Segment D
  // DispData[5]:=%01000101; // Segment E
  // DispData[6]:=%01110001; // Segment F
  // DispData[7]:=%01111100; // Segment G
  // DispData[8]:=%10101010; // Segment dp


Gruss
Harry
Gunter
Administrator
Avatar
Gender:
Location: Frankfurt Main / Germany
Posts: 1697
Registered: 02 / 2003
Subject:

Re: Array[1..8] of Byte um 90° "kippen" - wie?

 · 
Posted: 29.01.2017 - 17:10  ·  #4
Hi Harry,

ich würde das etwa so machen (nicht getestet):

for i := 1 to 8 do ;Zieldaten
  Ziel[i] := 0;
  for j := 1 to 7 do ;Quelldaten
    Ziel[i] := Ziel[i] OR (Daten[j] AND %0000 0001)
    SHL (Ziel[i])
    SHR (Daten[j])
  endfor
  Ziel[i] := Ziel[i] OR (Daten[j] AND %0000 0001)
endfor

so auf die Art müsste es funktionieren wenn dein Ergebnis in Ziel[1..8] ist

Gruß
Gunter
Harry
Moderator
Avatar
Gender:
Location: zwischen Augsburg und Ulm
Age: 59
Posts: 2090
Registered: 03 / 2003
Subject:

Re: Array[1..8] of Byte um 90° "kippen" - wie?

 · 
Posted: 29.01.2017 - 21:30  ·  #5
Hi Gunter,

danke für den Tip. Nachdem ich eine Weile drüber nachgedacht habe, bin ich zu dem Schluss gekommen, daß das sehr gut und schnell funktionieren müßte. Ich probiere das bei Gelegenheit mal aus.

Gruss
Harry
Gunter
Administrator
Avatar
Gender:
Location: Frankfurt Main / Germany
Posts: 1697
Registered: 02 / 2003
Subject:

Re: Array[1..8] of Byte um 90° "kippen" - wie?

 · 
Posted: 29.01.2017 - 21:54  ·  #6
Quote by Harry
daß das sehr gut und schnell funktionieren müßte

ja klar - ist ja fast schon Assembler und macht es dem Compiler leicht.
Hatte am Anfang noch IFs drin, aber so ist's besser (ein endif war vorhin
fälschlicherweise noch drin).
Ob der Compiler die SHIFTs mit Array-Elementen frißt, weiss ich grad nicht.
Ansonsten musst du dazu Hilfsvariaben benutzen.
Und dann im Sim schauen ob die For Schleifen so richtig sind und nicht zu
oft/wenig geshiftet wird.

Gruß
Gunter
Merlin
Administrator
Avatar
Gender:
Age: 24
Posts: 1373
Registered: 03 / 2005
Subject:

Re: Array[1..8] of Byte um 90° "kippen" - wie?

 · 
Posted: 30.01.2017 - 16:24  ·  #7
An additional tip for speed; If you make i and j local variables, the optimiser will optimise this very well.
Harry
Moderator
Avatar
Gender:
Location: zwischen Augsburg und Ulm
Age: 59
Posts: 2090
Registered: 03 / 2003
Subject:

Re: Array[1..8] of Byte um 90° "kippen" - wie?

 · 
Posted: 31.01.2017 - 19:28  ·  #8
Falls es noch jemand interessiert: Wenn man die richtigen Displays (gem.Kathode) anschließt und den MAX decodieren läßt, dauert das Zählen bis 50000 (ohne Optimizer) 21 Sekunden.
Ich werde den MAX jedoch nicht codieren lassen, da
1. nur wenige Zeichen zusätzlich anzeigbar sind (siehe Datenblatt)
2. ich es auf die schnelle nicht geschafft hab eine Vornullenunterdrückung zu programmieren
3. die Decodierung irgendwie blöd ist. d.h, ein gesendetes Byte mit dem Wert 5 zeigt eine 5 an. Ich hätte eher eine ASCII-Umsetzung erwartet zumal ich eine 8stellige Zahl trotzdem irgendwie in die 8 Einzelzahlen zerlegen muß. Das geht meiner Meinung nach mit Strings besser (oder kennt jemand eine Funktion mit der man einfach z.b. die Tausender-Stelle als Byte bekommt?).

Harry

PS: Hab fertige Platinen mit Displays und MAX aus China bekommen (1.38€) und die haben es doch tatsächlich geschafft das Layout zu versauen: Digit1 ist rechts ;) :D

..... achja ich arbeite momentan mit SoftSPI bei ca. 1.2 MHz. Wäre mal interessant den MAX bei 10 MHz (laut Datenblatt das Maximum) zu testen
  • 1
  • 2
  • Page 1 of 2
Selected quotes for multi-quoting:   0

Registered users in this topic

Currently no registered users in this section

The statistic shows who was online during the last 5 minutes. Updated every 90 seconds.
MySQL Queries: 15 · Cache Hits: 14   135   149 · Page-Gen-Time: 0.025932s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI