Bits falsch gesetzt, crc Prüfsumme immer flasch

Hallo Leute, ich portiere grade ein Javascript code auf einen avr in C.
Genaugenomen handelt es sich eine crc Prüfsummen berechnung von 40bits .

Der JavaScript teil schaut so aus:

function CRC(crcBits) {
      console.log(crcBits.join(""))
        let crc = [0, 0, 0, 0, 0, 0, 0];
        for (i = 0; i < crcBits.length; ++i) {
            let doinvert = (1 == crcBits[i]) ^ crc[6];
            crc[6] = crc[5] ^ doinvert;
            crc[5] = crc[4];
            crc[4] = crc[3];
            crc[3] = crc[2];
            crc[2] = crc[1] ^ doinvert;
            crc[1] = crc[0];
            crc[0] = doinvert;
        }
        console.log(crc.reverse().join(""));
        crcBits.push(...crc.reverse());
        return crcBits;
    }

crcBits ist ein Array enthält 40 bits wie folgt: 1111_0010_1000_1000_1100_0000_1111_0000_0111_0011
da kommt als Prüsumme 1100011.

Aus übersicht's Gründen und Speicher mangel beim AVR , habe die Telegramm Daten in den PROGMEM gepackt.

const byte telegrammArray[10][4] PROGMEM = {
  {1, 1, 1, 1},//BOS
  {0, 0, 1, 0},//LAND
  {1, 0, 0, 0},//ORT1
  {1, 0, 0, 0},//ORT2
  {1, 1, 0, 0},//KFZ1
  {0, 0, 0, 0},//KFZ2
  {1, 1, 1, 1},//KFZ3
  {0, 0, 0, 0},//KFZ4
  {0, 1, 1, 1},//AUFTRAG
  {0, 0, 1, 1} //Baustufe, Richtung, Taktische Kurzinfo
};

Zur weiterverarbeitung schreibe ich alles in eine 64 bit Variable die global in der .ino Datei steht:

volatile uint64_t initial_telegrammData = 0x00ULL; //<-global

void initTelegramm() {
  volatile byte bitIndex = 40;
  for (volatile byte i = 0;  i < sizeof(telegrammArray) / sizeof(telegrammArray[0]); i++) {
    for (volatile byte y = 0; y < sizeof(telegrammArray[i]) / sizeof(telegrammArray[i][0]); y++) {
      bool _word = pgm_read_word(&telegrammArray[i][y]);
      if (_word) {
        initial_telegrammData |= (1ULL << bitIndex);
      }
      bitIndex -= 1;
    }
  }
}

Die crc berechnung schaut so aus:

byte calcCRC(uint64_t data) {
  bool crc[] = {0, 0, 0, 0, 0, 0, 0};
  volatile byte i = 40;
  byte CRC = 0x00;
  for (; i > 0; --i) {
    Serial.print((bool)(data & ((uint64_t)1<<i)), DEC);
    bool doinvert =  (1 == (data & ((uint64_t)1<<i))) ^ crc[6];
    crc[6] = crc[5] ^ doinvert;
    crc[5] = crc[4];
    crc[4] = crc[3];
    crc[3] = crc[2];
    crc[2] = crc[1] ^ doinvert;
    crc[1] = crc[0];
    crc[0] = doinvert;
  }

  for (i = 0; i < 7; i++) {
    CRC |= (crc[i] << i);
  }
  return CRC;
}

uint64_t data ist initial_telegrammData.
Das Serial.print((bool)(data & ((uint64_t)1<<i)), DEC); sagt mir das irgendwas nicht stimmt.

Ich erwarte 1111_0010_.........0011. Ausgegeben wird: 1111_0111........0111

Das Problem ist aber allen anschien nach schon in der Funktion initTelegramm zu finden.

Ich habe auch schon das Progmem Array rückwärts durchlaufen und bitIndex um 1 inkrementiert.
Da kam aber auch nur Murks raus.

Jedenfalls der javascript code funktioniert und in C ist eine Krücke versteckt. Nur wo?

Dank schon mal im voraus :innocent:.

Kann mal bitte ein Amin den Titel korrigieren. Es Sollte Prüfsumme lauten :sweat_smile:

bool _word = pgm_read_word(&telegrammArray[i][y]);

read_byte(). read_word() liest zwei Bytes aus.

Wieso packst du nicht wenigstens 4 Bit in ein Byte, statt jedes Bit einzeln zu speichern? Dann hat man immer noch die Trennung der Bedeutungen

EDIT: Durch das Lesen von zwei Bytes und die etwas unsaubere Verwendung von bool statt byte handelst du dir leicht Fehler ein:

void setup ()
{
  Serial.begin(115200);  

  bool b1 = 0x1000;
  byte b2 = 0x1000;

  Serial.println(b1);
  Serial.println(b2);
}

Macht:

1
0

bool und byte mögen sehr ähnlich erscheinen. Aber der Compiler behandelt die leicht unterschiedlich da sie unterschiedliche Dinge darstellen

Laß die Admins in Ruhe und auch die Moderatoren :wink:
Das kann der Autor des Posts auch selbst und hat es auch schon gemacht.
Grüße Uwe

Ja ok.

Weil ich den Quellcode später jemanden überlassen will der 0 Plan von Programmieren hat. Deshalb sollte das so einfach und übersichtlich wie möglich gehalten werden.

Ok.

Ich habe jetzt gemerkt das das if in der initTelegramm Funktion falsch war und habe deswegen etwas korrigiert:

void initTelegramm() {
  volatile byte bitIndex = 40;
  for (volatile byte i = 0;  i < sizeof(telegrammArray) / sizeof(telegrammArray[0]); i++) {
    for (volatile byte y = 0; y < sizeof(telegrammArray[i]) / sizeof(telegrammArray[i][0]); y++) {
      byte _word = pgm_read_word(&telegrammArray[i][y]);
      initial_telegrammData |= ((uint64_t)_word << bitIndex);
      bitIndex -= 1;
    }
  }

Jetzt passt auch die Reihenfolge der bits. ABER die crc Prüfsumme ist immer 0 :unamused:

Wofür?

Wenn das doch ein Byte Array ist, tut es sicherlich nicht das, was du dir wünscht.

wenn du mal deine Funktionen mit Testdaten in einen Testsketch geben würdest und eine Testausgabe z.B. auf serial machst, dann könnten andere direkt helfen.

Dazu noch ein HTML mit Formular und dem funktionierenden Javascript aus dem wir ersehen, was "richtig" ist dann könnte das evtl. einige Helfer motivieren dich zu unterstützen.

Warum nicht??

Aber anscheint doch.

Was genau ist den jetzt ein Testsketch? Ein Code den Du fertig ausführen kannst?
Bitte:


const byte telegrammArray[10][4] PROGMEM = {
  {1, 1, 1, 1},//BOS
  {0, 0, 0, 0},//LAND
  {1, 0, 0, 0},//ORT1
  {1, 0, 0, 0},//ORT2
  {1, 1, 0, 0},//KFZ1
  {0, 0, 0, 0},//KFZ2
  {1, 1, 1, 1},//KFZ3
  {0, 0, 0, 0},//KFZ4
  {0, 1, 1, 1},//AUFTRAG
  {0, 0, 1, 1} //Baustufe, Richtung, Taktische Kurzinfo
};

volatile uint64_t initial_telegrammData = 0x00ULL;


void initTelegramm() {
  volatile byte bitIndex = 40;
  for (volatile byte i = 0;  i < sizeof(telegrammArray) / sizeof(telegrammArray[0]); i++) {
    for (volatile byte y = 0; y < sizeof(telegrammArray[i]) / sizeof(telegrammArray[i][0]); y++) {
      byte _word = pgm_read_word(&telegrammArray[i][y]);
      initial_telegrammData |= ((uint64_t)_word << bitIndex);
      bitIndex -= 1;
    }
  }
}

void setup() {
  Serial.begin(9600);
  Serial.println("Hello there");
  initTelegramm();
  makeTelegramm();

}

void loop() {
  // put your main code here, to run repeatedly:

}

byte calcCRC(uint64_t data) {
  byte crc[] = {0, 0, 0, 0, 0, 0, 0};
  volatile byte i = 40;
  byte CRC = 0x00;
  for (; i > 0; --i) {
    Serial.print((byte)bitRead(data, i), DEC);
    byte doinvert =  (1 == (byte)bitRead(data, i)) ^ crc[6];
    crc[6] = crc[5] ^ doinvert;
    crc[5] = crc[4];
    crc[4] = crc[3];
    crc[3] = crc[2];
    crc[2] = crc[1] ^ doinvert;
    crc[1] = crc[0];
    crc[0] = doinvert;
  }

  for (i = 0; i < 7; i++) {
    CRC |= (crc[i] << i);
  }
  return CRC;
}

void makeTelegramm() {
  const byte CRC = calcCRC(initial_telegrammData);
  Serial.print("CRC: ");
  Serial.println(CRC, BIN);
}

Das empfinde ich als schwierig. Der JS Code umfasst ca 2000 Zeilen das liest sich keiner durch. Da müsste ich den Code einkürzen und das auch noch so, dass er funktioniert. Das ist mir dann doch zu viel Arbeit.

PS.: Ich habe den Fehler bereits gefunden es lag wider am type cast

byte doinvert =  (1 == (byte)bitRead(data, i)) ^ crc[6];

Ich denke nicht, das am type cast lag.

Wenn du 0xff & 0x40 machst, bekommst du 0x40 und nicht 0x01. Dein test sollte gehen wenn du auf ungleich 0 testest:

 bool doinvert = (0 !=  (data & ...

wg. unnötig, und damit eher falsch.

Dazu weiß ich dann auch nix mehr zu sagen, außer:
Och!

Nur weil du das jetzt auf byte geändert hast. Mit read_byte() wäre es auch mit bool gegangen. Obwohl byte das schon sinnvoller ist

Unnötig ist aber nicht zwingend falsch.

:grimacing:

Naja, ich habe es mir zur Angewohnheit gemacht für Schaltungen die nur logisch 1(true) oder logisch 0 (false) benötigen, bool zu nehmen. In Javascript kann man sich da schon mal vertun denn false === 0 = nicht war, wiederum false == 0 = wahr.

Jedenfalls, das Thema ist gelöst.

Richtig!

Dann, sei doch bitte auch konsequent und nimm doch auch die Funktionen, welche extra fürs byte lesen gebaut wurden, wenn du byte Zellen auslesen möchtest.
Alles andere halte ich für absurd.

Klar kannst du dem Optimizer eine fette Kugel ans Bein klemmen, wenn dir das Spaß macht. Aber konsequent oder klug ist das nicht. Es macht das Programm lahm, und das bei dir ohne jeden Sinn.
volatile verwendet man nur, wenn es nötig ist. Ist es bei dir nicht.

:japanese_ogre: :japanese_ogre: :japanese_ogre:

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.