/* the radian_trx SW shall not be distributed nor used for commercial product*/ /* it is exposed just to demonstrate CC1101 capability to reader water meter indexes */ /* there is no Warranty on radian_trx SW */ void show_in_hex(uint8_t* buffer, size_t len) { int i=0; for (i=0 ; i>= 1 ) { (mask & *ptr) > 0 ? printf("1") : printf("0"); } printf(" "); } printf("\n"); } void echo_debug(T_BOOL l_flag,char *fmt, ...) { if (l_flag) { va_list args; va_start (args, fmt); vprintf (fmt, args); fflush(stdout); } } void print_time(void) {/* time_t mytime; mytime = time(NULL); printf(ctime(&mytime));*/ time_t rawtime; struct tm * timeinfo; char buffer [80]; time (&rawtime); timeinfo = localtime (&rawtime); strftime (buffer,80,"%d/%m/%Y %X",timeinfo); printf("%s",buffer); } /*----------------------------------------------------------------------------*/ #define CRC_START_KERMIT 0x0000 #define CRC_POLY_KERMIT 0x8408 static uint8_t crc_tab_init = 0; static uint16_t crc_tab[256]; /*----------------------------------------------------------------------------*/ /* https://www.libcrc.org/ * static void init_crc_tab( void ); * * For optimal performance, the CRC Kermit routine uses a lookup table with * values that can be used directly in the XOR arithmetic in the algorithm. * This lookup table is calculated by the init_crc_tab() routine, the first * time the CRC function is called. */ static void init_crc_tab( void ) { uint16_t i; uint16_t j; uint16_t crc; uint16_t c; for (i=0; i<256; i++) { crc = 0; c = i; for (j=0; j<8; j++) { if ( (crc ^ c) & 0x0001 ) crc = ( crc >> 1 ) ^ CRC_POLY_KERMIT; else crc = crc >> 1; c = c >> 1; } crc_tab[i] = crc; } crc_tab_init = 1; } /* init_crc_tab */ /* https://www.libcrc.org/ * uint16_t crc_kermit( const unsigned char *input_str, size_t num_bytes ); * * The function crc_kermit() calculates the 16 bits Kermit CRC in one pass for * a byte string of which the beginning has been passed to the function. The * number of bytes to check is also a parameter. */ uint16_t crc_kermit( const unsigned char *input_ptr, size_t num_bytes ) { uint16_t crc; uint16_t tmp; uint16_t short_c; uint16_t low_byte; uint16_t high_byte; const unsigned char *ptr; size_t a; if ( ! crc_tab_init ) init_crc_tab(); crc = CRC_START_KERMIT; ptr = input_ptr; for (a=0; a> 8) ^ crc_tab[ tmp & 0xff ]; ptr++; } low_byte = (crc & 0xff00) >> 8; high_byte = (crc & 0x00ff) << 8; crc = low_byte | high_byte; return crc; } /* crc_kermit */ /*----------------------------------------------------------------------------*/ /** * Reverses the bit order of the input data and adds a start bit before and a stop bit * after each byte. * * @param inputBuffer Points to the unencoded data. * @param inputBufferLen Number of bytes of unencoded data. * @param outputBuffer Points to the encoded data. * @param outputBufferLen Number of bytes of encoded data. */ int encode2serial_1_3(uint8_t *inputBuffer, int inputBufferLen, uint8_t *outputBuffer) { // Adds a start and stop bit and reverses the bit order. // 76543210 76543210 76543210 76543210 // is encoded to: // #0123456 7###0123 4567###0 1234567# ##012345 6s7# (# -> Start/Stop bit) int bytepos; int bitpos; int i; int j = 0; for (i=0 ; i < (inputBufferLen * 8) ; i++) { //printf("\r\ni=%u",i); if (i % 8 == 0) { if (i > 0) { //printf(" j=%u stopBIT",j); // Insert stop bit (3) bytepos = j / 8; bitpos = j % 8; outputBuffer[bytepos] |= 1 << (7 - bitpos); j++; bytepos = j / 8; bitpos = j % 8; outputBuffer[bytepos] |= 1 << (7 - bitpos); j++; bytepos = j / 8; bitpos = j % 8; outputBuffer[bytepos] |= 1 << (7 - bitpos); j++; } //stop bit // Insert start bit (0) bytepos = j / 8; bitpos = j % 8; //printf(" j=%u startBIT",j); outputBuffer[bytepos] &= ~(1 << (7 - bitpos)); j++; }// start stop bit bytepos = i / 8; bitpos = i % 8; uint8_t mask = 1 << bitpos; if ((inputBuffer[bytepos] & mask) > 0) { bytepos = j / 8; bitpos = 7 - (j % 8); outputBuffer[bytepos] |= 1 << bitpos; } else { bytepos = j / 8; bitpos = 7 - (j % 8); outputBuffer[bytepos] &= ~(1 << bitpos); } j++; }//for //insert additional stop bit until end of byte while (j%8 > 0) { bytepos = j / 8; bitpos = 7 - (j % 8); outputBuffer[bytepos] |= 1 << bitpos; j++; } outputBuffer[bytepos+1] = 0xFF; return bytepos+2; } int Make_Radian_Master_req(uint8_t *outputBuffer,uint8_t year,uint32_t serial) { uint16_t crc; uint8_t to_encode[] ={0x13,0x10,0x00,0x45,0xFF,0xFF,0xFF,0xFF,0x00,0x45,0x20,0x0A,0x50,0x14,0x00,0x0A,0x40,0xFF,0xFF}; //les 2 derniers octet sont en reserve pour le CKS ainsi que le serial number uint8_t synch_pattern[] ={0x50,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF}; uint8_t TS_len_u8; to_encode[4] = year; to_encode[5] = (uint8_t)((serial&0x00FF0000)>>16); to_encode[6] = (uint8_t)((serial&0x0000FF00)>>8); to_encode[7] = (uint8_t) (serial&0x000000FF); crc = crc_kermit(to_encode,sizeof(to_encode)-2); //printf("crc:%x\r\n",crc); to_encode[sizeof(to_encode)-2]=(uint8_t)((crc&0xFF00)>>8); to_encode[sizeof(to_encode)-1]=(uint8_t)(crc&0x00FF); //show_in_hex_one_line(to_encode,sizeof(to_encode)); memcpy(outputBuffer,synch_pattern,sizeof(synch_pattern)); TS_len_u8=encode2serial_1_3(to_encode,sizeof(to_encode),&outputBuffer[sizeof(synch_pattern)]); return TS_len_u8+sizeof(synch_pattern); }