/** * Calculates 32-bit CRC for the specified input string * * @return A 32-bit unsigned integer representing the CRC */ uint32_t calculateCRC32C(uint32_t crc, const char *buf, size_t len) { // If the string is empty, return 0 if (len == 0) { return crc; } // XOR the initial CRC with INT_MAX crc ^= 0xFFFFFFFF; // Align the input to the word boundary for (; (len > 0) && ((size_t)buf & ALIGN_MASK); len--, buf++) { crc = _mm_crc32_u8(crc, *buf); } // Blast off the CRC32 calculation #ifdef __x86_64__ CALC_CRC(_mm_crc32_u64, crc, uint64_t, buf, len); #endif CALC_CRC(_mm_crc32_u32, crc, uint32_t, buf, len); CALC_CRC(_mm_crc32_u16, crc, uint16_t, buf, len); CALC_CRC(_mm_crc32_u8, crc, uint8_t, buf, len); // Post-process the crc return (crc ^= 0xFFFFFFFF); }
uint8_t check_crc(data_t* data) { uint8_t remainder = CRC_INITIAL_REMAINDER; remainder ^= (*data).a; CALC_CRC(remainder); remainder ^= (*data).b; CALC_CRC(remainder); remainder ^= (*data).c; CALC_CRC(remainder); if(remainder != (*data).d) return 1; return 0; }
uint8_t manchester_send(data_t* data) { (*data).d = CRC_INITIAL_REMAINDER; ZERO(); // Calculate CRC here in parts. This should be well timed. (*data).d ^= (*data).a; // 3 cycles CALC_CRC((*data).d); // Grand total 48+24+3 = 75 cycles = 9.375 us. (*data).d ^= (*data).b; // 3 cycles CALC_CRC((*data).d); // Grand total 48+24+3 = 75 cycles = 9.375 us. del_us(25 - 9.375 - 9.375 - 0.250); ONE(); (*data).d ^= (*data).c; // 3 cycles CALC_CRC((*data).d); // Grand total 48+24+3 = 75 cycles = 9.375 us. del_us(25 - 9.375 - 0.250); for(uint8_t i = 32; i > 0; --i) { if((*data).a & 0b10000000) { ZERO(); del_us(25-0.125); ONE(); } else { ONE(); del_us(25-0.125); ZERO(); } del_us(25-0.125-2.5-0.250); (*data).abcd = (*data).abcd << 1; } ONE(); return COMM_SUCCESS; }
uint8_t manchester_receive(data_t* data) // Function call 4 clk, function overhead at start 5 clk { // Grand total from the edge 15 us + 1.125 us = 16.125 us. uint8_t time_tmp; uint8_t remainder = CRC_INITIAL_REMAINDER; // 0 clk PULLUP_OFF(); (*data).abcd = 0; // 8 clk = 1 us. //if(pinstat) // return 1; // Wait for high transition // Already consumed 17.125 us. For +13 us time window, it needs to come within (25+13) - 17.125 us = 20.875 us = 167 clk // Require two successive high readings. // LOOP: SBIS 2 + SBIC 2 + SUBI 1 + BRCC 2 = 7 clk /round. time_tmp = 24; //167/7 would be 23.85, round to 24. while(time_tmp--) { if(pinstat && pinstat) goto OK1; } PULLUP_ON(); return 2; OK1: // Now we are exactly aligned at first '1', which is discarded. _delay_us(10.125 + 1.5); // Compensation for CRC delay, see below. // +1.5 = measured correction. for(uint8_t i = 0; i < 32; i++) { (*data).abcd <<= 1; // 20 clk = 2.5 us // Align at 35.0 us from previous data bit. 37.5 us is // halfway between the optional edge and the next data bit. // Sample the value between 35.0 us and 40.0 us. // The expected edge is at 50 us, but allow it some window // due to clock differences. del_us(35.0 - 2.5 - 10.125 - 2.5 + 1.0); // CRC calculation uses 10.125 us - see // below. // -2.5 = measured correction. uint8_t n_low_readings = 0; for(uint8_t i = 8; i>0; --i) // 5 clk per round (regardless of pin value.) { if(!pinstat) n_low_readings++; } // 40 clk = 5 us. // Num of zeroes: 0 1 2 3 4 5 6 7 // H I G H | ? ? | L O W if(n_low_readings < 3) { // High -- expect low. del_us(10-WINDOW_BEFORE); // time windows of +/-10 us = 20 us = 160 clock cycles starts here. // LOOP: SBIS 2 + SBIC 2 + SUBI 1 + BRCC 2 = 7 clk /round. time_tmp = ((WINDOW_BEFORE+WINDOW_AFTER)*8)/7; while(time_tmp--) { // Require two successive low readings. if((!pinstat) && (!pinstat)) goto OK2; } PULLUP_ON(); return 0x40+i; OK2: __asm__ __volatile__ ("nop"); } else if(n_low_readings > 4) // low -- expect high { del_us(10-WINDOW_BEFORE); // time windows of +/-10 us = 20 us = 160 clock cycles starts here. // LOOP: SBIS 2 + SBIC 2 + SUBI 1 + BRCC 2 = 7 clk /round. time_tmp = ((WINDOW_BEFORE+WINDOW_AFTER)*8)/7; while(time_tmp--) { // Require two successive high readings. if(pinstat && pinstat) goto OK3; } PULLUP_ON(); return 0x60+i; OK3: (*data).d |= 1; // 1 clk = 0.125 us } else { PULLUP_ON(); return 0x20+i; } // Here, we are aligned perfectly again. // At the same time, calculate CRC8. Calculate every time 8 bits have been received, // but of course skip the last octet which is the CRC. // Consume a constant amount of time here, which can be then subtracted from // the delay at the beginning of the loop. if(i==7 || i==15 || i==23) // 6 cycles used when not true, 3...7 if true. { // We have our latest full byte in data.d remainder ^= (*data).d; // 3 cycles CALC_CRC(remainder); // Total 3+48+24 = 75 cycles = 9.375 us. } else { _delay_us(9.375); } // In total, 10.125 us was spent for the if + CRC. } PULLUP_ON(); if(remainder != (*data).d) return CRC_ERROR; return COMM_SUCCESS; }