farrellf / TelemetryViewer

Data Visualization Tool
164 stars 69 forks source link

Calculating binary checksum? #24

Open MiloMindbender opened 5 years ago

MiloMindbender commented 5 years ago

I've had some problems getting binary packets to work right. Does anyone have an example of how to correctly calculate the checksum for the binary packet, I'm probably messing up something very simple.

farrellf commented 5 years ago

I plan to add example code to the program, like I did for CSV mode, but in the mean time here is some code I use with an LPC1768:

/**
 * Transmits a number of uint16's to the PC via DMA. An 0xAA sync byte and a 16bit checksum are automatically wrapped around the data.
 *
 * @param count          The number of uint16's to send.
 * @param first_value    The first uint16 to send.
 * @param ...            Subsequent uint16's to send.
 */
void uart1_transmit_uint16s(uint8_t count, uint16_t first_value, ...) {

    va_list arglist;
    va_start(arglist, first_value);

    uint8_t i = 0;
    uint16_t checksum = 0;

    tx_buffer[i++] = 0xAA; // sync word

    tx_buffer[i++] = first_value & 0xFF;
    tx_buffer[i++] = first_value >> 8;
    checksum += first_value;
    count--;

    while(count > 0) {

        uint16_t value = va_arg(arglist, int);
        tx_buffer[i++] = value & 0xFF;
        tx_buffer[i++] = value >> 8;
        checksum += value;
        count--;

    }

    tx_buffer[i++] = checksum & 0xFF;
    tx_buffer[i++] = checksum >> 8;

    while((LPC_GPDMACH4->DMACCConfig & 0x01) != 0);                     // wait for previous DMA transfer to finish
    LPC_GPDMACH4->DMACCSrcAddr = (uint32_t) tx_buffer;                  // source address: the transmit buffer array
    LPC_GPDMACH4->DMACCControl = (i << 0) | (1 << 26);                  // transfer size, increment source address
    LPC_GPDMACH4->DMACCConfig |= (1 << 0);                              // enable ch4

}
Driver55 commented 3 years ago

I am working with an ESP32 in Arduino environment and from what I understand it is a little endian. But I can't transmit binary data, not even a simple uint16. I feel like I've gone back 30 years. I don't understand if I have to also consider the Sync-byte in the checksum calculation or not. Is there somewhere a clear and unambiguous documentation explaining the exact structure in case of a binary protocol. My initial test code is very basic like the following: SPO2_ESP32_PhysioNet_Data _ Arduino 1 8 13 2021-05 (2)

My setting is : Telemetry Viewer v0 7 2021-05-22 12 51 18 (1)

Can anyone tell me what am I wrong ??

farrellf commented 3 years ago

The uint16 checksum needs to sum up the payload region as uint16 chunks, not as bytes. For example, if you're sending a uint16 number and two uint8 bitfields, the firmware might look something like this:

static uint8_t buffer[7] = {0};
uint16_t checksum = 0;

buffer[0] = 0xAA;

buffer[1] = number1 & 0xFF;
buffer[2] = number1 >> 8;
checksum += number1;

buffer[3] = bitfields1; // uint8 bitfield
buffer[4] = bitfields2; // another uint8 bitfield
checksum += (bitfields2 << 8) | bitfields1;

buffer[5] = checksum & 0xFF;
buffer[6] = checksum >> 8;

uart1_transmit(buffer, 7);
Driver55 commented 3 years ago

The uint16 checksum needs to sum up the payload region as uint16 chunks, not as bytes. For example, if you're sending a uint16 number and two uint8 bitfields, the firmware might look something like this:

.............

Thankyou for the answer, .... but how to transfer a uint32_t or a int32_t value ? With the CSV method it is possible, and it is interpreted correctly . Is casting to float the only way ??

farrellf commented 2 years ago

The latest release has demo code for calculating the checksum when in UDP mode, and also added support for uint32 datasets:

http://www.farrellf.com/projects/software/2021-07-24_Telemetry_Viewer_v0.8/ https://www.youtube.com/watch?v=NUBm9b8YQMQ&t=1249s