Motorola zu Intel konvertieren ....



  • naja, z.b. einlesen wie's kommt und dann (am besten wenn nix auf dem bus los ist) einen der bitverdreher-algos

    okay, es kommt bitweise... was machst du da um die nacheinander in einen int reinzubekommen
    additionen oder nicht?
    auch 32 aber eben in der falschen richtung und ne maske brauchst du auch.

    und hardware davor ist ja auch ganz nett, aber das geht immer...;-)

    die einleserouting sollte natürlich nicht blockieren. insbesondere
    bit_from_bus())
    sollte die rechenzeit wieder an andere prozesse abgeben.
    aber sonst sehe ich da jetzt keinen riesen vorschlage

    jenz



  • mich würde wirklich noch mal das Einlesen der Daten interessieren.
    Falls du das mal posten könntest...

    danke,
    jenz



  • jenz schrieb:

    okay, es kommt bitweise... was machst du da um die nacheinander in einen int reinzubekommen
    additionen oder nicht?
    auch 32 aber eben in der falschen richtung und ne maske brauchst du auch.

    nö, selbst wenn man's nacheinander, sozusagen 'online' macht, braucht man nur ein paar 'oders' mit 'ner lookuptable in der die bits umgedreht sind.

    btw: aber wir wissen ja nicht wie schnell's ein soll. vielleicht trudeln die bits nur mit ein paar kHz ein, dann ist das ja alles egal 😉



  • @jenz

    Das einlesen geht ueber unterschiedliche API's die ich vom hersteller bekomme ....

    bei einem muss ich pollen .... beim anderen muss ich dem nen zeiger aufn Event geben, der setzt das event wenn ne nachricht eintrifft, und dann dann kann ich mir nen Array mit daten abholen ....

    die API's geben die Daten schon telegrammorinetiert raus ... also ich bekomm nen array von ner Struct.

    In der struct stehen
    zeitstempel (64bit int),
    telegrammID(16 bit Int),
    DLC(laenge der nutzdaten in byte, 8bit int),
    und nen char[8] array (8 ist max laenge)

    TelegramID ist spezifiziert, die kommt auch richtig rum an .... weil die telegrammID auch was mit der Prioritaet aufn Bus zu tun hat (iss nen serieller Bus mit 1 oder 2 leitungen)
    DLC kommt auch richtig rum an (istd spezifiziert), weil die auch fuer die uebertragung und stopbits usw wichtig ist.

    Nur bei den Datenbytes ist es nicht spezifiziert ...
    Die telegramme Sind in Signale aufgeteilt. diese signale werden in ner Zentralen DB gepflegt. Da steht dann drinn, das bspweise am telegram 0x116 das bit 8 - 15 nen Signal X enspricht ... fuer das Signal gibts dann Offset und Aufloesung so dass man sich den realen wert mit offset + x*aufloesung errechnen kann

    wie gesagt bei den Motorola buss iss nu alles verkehrt rum ... waehrend ich in der DB wenigstens schon mal die Startbits der signale umrechnen kann, kommen am treiber die Bytes nun aber bitverdreht an ...

    Das nur zur allgemeinen Info ... wer jetzt wegen den 8 Byte laenge an CAN denkt, liegt auch genau richtig ...

    die ganze anbindung an den CAN-Bus der Stg's wird von industriellen CAN-Controllern uebernommen, da sind also TelegrammID und laenge spezifiziert. Aber was in den Daten drinnesteht, intressiert die controller nich, sondern das wird von den FPGA's oder CPU der STG's befuellt. wenn da nun einige Motorola Teile verwenden, schreiben die einfach die eigenen Speicherbereiche in die puffer der CAN Controller, und die sind gegenueber Intel bitverdreht ... intressiert aber nich, weil alle stg's am buss (monentan noch) dann motorola sprechen.
    Nur wir muessen die Daten interpretieren ... und die meisten karten schieben eh nur den puffer der CANController in den Speicher des PC's (Intel) und voila, alles ist verdreht ^^

    Willst wirklich noch ne ausleseroutine sehen ? ^^

    btw: aber wir wissen ja nicht wie schnell's ein soll. vielleicht trudeln die bits nur mit ein paar kHz ein, dann ist das ja alles egal

    eigentlich human .... 500kbit bei extrem schlechter nutzdatenrate ^^ (CAN halt)

    im schnitt max 3800 Nachrichten = 2+1+8 byte pro sekunde ... der zeitstempel wird beim empfang generiert.

    Problem ist, dass unsere SW auch auf mobilen industrierechnern laufen muss, die haben zwar windows drauf, aber die rechenleistung ist ... urks ^^ glaub die miesesten haben nen 500Mhz cyrix prozessor oder so. Da kommts eben halt auch extrem aufn stromverbrauch und temperatur / ruettelfestigkeit an ....

    Ciao ...



  • @net ich will ja jetzt nicht drauf rumreiten, aber auch wenn du oderst brauchst du eine maske...
    und ein oder ist auch nicht schneller als ein add vielleicht früher mal.

    bitte pseudocode mir das doch mal "online" bitweise ohne maske.
    das umdrehen per lookuptable kann man sich dann auch gleich schenken..

    wenn man die daten natürlich von nicht änderbarem code bekommt, dann kann man natürlich nichts machen. aber ob dann der umdrehen per lookuptable schneller ist, als ein bitweises übertragen von register zu register, das wage ich dann doch zu bezweifeln.
    aber das bezweifel ich auch einfach aus der lust heraus. 😉 nicht, dass es wirklich wichtig wäre
    vielleicht hat ja trotzdem jemand lust, das mal auszumessen. bestimmt ne ganz gute anfänger übung...

    ciao,
    jenz



  • jenz schrieb:

    bitte pseudocode mir das doch mal "online" bitweise ohne maske.

    ganz einfach, so ungefähr

    unsigned long table[32] =
    {
       0x00000001,
       0x00000002,
       0x00000004,
       0x00000008,
       0x00000010,
       0x00000020,
       ...
       ...
       ...
       0x20000000,
       0x40000000,
       0x80000000,
    }
    ...
       unsigned long result = 0;
       int s;
       for (s=0; s<32; s++)
       {
          if (read_bit() == 1)   // hi-bit kommt als erstes
             result |= table[s];
       }
       // result enthält nun umgedrehtes bitmuster
    ...
    

    @RHBaum
    was habt ihr denn für'n adapter am pc der die can-messages bitweise abliefert? sowas ist doch eher ungewöhnlich 😕


  • Mod

    das geht dann allerdings auch ohne LUT, indem wir die maske als laufvariable der schleife missbrauchen (vorausgesetzt, der entsprechende typ ist exakt 32bit breit):

    unsigned result = 0;
       for (unsigned mask=1; mask!=0; mask<<=1)
       {
          if (read_bit() == 1)   // hi-bit kommt als erstes
             result |= mask;
       }
    


  • @net, na da hast du ja mal eine richtig tolle lösung gefunden.
    du schreibst also lieber die ganzen masken hin, anstatt die zu schiften?
    so ganz kann ich das leider nicht akzeptieren.

    zumal der nächste auch gleich wieder die maske vorschlägt. natürlich ein bisschen cleverer implementiert als ich aber mit maske...

    ciao,
    jenz



  • jenz schrieb:

    @net, na da hast du ja mal eine richtig tolle lösung gefunden.
    du schreibst also lieber die ganzen masken hin, anstatt die zu schiften?
    so ganz kann ich das leider nicht akzeptieren.

    toll ist das alles nicht (wegen der 32 schleifendurchläufe). aber lookuptables sind immer ein tickchen schneller. kannst es ja mal testen (beide versionen einige millionen mal aufrufen und zeit messen).



  • toll ist das alles nicht (wegen der 32 schleifendurchläufe). aber lookuptables sind immer ein tickchen schneller. kannst es ja mal testen (beide versionen einige millionen mal aufrufen und zeit messen).
    

    okay, wenn sich bis samstag nicht irgendein anderer daran versucht hat werde ich das mal durchmessen.
    ich bin mir sicher, dass die variante ohne lut schneller ist. vor allem dann, wenn auch noch threadwechsel stattfinden. wovon man wohl ausgehen sollte.

    bis dahin,
    jenz



  • jenz schrieb:

    ich bin mir sicher, dass die variante ohne lut schneller ist. vor allem dann, wenn auch noch threadwechsel stattfinden. wovon man wohl ausgehen sollte.

    das könnte schon sein, weil der shiftwert in 'nem register gehalten wird. andererseits könnte ein geschickter compiler die schleife auflösen und die werte aus dem array direkt nehmen (also ohne array-zugriffe zu machen). dann wär' wieder die lut-variante schneller 😉



  • Es gibt noch eine Möglichkeit (ohne Schleife):

    Zuerst swappt man die 4 Bytes (d.h. aus "abcd" wird "dcba").
    Dann greift man über eine Lookup-Table mit 256 Werten für jedes Byte darauf zu und swappt jeweils die 8 Bits.

    0 -> 0 00000000 -> 00000000
    1 -> 128 00000001 -> 10000000
    2 -> 64 00000010 -> 01000000
    ...
    254 -> 127 11111110 -> 01111111
    255 -> 255 11111111 -> 11111111



  • @th: das swappen ist schon längst nicht mehr unser problem. 😉
    wir reden über ein möglichst effizientes einlesen...

    ciao,
    jenz



  • Ich habe hier mal ein Testprogramm geschrieben, mit dem ich verschiedene Varianten ausprobiert habe. Die Lookuptabelle gewinnt bei mir um ca. den Faktor 6. Hier ist meine Rotationsfunktion, die ich auch zum initialisieren der Lookuptabelle verwende:

    template <typename T>
    T rotbits(T v, unsigned bits = 8)
    {
      T ret = 0;
      for (unsigned n = 0; n < bits; ++n)
      {
        ret = (ret << 1) | (v & 1);
        v >>= 1;
      }
      return ret;
    }
    

    Wenn Interesse besteht, kann ich auch mein komplettes Testprgramm posten.

    Tntnet



  • ich hatte auch mal etwas lange weile:

    #include <stdio.h>
    #include <windows.h>
    
    // dummy
    int read_bit (void)
    {
       return 1;
    }
    
    unsigned long read32_reverse_table (void)
    {
       static unsigned long table[] =
       {
          0x00000001,
          0x00000002,
          0x00000004,
          0x00000008,
          0x00000010,
          0x00000020,
          0x00000040,
          0x00000080,
          0x00000100,
          0x00000200,
          0x00000400,
          0x00000800,
          0x00001000,
          0x00002000,
          0x00004000,
          0x00008000,
          0x00010000,
          0x00020000,
          0x00040000,
          0x00080000,
          0x00100000,
          0x00200000,
          0x00400000,
          0x00800000,
          0x01000000,
          0x02000000,
          0x04000000,
          0x08000000,
          0x10000000,
          0x20000000,
          0x40000000,
          0x80000000
       };
    
       register unsigned long result = 0;
       register unsigned long s;
    
       for (s=0; s<32; s++)
       {
          if (read_bit() == 1)
             result |= table[s];
       }
    
       return result;
    }
    
    unsigned long read32_reverse_loopless (void)
    {
       register unsigned long result = 0;
    
       if (read_bit() == 1)
          result |= 0x00000001;
       if (read_bit() == 1)
          result |= 0x00000002;
       if (read_bit() == 1)
          result |= 0x00000004;
       if (read_bit() == 1)
          result |= 0x00000008;
       if (read_bit() == 1)
          result |= 0x00000010;
       if (read_bit() == 1)
          result |= 0x00000020;
       if (read_bit() == 1)
          result |= 0x00000040;
       if (read_bit() == 1)
          result |= 0x00000080;
       if (read_bit() == 1)
          result |= 0x00000100;
       if (read_bit() == 1)
          result |= 0x00000200;
       if (read_bit() == 1)
          result |= 0x00000400;
       if (read_bit() == 1)
          result |= 0x00000800;
       if (read_bit() == 1)
          result |= 0x00001000;
       if (read_bit() == 1)
          result |= 0x00002000;
       if (read_bit() == 1)
          result |= 0x00004000;
       if (read_bit() == 1)
          result |= 0x00008000;
       if (read_bit() == 1)
          result |= 0x00010000;
       if (read_bit() == 1)
          result |= 0x00020000;
       if (read_bit() == 1)
          result |= 0x00040000;
       if (read_bit() == 1)
          result |= 0x00080000;
       if (read_bit() == 1)
          result |= 0x00100000;
       if (read_bit() == 1)
          result |= 0x00200000;
       if (read_bit() == 1)
          result |= 0x00400000;
       if (read_bit() == 1)
          result |= 0x00800000;
       if (read_bit() == 1)
          result |= 0x01000000;
       if (read_bit() == 1)
          result |= 0x02000000;
       if (read_bit() == 1)
          result |= 0x04000000;
       if (read_bit() == 1)
          result |= 0x08000000;
       if (read_bit() == 1)
          result |= 0x10000000;
       if (read_bit() == 1)
          result |= 0x20000000;
       if (read_bit() == 1)
          result |= 0x40000000;
       if (read_bit() == 1)
          result |= 0x80000000;
    
       return result;
    }
    
    unsigned long read32_reverse_mask (void)
    {
       register unsigned long result = 0;
       register unsigned long mask;
    
       for (mask=1; mask!=0; mask<<=1)
       {
          if (read_bit() == 1)   
             result |= mask;
       }
    
       return result;
    }
    
    #define REPETITIONS 10000000L
    
    void test (void)
    {
       unsigned long timer;
       unsigned long s;
    
       // mask
       timer = GetTickCount();
       for (s=0; s<REPETITIONS; s++)
          read32_reverse_mask();
       timer = GetTickCount() - timer;
       printf ("mask: %lu\n", timer);
    
       // table
       timer = GetTickCount();
       for (s=0; s<REPETITIONS; s++)
          read32_reverse_table();
       timer = GetTickCount() - timer;
       printf ("table: %lu\n", timer);
    
       // w/o loop
       timer = GetTickCount();
       for (s=0; s<REPETITIONS; s++)
          read32_reverse_loopless();
       timer = GetTickCount() - timer;
       printf ("loopless: %lu\n", timer);
    
       printf ("------------------------------\n");
    }
    
    void main (void)
    {
       SetPriorityClass (GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
       SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
    
       test();
       test();
       test();
       test();
    }
    

    ergebnis:

    mask: 1656
    table: 1672
    loopless: 1125
    ------------------------------
    mask: 1656
    table: 1672
    loopless: 1125
    ------------------------------
    mask: 1656
    table: 1672
    loopless: 1141
    ------------------------------
    mask: 1656
    table: 1688
    loopless: 1125
    ------------------------------
    Press any key to continue
    

    demnach ist die lut-version etwas schlechter als die mit dem shiften.
    aber ohne schleife ist es um ca. 1/3 schneller....



  • @net: Ich glaube, einer von uns beiden hat das Problem nicht richtig verstanden. Du gehst von einer Funktion read_bit aus, welches ein bit nach dem anderen liefert. Ich gehe davon aus, daß ein 32-Bit-Wort zur verfügung steht, welches bitweise umgedreht werden soll.

    Auch ist Deine Lookup-tabelle was anderes, als meine. Die Idee ist doch, daß man ein Byte umdreht, indem man in einer Tabelle mit den 256 Byte-Werten den entsprechenden umgedrehten Byte nachschaut.

    Bei mir sieht das so aus:

    static unsigned char lut[256];
    
      // initialize lookup-table
      for (unsigned i = 0; i < 256; ++i)
        lut[i] = rotbits(i);
    
      unsigned char ch = getIrgendeinByte();
      unsigned char rch = lut[ch];  // schlage in der Lookup-tabelle nach
    

    Und diese Variante ist in der Tat wesentlich schneller als etwa:

    unsigned char rch = rotbits(ch);
    

    welches jedes einzelne Byte algorithmisch undreht.

    Tntnet



  • die API's geben die Daten telegrammorinetiert raus
    ich bekomm nen array von ner Struct:
    [...]
    char[8] array

    unsigned char b;
    b = ((b * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
    

    (Bit Twiddling Hacks)



  • @tntnet, net programmiert da etwas anderes. das ist so ne kleine privatfehde.

    @net, fleißig. sieht man mal, das unsere ersten varianten nicht so besonders waren. die ausgerollte ist halt am besten.
    einigen wir uns darauf, dass wir beide danebenlagen? 😉
    die paar ticks sind dann ja wirklich egal.

    also back to topic, vielleicht können wir dem tntnet noch was zeigen 😉

    ciao,
    jenz



  • RHBaum schrieb:

    im schnitt max 3800 Nachrichten = 2+1+8 byte pro sekunde ... der zeitstempel wird beim empfang generiert.

    3800 Botschaften pro Sekunde wären aber schon recht viel für 500k. Ihr fahrt da hoffentlich nur mit einem Sender, oder?



  • jenz schrieb:

    @net, fleißig. sieht man mal, das unsere ersten varianten nicht so besonders waren. die ausgerollte ist halt am besten.

    ja, und die moral von der geschicht? schleifen haben in zeitkritischen codes nix zu suchen :p


Anmelden zum Antworten