uint16_t Array in uint8_t Array umsortieren


  • Mod

    Ich würde es so in dieser Richtung machen. Das sollte dir genug Freiheit geben, eventuelle Anpassungen selber vorzunehmen, da ich jetzt nicht jedes Detail erfragt habe:

    #include <stdio.h>
    #include <stdint.h>
    
    
    const int WRITEBUFFERSIZE = 9*2;
    
    void write_buffer_to_ssd(uint8_t *begin, uint8_t *end)
    {
      for(int i=0; begin != end; ++i, ++begin)
        {
          printf("%.2x ", *begin);
          if (i%9 == 8) putchar('\n');
        }
    }
    
    
    static inline uint8_t high_byte(uint16_t word)
    {
      return (word & 0xFF00) >> 8;
    }
    
    
    static inline uint8_t low_byte(uint16_t word)
    {
      return word & 0x00FF;
    }
    
    
    uint8_t * transform_frame(uint16_t *frame_ptr, uint8_t *write_ptr)
    {
      // Hier optional prüfen, ob Frame mit 0x80000000 beginnt
      for(int i = 2; i < 8; i+=2)
        {
          // Hier optional prüfen, ob Markerbytes (high_byte(frame_ptr[i])) erlaubte Werte haben
          *write_ptr++ = low_byte(frame_ptr[i]);
          *write_ptr++ = high_byte(frame_ptr[i+1]);
          *write_ptr++ = low_byte(frame_ptr[i+1]);
        }
      return write_ptr;
    }
    
    
    int main()
    {
      uint16_t rawBuffer[] = {0x8000,0x0000,0x1113,0x1224,0x1200,0x09DE,0x1300,0x07B9,
                              0x8000,0x0000,0x1114,0x1325,0x1201,0x10DF,0x1301,0x08C0,
                              0x8000,0x0000,0x1112,0x1123,0x1299,0x07DD,0x1300,0x06B8};
      uint8_t writeBuffer[WRITEBUFFERSIZE];
      uint8_t *write_ptr = writeBuffer;
    
    
      for(size_t i = 0; i < sizeof(rawBuffer)/sizeof(*rawBuffer); i+=8)  // Hier anpassen, wie du über die echten Daten iterierst
        {
          write_ptr = transform_frame(rawBuffer + i, write_ptr);
          if (write_ptr - writeBuffer >= WRITEBUFFERSIZE)
            {
              write_buffer_to_ssd(writeBuffer, write_ptr);
              write_ptr = writeBuffer;
            }
        }
      write_buffer_to_ssd(writeBuffer, write_ptr);  // Schreibt eventuelle Reste
    }
    


  • Was mich hier etwas verwirrt ist der wilde Mix aus uint8_t, uint16_t und uint32_t
    Stimmt die Annahme, dass ein Frame aus einem 32bit Header mit dem Wert 0x80000000 besteht, dem eine Anzahl von Messdaten folgen, die selbst jeweils aus einem 32bit uint bestehen? Und jeder Messwert hat selbst einen Typ, der in die obersten 8bit kodiert ist, die unteren 24bit sind der Messwert selbst? Das würde ich dann auch so modellieren:

    struct DataPoint
    {
       std::uint32_t RawValue = 0;
    
       std::uint8_t type() const
       {
          return RawValue >> 24;
       }
    
       std::uint32_t value() const
       {
          return RawValue & 0xffffff;
       }
    };
    
    struct Frame
    {
       static const std::uint32_t ValidHeaderValue = 0x8000000;
    
       std::uint32_t Header = 0;
       std::vector<DataPoint> Data;
    
       bool valid() const
       {
          return Header = ValidHeaderValue;
       }
    }
    
    std::vector<uint8_t> process_frame( Frame const& frame )
    {
       std::vector<uint8_t> retval;
       if( frame.valid() )
       {
           for( auto const& dp : frame.Data )
           {
              if( dp.type() == 0x11 || dt.type() == 0x12 || dt.type() == 0x13 )
              {
                 // Funktion von LOBYTE/LOWORD/HIBYTE/HIWORD sollten klar sein, 
                 // hab hier einfach die Makros aus der WINAPI genommen
                 retval.push_back( LOBYTE( LOWORD( dt.value() ) );   
                 retval.push_back( HIBYTE( LOWORD( dt.value() ) );   
                 retval.push_back( LOBYTE( HIWORD( dt.value() ) );   
               }
           }
           return retval;
       }
    }
    
    

  • Mod

    @DocShoe : C-Forum, nicht C++
    Ansonsten Zustimmung, dass ich bei dem uint-Mix auch den Verdacht habe, dass in der Anforderung vielleicht wichtige Teile (unbeabsichtigt) fehlen oder Annahmen gemacht werden, die nicht unbedingt gelten.



  • @SeppJ
    Irre... ich schaffe es immer wieder relevante Details zu ignorieren 😕
    Trotzdem kann man das Datenmodell so aufbauen, man hat dann nur keinen vector zur Verfügung und muss dann halt in ein uint8_t Array schreiben.



  • @DocShoe sagte in uint16_t Array in uint8_t Array umsortieren:

    Was mich hier etwas verwirrt ist der wilde Mix aus uint8_t, uint16_t und uint32_t

    ALSO ... 🙂

    Die Daten kommen per SPI von einem EKG-Frontend, quasi ein 24-bit ADC (stark vereinfacht). Der STM32f469 der die Daten entgegen nimmt kann nur max. 16bit lesen und schreiben (8 kann er auch). Das heißt für ein 32bit Word wie 0x80000000 muss ich zwei 16bit Transfers machen und da ich das per DMA mache flutschen die Daten halt in ein uint16_t array.

    Das ich die Daten dann beim sortieren in ein uint8_t array packe um dieses dann an die SD-Karte zu senden ist evtl. ungeschickt. Vielleicht kann ich auch gleich ein uint16_t array auf die Karte schreiben.

    Ich kontempliere erstmal über eure Ansätze 🙂


  • Mod

    Unabhängig deiner Frage drängt sich der Verdacht auf, dass du vielleicht zu sehr vereinfacht hast, vielelicht unabsichtlich. Denn: Wieso sind da magische Frameheader drin, wenn die Frames immer die gleiche Länge haben? Wozu die Marker 11,12,13, wenn diese immer gleich sind?

    Bist du wirklich sicher, dass deine Annahmen richtig sind und diese Informationen getrost wegeworfen werden können? Denn wenn sie so unnötig wären, dann hätte man sie wahrscheinlich nicht eingebaut.



  • @pauledd sagte in uint16_t Array in uint8_t Array umsortieren:

    EKG-Frontend

    Wenn damit soetwas wie Frontend AD8232 für EKG-Herzfrequenzmesser gemeint ist, machen mir deine Fragen hier Angst.



  • @pauledd
    Du orientierst dein Design am Übetragungsweg, das sollte man mMn nicht machen. Überleg´ dir ein Datenmodell, das deine Daten vernünftig repräsentiert, ohne durch irgendwelche Protokolleigenschaften eingeschränkt zu sein. Anschließend braucht du mind. einen Protokollhandler, der deine Daten im protokollspezifischen Format lesen und schreiben kann. Die Fummelei auf Telegrammebene würde ich so nicht machen.

    PS:
    Schon deine Aufgabenbeschreibung ist falsch. Du willst nicht alle 0x11, 0x12, 0x13 aus den Daten entfernen. Deiner Beschreibung nach willst du alle 0x11, 0x12, 0x13 aus den Telegrammdaten entfernen, wenn sie die obersten 8 Bit eines DWORDs sind.



  • @SeppJ sagte in uint16_t Array in uint8_t Array umsortieren:

    Wieso sind da magische Frameheader drin, wenn die Frames immer die gleiche Länge haben? Wozu die Marker 11,12,13, wenn diese immer gleich sind?

    Die Header mit 0x80 zeigen an das der ADC die Daten fertig gesampled hat und ausgelesen werden können. 0x11 0x12 0x13 bezeichnen die jeweiligen EKG-Elektroden, nämlich LA, LL und RA. Die Anzahl und welche Elektroden ausgelesen werden sollen muss vor dem Transfer konfiguriert werden und für meine Anwendung reichen mir die drei (von fünf möglichen).

    Datenaufbau:
    http://p-bg.de/pics/Screenshot_20210505_142516.png

    Mitschnitt eines Transfers:
    http://p-bg.de/pics/Screenshot_20210505_143730.png

    Beschreibung der Daten Words:
    http://p-bg.de/pics/Screenshot_20210505_145510.png

    Aber das geht schon viel zu weit... die Daten kommen nun mal so an und ich will die Binary Datei so klein wie möglich halten. Ich habe zuvor immer die ganzen 32bit (0x11......., 0x12........0x1300000) in einer Binary gespeichert und das klappte soweit ganz gut.

    Also werfe ich den Word-Identifizierer und den Header weg und spare fast 500MB Daten wenn ich 24h Daten auf die SD-Karte logge...



  • @DocShoe sagte in uint16_t Array in uint8_t Array umsortieren:

    Die Fummelei auf Telegrammebene würde ich so nicht machen.

    Was meinst du mit Telegramm?



  • @manni66 sagte in uint16_t Array in uint8_t Array umsortieren:

    Wenn damit soetwas wie Frontend AD8232 für EKG-Herzfrequenzmesser gemeint ist, machen mir deine Fragen hier Angst.

    Keine Angst, das ganze wird nicht am echten Menschen getestet sondern nur simuliert 🙂


  • Mod

    @pauledd sagte in uint16_t Array in uint8_t Array umsortieren:

    Aber das geht schon viel zu weit... die Daten kommen nun mal so an und ich will die Binary Datei so klein wie möglich halten. Ich habe zuvor immer die ganzen 32bit (0x11......., 0x12........0x1300000) in einer Binary gespeichert und das klappte soweit ganz gut.

    Also werfe ich den Word-Identifizierer und den Header weg und spare fast 500MB Daten wenn ich 24h Daten auf die SD-Karte logge...

    Kompression?



  • @SeppJ sagte in uint16_t Array in uint8_t Array umsortieren:

    Kompression?

    Damit kenne ich mich absolut nicht aus und würde den Rahmen sprengen. Ich weiß auch nicht wieviel CPU Zeit Komprimierung beanspruchen würde da das ganze nicht Zeitunkritisch ist.

    Der Speicher auf dem µC ist schon fast gänzlich für den Lese/Schreibpuffer ausgereizt und vom Timing her würde ich ungern noch in irgendwelchen zusätzlichen Funktionen CPU Zeit investieren.

    Später ist evtl. noch geplant das ISHNE Binärformat für EKG Daten zu implementieren. Aber das ist nur eine Idee...


  • Mod

    Ich meinte das nicht so, dass du selber Kompressionsalgoithmen implementieren sollst. Sondern, dass du fertige Standardkompressionsprogramme nutzen solltest. Die verkleinern deine Daten nochmals deutlich mehr als das, was du dir hier selber ausdenkst, und du sparst dabei massiv deine eigene (nicht kostenlose) Zeit, und vermeidest zudem auch alle vorstellbaren Fehler.

    Aber wenn's wirklich ein Ressourcenbottleneck gibt, dann verwirf die Idee. Oder besser noch: Prüf es einmalig. Vielleicht verschätzt du dich ja. Wenn's nämlich doch reicht, dann gewinnst du viel.



  • @manni66 sagte in uint16_t Array in uint8_t Array umsortieren:

    @pauledd sagte in uint16_t Array in uint8_t Array umsortieren:

    EKG-Frontend

    Wenn damit soetwas wie Frontend AD8232 für EKG-Herzfrequenzmesser gemeint ist, machen mir deine Fragen hier Angst.

    +1


Anmelden zum Antworten