unsigned short UpdateCRC(unsigned short crcIn, unsigned char const* pBuffer, unsigned int len)
{
    unsigned short crcOut = crcIn;
    for(unsigned int i=0; i < len; ++i, ++pBuffer)
    {
        crcOut = update_crc_ccitt(crcOut, *pBuffer);
    }

    return crcOut;
}
Exemplo n.º 2
0
void main( int argc, char *argv[] ) {

    char input_string[MAX_STRING_SIZE];
    char *ptr, *dest, hex_val, prev_byte;
    unsigned short crc_16, crc_16_modbus, crc_ccitt_ffff, crc_ccitt_0000, crc_ccitt_1d0f, crc_dnp, crc_sick, low_byte, high_byte;
    unsigned long crc_32;
    int a, ch, do_ascii, do_hex;
    FILE *fp;

    do_ascii = FALSE;
    do_hex   = FALSE;

    printf( "\nCRC algorithm sample program\nLammert Bies,  Version " CRC_VERSION "\n\n" );

    if ( argc < 2 ) {

        printf( "Usage: tst_crc [-a|-x] file1 ...\n\n" );
        printf( "    -a Program asks for ASCII input. Following parameters ignored.\n" );
        printf( "    -x Program asks for hexadecimal input. Following parameters ignored.\n" );
        printf( "       All other parameters are treated like filenames. The CRC values\n" );
        printf( "       for each separate file will be calculated.\n" );

        exit( 0 );
    }

    if ( ! strcmp( argv[1], "-a" )  ||  ! strcmp( argv[1], "-A" ) ) do_ascii = TRUE;
    if ( ! strcmp( argv[1], "-x" )  ||  ! strcmp( argv[1], "-X" ) ) do_hex   = TRUE;

    if ( do_ascii  ||  do_hex ) {

        printf( "Input: " );
        fgets( input_string, MAX_STRING_SIZE-1, stdin );
    }

    if ( do_ascii ) {

        ptr = input_string;
        while ( *ptr  &&  *ptr != '\r'  &&  *ptr != '\n' ) ptr++;
        *ptr = 0;
    }

    if ( do_hex ) {

        ptr  = input_string;
        dest = input_string;

        while( *ptr  &&  *ptr != '\r'  &&  *ptr != '\n' ) {

            if ( *ptr >= '0'  &&  *ptr <= '9' ) *dest++ = (char) ( (*ptr) - '0'      );
            if ( *ptr >= 'A'  &&  *ptr <= 'F' ) *dest++ = (char) ( (*ptr) - 'A' + 10 );
            if ( *ptr >= 'a'  &&  *ptr <= 'f' ) *dest++ = (char) ( (*ptr) - 'a' + 10 );

            ptr++;
	}

        * dest    = '\x80';
        *(dest+1) = '\x80';
    }



    a = 1;

    do {

        crc_16         = 0;
        crc_16_modbus  = 0xffff;
        crc_dnp        = 0;
        crc_sick       = 0;
        crc_ccitt_0000 = 0;
        crc_ccitt_ffff = 0xffff;
        crc_ccitt_1d0f = 0x1d0f;
        crc_32         = 0xffffffffL;



        if ( do_ascii ) {

            prev_byte = 0;
            ptr       = input_string;

            while ( *ptr ) {

                crc_16         = update_crc_16(    crc_16,         *ptr            );
                crc_16_modbus  = update_crc_16(    crc_16_modbus,  *ptr            );
                crc_dnp        = update_crc_dnp(   crc_dnp,        *ptr            );
                crc_sick       = update_crc_sick(  crc_sick,       *ptr, prev_byte );
                crc_ccitt_0000 = update_crc_ccitt( crc_ccitt_0000, *ptr            );
                crc_ccitt_ffff = update_crc_ccitt( crc_ccitt_ffff, *ptr            );
                crc_ccitt_1d0f = update_crc_ccitt( crc_ccitt_1d0f, *ptr            );
                crc_32         = update_crc_32(    crc_32,         *ptr            );

                prev_byte = *ptr;
                ptr++;
            }
        }



        else if ( do_hex ) {

            prev_byte = 0;
            ptr       = input_string;

            while ( *ptr != '\x80' ) {

                hex_val  = (char) ( ( * ptr     &  '\x0f' ) << 4 );
                hex_val |= (char) ( ( *(ptr+1)  &  '\x0f' )      );

                crc_16         = update_crc_16(    crc_16,         hex_val            );
                crc_16_modbus  = update_crc_16(    crc_16_modbus,  hex_val            );
                crc_dnp        = update_crc_dnp(   crc_dnp,        hex_val            );
                crc_sick       = update_crc_sick(  crc_sick,       hex_val, prev_byte );
                crc_ccitt_0000 = update_crc_ccitt( crc_ccitt_0000, hex_val            );
                crc_ccitt_ffff = update_crc_ccitt( crc_ccitt_ffff, hex_val            );
                crc_ccitt_1d0f = update_crc_ccitt( crc_ccitt_1d0f, hex_val            );
                crc_32         = update_crc_32(    crc_32,         hex_val            );

                prev_byte = hex_val;
                ptr      += 2;
            }

            input_string[0] = 0;
        }



        else {

            prev_byte = 0;
            fp        = fopen( argv[a], "rb" );

            if ( fp != NULL ) {

                while( ( ch=fgetc( fp ) ) != EOF ) {

                    crc_16         = update_crc_16(    crc_16,         (char) ch            );
                    crc_16_modbus  = update_crc_16(    crc_16_modbus,  (char) ch            );
                    crc_dnp        = update_crc_dnp(   crc_dnp,        (char) ch            );
                    crc_sick       = update_crc_sick(  crc_sick,       (char) ch, prev_byte );
                    crc_ccitt_0000 = update_crc_ccitt( crc_ccitt_0000, (char) ch            );
                    crc_ccitt_ffff = update_crc_ccitt( crc_ccitt_ffff, (char) ch            );
                    crc_ccitt_1d0f = update_crc_ccitt( crc_ccitt_1d0f, (char) ch            );
                    crc_32         = update_crc_32(    crc_32,         (char) ch            );

                    prev_byte = (char) ch;
                }

                fclose( fp );
            }

            else printf( "%s : cannot open file\n", argv[a] );
        }



        crc_32 ^= 0xffffffffL;

        crc_dnp   = ~crc_dnp;
        low_byte  = (crc_dnp & 0xff00) >> 8;
        high_byte = (crc_dnp & 0x00ff) << 8;
        crc_dnp   = low_byte | high_byte;

        low_byte  = (crc_sick & 0xff00) >> 8;
        high_byte = (crc_sick & 0x00ff) << 8;
        crc_sick  = low_byte | high_byte;

        printf( "%s%s%s :\nCRC16              = 0x%04X      /  %u\n"
                          "CRC16 (Modbus)     = 0x%04X      /  %u\n"
                          "CRC16 (Sick)       = 0x%04X      /  %u\n"
                          "CRC-CCITT (0x0000) = 0x%04X      /  %u\n"
                          "CRC-CCITT (0xffff) = 0x%04X      /  %u\n"
                          "CRC-CCITT (0x1d0f) = 0x%04X      /  %u\n"
                          "CRC-DNP            = 0x%04X      /  %u\n"
                          "CRC32              = 0x%08lX  /  %lu\n"
                    , (   do_ascii  ||    do_hex ) ? "\""    : ""
                    , ( ! do_ascii  &&  ! do_hex ) ? argv[a] : input_string
                    , (   do_ascii  ||    do_hex ) ? "\""    : ""
                    , crc_16,         crc_16
                    , crc_16_modbus,  crc_16_modbus
                    , crc_sick,       crc_sick
                    , crc_ccitt_0000, crc_ccitt_0000
                    , crc_ccitt_ffff, crc_ccitt_ffff
                    , crc_ccitt_1d0f, crc_ccitt_1d0f
                    , crc_dnp,        crc_dnp
                    , crc_32,         crc_32     );

        a++;

    } while ( a < argc );

}  /* main (tst_crc.c) */
Exemplo n.º 3
0
/* Subroutine: bit_slicer()
 * Description: recover bits from the channel
 * Input:
 *  channel: up to 2 channels are supported for now
 *  amplitude: sample value
 * Output: none
 */
forceinline void bit_slicer(const uint8_t channel, const int32_t amplitude) {
    /* Why is everything so "static"? As mentioned in the "forceinline"
     * comment way above, these subroutines are not real subroutines. Thus we
     * need to use "static" in order to preserve the buffer contents. Or use
     * global variables.
     * The best part is why the 'packet' buffer is also "static": nRF905
     * resends the packets (sometimes on different channels). If we miss some
     * bits on the first try, perhaps we manage to get them on the second
     * attempt. Note that this is only possible because we differentiate
     * "0" from "1" from "missing" during the decoding step!
     */
    static int32_t cb_buf_pcm[2][smooth_buffer_size];
    static uint16_t cb_idx_pcm[2];
    static uint8_t cb_buf_bit[2][buffer_size];
    static uint16_t cb_idx_bit[2];
    static int32_t sliding_sum[2];
    static uint16_t skip_samples[2];
    static uint8_t packet[max_packet_bytes];
    uint16_t i, j, k;
    uint16_t bad_manchester;
    uint16_t crc16 = 0xffff;

    /* Simplest possible noise filter (at least, in software): sliding average.
     */
    cb_write(pcm[channel], amplitude);

    sliding_sum[channel] -= cb_readn(pcm[channel], average_n);
    sliding_sum[channel] += amplitude;

    /* Input for bit_slicer() is the magnitude at the space pulse frequency minus
     * the magnitude at the mark pulse frequency. If this value is positive,
     * the space signal is stronger than the mark signal. Thus, by convention,
     * we have the "0" symbol. Same thing happens for the "1" symbol.
     * However, these symbols are not bits yet: actual bits are encoded using
     * the Manchester coding.
     */
    cb_write(bit[channel], sliding_sum[channel] > 0 ? 1 : 0);

    /* Don't reprocess samples if we already decoded this as a valid message.
     * This saves a lot of processing time, specially when dealing with busy
     * channels.
     */
    if (skip_samples[channel]) {
        skip_samples[channel]--;
        return;
    }

    /* Attempt to match the preamble bit pattern. Bail out on the first
     * discrepancy to spare CPU cycles. This is the hottest code path
     * (most CPU-intensive).
     */
    for (
        i = packet_samples, j = 0;
        j < preamble_bits;
        i -= symbol_samples, j++
    ) {
        if (preamble_pattern[j] != cb_readn(bit[channel], i))
            return;
    }

    /* When the preamble looks like valid, attempt to decode the rest of the
     * packet. All the bits (including the preamble) are Manchester-coded.
     * This means that the symbol values do not matter, only symbol transitions
     * do encode the actual bits. For instance, "01" means "1", while "10" means
     * "0". Both "00" and "11" are invalid, when one of these is detected, the
     * bit is skipped (and the bit from the previous decoding attempt for this
     * position is used). If there are too many invalid bits, probably the
     * thing interpreted as preamble was a fluctuation in randomness, so we
     * bail out. And yes, preamble is also Manchester-coded, in case you're
     * wondering. nRF905 preamble is usually stated as having 10 bits. But
     * Manchester-coded nRF905 preamble has 20 bits.
     */
    bad_manchester = 0;
    for (
        i = packet_samples - preamble_bits * symbol_samples, j = 0;
        i > symbol_samples;
        i -= symbol_samples * 2, j++
    ) {
        k = j / 8;
        if (cb_readn(bit[channel], i) != cb_readn(bit[channel], i + symbol_samples)) {
            // valid Manchester
            if (cb_readn(bit[channel], i)) {
                // set to 1
                packet[k] |=  (1 << (7 - (j & 7)));
            } else {
                // set to 0
                packet[k] &= ~(1 << (7 - (j & 7)));
            }
        } else {
            // heuristic, skip if too many bit encoding errors
            if (++bad_manchester > j / 2)
                return;
        }

        /* At the end of every 8-bit chunk, update CRC checksum. When the
         * checksum is (looks like) correct, proceed and output the packet
         * bytes, regardless the packet size. It is quite possible that some
         * incompletely processed packet appears to have a correct CRC.
         * If the desired packet size is known/fixed and/or CRC is unavailable,
         * it is possible to use packet size as the "packet received" condition.
         */
        if ((j & 7) == 7) {
            crc16 = use_crc ? update_crc_ccitt(crc16, packet[k]) : 0;
            k++;
            if (crc16 == 0 && k == (packet_bytes ? packet_bytes : k)) {
                output((const uint8_t *) packet, k, channel);
                skip_samples[channel] = symbol_samples * 2 * (preamble_bits + k * 8);
                /* memset((void *) packet, 0, sizeof(packet)); */
                return;
            }
        }
    }
}
Exemplo n.º 4
0
void create_dls_datagroup (char* text, int padlen, UCHAR*** p_dlsdg, int* p_numdg) {

    UCHAR dlsseg[8][16];      // max 8 segments, each max 16 chars
    UCHAR** dlsdg;            // Array of datagroups composing dls text;


    int numseg;               // Number of DSL segments
    int lastseglen;           // Length of the last segment
    int numdg;                // Number of data group
    int xpadlengthmask;
    int i, j, k, z, idx_start_crc, idx_stop_crc;
    USHORT dlscrc;
    static UCHAR toggle = 0;

    if (toggle == 0)
        toggle = 1;
    else
        toggle = 0;

    numseg = strlen(text) / 16;
    lastseglen = strlen(text) % 16;
    if (padlen-9 >= 16) {
        if (lastseglen > 0) {
            numseg++;   // The last incomplete segment
        }

        // The PAD can contain the full segmnet and overhead (9 bytes)
        numdg = numseg;

    }
    else {
        // Each 16 char segment span over 2 dg
        numdg = numseg * 2;

        if (lastseglen > 0) {
            numseg++;              // The last incomplete segment

            if (lastseglen <= padlen-9) {
                numdg += 1;
            }
            else {
                numdg += 2;
            }
        }
    }

    *p_numdg = numdg;
    fprintf(stderr, "PAD Length: %d\n", padlen);
    fprintf(stderr, "DLS text: %s\n", text);
    fprintf(stderr, "Number of DLS segments: %d\n", numseg);
    fprintf(stderr, "Number of DLS data groups: %d\n", numdg);

    xpadlengthmask = get_xpadlengthmask(padlen);

    *p_dlsdg = (UCHAR**) malloc(numdg * sizeof(UCHAR*));
    dlsdg = *p_dlsdg;

    i = 0;
    for (z=0; z < numseg; z++) {
        char* curseg;
        int curseglen;
        UCHAR firstseg, lastseg;

        curseg = &text[z * 16];
        fprintf(stderr, "Segment number %d\n", z+1);

        if (z == 0) {             // First segment
            firstseg = 1;
        }
        else {
            firstseg = 0;
        }

        if (z == numseg-1) {      //Last segment
            if (lastseglen != 0) {
                curseglen = lastseglen;
            }
            else {
                curseglen = 16;
            }
            lastseg = 1;
        }
        else {
            curseglen = 16;
            lastseg = 0;
        }

        if (curseglen <= padlen-9) {  // Segment is composed of 1 data group
            dlsdg[i] = (UCHAR*) malloc(padlen * sizeof(UCHAR));

            // FF-PAD Byte L (CI=1)
            dlsdg[i][padlen-1]=0x02;

            // FF-PAD Byte L-1 (Variable size X_PAD)
            dlsdg[i][padlen-2]=0x20;

            // CI => data length = 12 (011) - Application Type=2
            // (DLS - start of X-PAD data group)
            dlsdg[i][padlen-3]=(xpadlengthmask<<5) | 0x02;

            // End of CI list
            dlsdg[i][padlen-4]=0x00;

            // DLS Prefix (T=1,Only one segment,segment length-1)
            dlsdg[i][padlen-5]=((toggle*8+firstseg*4+lastseg*2+0)<<4) | (curseglen-1);

            if (firstseg==1) {
                // DLS Prefix (Charset standard)
                dlsdg[i][padlen-6]=0x00;
            }
            else {
                // DLS SegNum
                dlsdg[i][padlen-6]=z<<4;
            }

            // CRC start from prefix
            idx_start_crc = padlen-5;

            // DLS text
            for (j = 0; j < curseglen; j++) {
                dlsdg[i][padlen-7-j] = curseg[j];
            }

            idx_stop_crc = padlen - 7 - curseglen+1;

            dlscrc = 0xffff;
            for (j = idx_start_crc; j >= idx_stop_crc; j--) {
                dlscrc = update_crc_ccitt(dlscrc, dlsdg[i][j]);
            }

            dlscrc = ~dlscrc;
            fprintf(stderr, "crc=%x ~crc=%x\n", ~dlscrc, dlscrc);

            dlsdg[i][padlen-7-curseglen] = (dlscrc & 0xFF00) >> 8;     // HI CRC
            dlsdg[i][padlen-7-curseglen-1] = dlscrc & 0x00FF;          // LO CRC

            // NULL PADDING
            for (j = padlen-7-curseglen-2; j >= 0; j--) {
                dlsdg[i][j]=0x00;
            }

            fprintf(stderr, "Data group: ");
            for (j = 0; j < padlen; j++)
                fprintf(stderr, "%x ", dlsdg[i][j]);
            fprintf(stderr, "\n");
            i++;

        }
        else {   // Segment is composed of 2 data groups