//****************************************************************************** // OPERA_Coding_Test.cpp : Defines the entry point for the console application. // // Purpose : Algorithm testing by a laptop computer before implementation // into PIC micro processor. // // Usage: "OPERA_Coding_Test [? | d | s] ["callsign"]"; // where : s = help, d = debug and s = sample"; // // Version 1.0.4, 2015/11/29: Modified print format // Version 1.0.3, 2015/11/13: Delete an additional start bit for decoder // Version 1.0.2, 2015/11/11: Add Visual C++ directives // Version 1.0.1, 2015/11/10: Changed help message // Version 1.0.0, 2015/11/07: Initial Release // // Copyright(C) 2015 F4GCB // Partial copyright (C)2015 7L1RLL // // Environment : Microsoft Visual C++ 2010 Express under Windows 10. // Compiler version 10.0.40219.1 SP1Rel // // Acknowledgement : // 1)Portion of this OPERA is derived from the work of EA5HVK. // 2)All functions of this program are a copy of JUMA-TX500/136 // Transmitter Controller which written by F4GCB. //****************************************************************************** #include "stdafx.h" #include #include #include "string.h" #include "math.h" #define __VCpp__ TRUE // Grobal Variables static const short int pseudo_sequence[51] = { 1,1,1,0,0,0,0,1,0,1, 0,1,0,1,1,1,1,1,1,0, 0,1,1,0,1,1,0,1,0,0, 0,0,0,0,0,1,1,0,0,1, 0,0,0,1,0,1,0,1,0,1, 1 }; static short int walsh_matrix[8][7] = { {0,0,0,0,0,0,0},{1,0,1,0,1,0,1},{0,1,1,0,0,1,1},{1,1,0,0,1,1,0}, {0,0,0,1,1,1,1},{1,0,1,1,0,1,0},{0,1,1,1,1,0,0},{1,1,0,1,0,0,1} }; static short int symbol[239]; char call[7], call_coded[45], vector[52]; short int vector_to_tx[51]; short int symbol_interleaving[119], symbol_coding[119]; short int DEBUG = 0; const char sampleCall[7] = "AA1AA"; // Declaration of functions void genn_opera(void); void generate_call(char call[7], char call_coded[45]); void add_crc16(char call_coded[45], char vector[52]); void scramble(char vector[52], short int symbol_coding[119]); void Walsh_Hammered_code(short int symbol_coding[119], short int vector_to_tx[51]); void interleave(short int vector_to_tx[51], short int symbol_interleaving[119]); void ManchesterEncode(short int symbol_interleaving[119], short int symbol[239]); char chr_norm_opera(char bc); void print_help(void); void print_short_int(const char caption[], short int code[239], int length); void print_str(const char caption[250], char code[52]); void strcpy_w(char s1[52], char s2[52], int length); void strcat_w(char s1[52], char s2[52], int lenS1, int lenS2); #ifdef __VCpp__ //********************************** // main forVisual C++ int _tmain(int argc, _TCHAR* argv[]) //********************************** { _tsetlocale(LC_ALL, _T("")); //Change Unicode to OS-Default locale #else int main(int argc, char* argv[]) //********************************** { #endif int i = 0; char s1 = 0x00, s2[7] = ""; // CMD argument test printf("argc=%d\n", argc); switch (argc) { case 1 : // Help required { printf("%s\n", "More argument is required!"); print_help(); return 0; } case 2: // 2 arguments { s1 = (char)argv[1][0]; if ((s1 == 's') && (argv[1][1] == 0x00)) // sample callsign { printf("%s\n","A sample callsign is used."); DEBUG = 0; i = 0; while (sampleCall[i] != 0 && i < 7) { call[i] = sampleCall[i]; call[++i] = 0x00; } genn_opera(); return 0; } else if ((s1 =='?') && (argv[1][1] == 0x00)) { printf("%s\n","Help requested"); print_help(); return 0; } else { // range check if (!((argv[1][0] >= '0' && argv[1][0] <= '9') || (argv[1][0] >= 'A' && argv[1][0] <= 'Z') || (argv[1][0] >= 'a' && argv[1][0] <= 'z'))) { printf("%s\n","Callsign must be began with an alphan/numeric character"); print_help(); return 0; } DEBUG = 0; i = 0; while (argv[1][i] != 0 && i < 7) { call[i] = argv[1][i]; call[++i] = 0x00; } genn_opera(); return 0; } } case 3 : // 3 arguments { s1 = (char)argv[1][0]; // 'd' switch (s1) { case 'd': // debug mode requested { printf("%s\n","Debug Mode"); // range check if (!((argv[2][0] >= '0' && argv[2][0] <= '9') || (argv[2][0] >= 'A' && argv[2][0] <= 'Z') || (argv[2][0] > 'a' && argv[2][0] <= 'z'))) { printf("%s\n","Callsign must be began with an alphan/numeric character."); print_help(); return 0; } DEBUG = 1; i = 0; while (argv[2][i] != 0 && i < 7) { call[i] = argv[2][i]; call[++i] = 0x00; } genn_opera(); return 0; } default : { printf("%s\n", "3 arguments, but not debug."); print_help(); return 0; } } // end of switch s1 } // end of case 3 default: { printf("%s\n", "Too many arguments."); print_help(); break; } } // end of switch argc return 0; } // end of _tmain //******************* void genn_opera(void) //******************* { printf("\nCallsign = %s\n", call); generate_call(call, call_coded); if (DEBUG) print_str("call_coded =", call_coded); add_crc16(call_coded, vector); if (DEBUG) print_str("crc16 vector =", vector); scramble(vector, vector_to_tx); if (DEBUG) print_short_int("vector_to_tx =", vector_to_tx, 44); Walsh_Hammered_code(vector_to_tx, symbol_coding); if (DEBUG) print_short_int("symbol_coding =", symbol_coding, 119); interleave(symbol_coding, symbol_interleaving); if (DEBUG) print_short_int("symbol_interleaving =", symbol_interleaving, 119); ManchesterEncode(symbol_interleaving, symbol); print_short_int("symbol =", symbol, 239); } // genn_opera //**************************************************** // Normalize characters space S..Z 0..9 in order 0..36 char chr_norm_opera(char bc) //**************************************************** { char cc = 0; if (bc >= '0' && bc <= '9') cc = bc - '0' + 27; if (bc >= 'A' && bc <= 'Z') cc = bc - 'A' + 1; if (bc >= 'a' && bc <= 'z') cc = bc - 'a' + 1; if (bc == ' ') cc = 0; return (cc); } // enf of chr_norm_opera //********************************************** void generate_call(char *call, char *call_coded) //********************************************** { int i; unsigned long code_sum; //the thired character must always be a number if (chr_norm_opera(call[2]) < 27) { for (i=5; i> 0; i--) call[i] = call[i-1]; call[0]=' '; } // the call must always have 6 characters for (i=strlen(call); i < 6; i++) call[i] = ' '; call[6] = 0x00; if (DEBUG) printf("NormalizedCall=%s\n", call); code_sum = chr_norm_opera(call[0]); code_sum = code_sum * 36 + chr_norm_opera(call[1]) - 1; code_sum = code_sum * 10 + chr_norm_opera(call[2]) - 27; code_sum = code_sum * 27 + chr_norm_opera(call[3]); code_sum = code_sum * 27 + chr_norm_opera(call[4]); code_sum = code_sum * 27 + chr_norm_opera(call[5]); if (DEBUG) printf("code_sum=%Lu\n", code_sum); // merge coded callsign ino a string call_coded[28] = 0x00; call_coded[27] = (short int) ((code_sum & 0x01) + 0x30); for (i = 26; i >= 0; i--) { code_sum = code_sum >> 1; call_coded[i] = (short int)((code_sum & 0x01) + 0x30); } } // end of pack_callsign //*************************************************** void generate_crc(char *datas, char *crc, int length) //*************************************************** { unsigned int i, j, k; char buffer[52]; //strlen(datas)]; short int wcrc[16] = {0}, byte1 = 0, byte2 = 0; #ifdef __VCpp__ strcpy_s(buffer, 52, datas);// strcpy(buffer, datas); #else strcpy(buffer, datas);// strcpy(buffer, datas); #endif if (DEBUG) print_str("buffer_crc = ", buffer); for (i = 0; i < strlen(datas); i++) { for (j = 0; j < 8; j++) { if (j > 0) buffer[i] = buffer[i] >> 1; byte1 = buffer[i] & 0x01; byte2 = byte1 ^ wcrc[0]; wcrc[0] = byte2 ^ wcrc[1]; for (k = 1; k < 13; k++) wcrc[k] = wcrc[k+1]; wcrc[13] = byte2 ^ wcrc[14]; wcrc[14] = wcrc[15]; wcrc[15] = byte2; } } // if msb byte crc = 0 then value at 27 byte2 = 0; for (i = 0; i < 8; i++) #ifdef __VCpp__ // add for Visual C++ by 7L1RLL 11/07/2015 byte2 = byte2 + (short) wcrc[i] * pow((double)2.0, (int)i); #else byte2 = byte2 + wcrc[i] * pow(2, i); #endif if (byte2 == 0) byte2 =27; // if lsb byte crc = 0 then value at 43 byte1 = 0; for (i = 8; i < 16; i++) #ifdef __VCpp__ byte1 = byte1 + (short) (wcrc[i] * (double)pow(2.0, (int)i - 8)); // add cast by 7L1RLL #else byte1 = byte1 + (wcrc[i] * pow(2, i - 8)); #endif if (byte1 == 0) byte1 = 43; if (DEBUG) printf("byte1 = %x, byte2 = %x\n", byte1, byte2); // merge crc into a string for (i = 0; i < 8; i++) { if (i > 0) byte2 = byte2 >> 1; wcrc[7 - i] = byte2 & 0x01; if ( i > 0) byte1 = byte1 >> 1; wcrc[15 - i] = byte1 & 0x01; } if (length > 16) length = 16; for (i = 16 - length; i < 16; i++) crc[i - (16 - length)] = wcrc[i] + 0x30; crc[length] = 0x00; } // end of genarate_crc //********************************************* void add_crc16(char * call_coded, char *vector) //********************************************* { // input: |28 bits|, output : |51 bits| char crc1[17] = "", crc2[4] = ""; #ifdef __VCpp__ // for wide character compiler char temp[52] = ""; _tsetlocale(LC_ALL, _T("")); //Change Unicode to OS-Default locale if (DEBUG) print_str("call_coded in add CRC16 =", call_coded); strcpy_w(temp, call_coded, 28); // 28 bit if (DEBUG) print_str("temp in add CRC16=", temp); generate_crc(call_coded, crc1, 16); if (DEBUG) print_str("crc1 =", crc1); strcat_w(temp, crc1, 28, 16); // 28 + 16 = 44 generate_crc( temp, crc2, 3); if (DEBUG) print_str("crc2 =", crc2); #else // PIC C compiler using ASCII char crc1[17] = "", crc2[4] = ""; generate_crc(call_coded, crc1, 16); if (DEBUG) printf("crc1 =%s\n", crc1); generate_crc(strcat(call_coded, crc1), crc2, 3); if (DEBUG) printf("crc2 =%s\n", crc2); #endif // |4 bits sync| + |28 bits call| + |19 bit crc| #ifdef __VCpp__ strcpy_w(vector, "0000", 4); // 4 strcat_w(vector, temp, 4, 44); // 4 + 44 = 48 strcat_w(vector, crc2, 48, 3); // 48 + 3 = 51 #else // not VC++ ex : PIC strcpy(vector, "0000"); // 4 strcat(vector, call_coded); // 4 + 44 = 48 strcat(vector, crc2); // 48 + 3 = 51 #endif } // end of add_crc16 //************************************************** void scramble(char *vector, short int *vector_to_tx) //************************************************** { // encoding |51 bits| int i=0; for (i = 0; i < 51; i++) { vector_to_tx[i] = vector[i] & 0x01; // convert ASCII to binary vector_to_tx[i] = vector_to_tx[i] ^ pseudo_sequence[i]; } } // end of scrambling //************************************************************************* void Walsh_Hammered_code(short int *vector_to_tx, short int *symbol_coding) //************************************************************************* { // order 8 walsh matrix codification : |119 bits| int data = 0, idx = 0, i = 0, j = 0; for (i = 0; i < 51; i += 3) { data = 0; for (j = 0; j < 3; j++) data = data + (vector_to_tx[i + j] << (2 - j)); for (j = 0; j < 7; j++) { symbol_coding[idx] = walsh_matrix[data][j]; idx++; } } } //end of Walsh_Hammered_code //*********************************************************************** void interleave(short int *symbol_coding, short int *symbol_interleaving) //*********************************************************************** { // interleaving : |119 bits| int idx = 0, i = 0, j = 0; idx = 0; for (i = 0; i < 7; i++) { for (j = i; j < 119; j += 7) { symbol_interleaving[idx]= symbol_coding[j]; idx++; } } } // end of interleave //********************************************************************** void ManchesterEncode(short int *symbol_interleaving, short int *symbol) //********************************************************************** { // manchester codification : |11| + |238 bits| - |1 bit| modified by 7L1RLL 11/07/2015 int idx = 0; int i = 0, j = 0; symbol[0] = 1; for (i = 0; i < 119; i++) { if (symbol_interleaving[i] == 0) { symbol[idx + 1] = 1; symbol[idx + 2] = 0; } else { symbol[idx + 1] = 0; symbol[idx + 2] = 1; } idx += 2; } } // end of Manchester_encode //*************** void print_help() //*************** { printf("%s\n","Usage : OPERA_Coding_Test [? | s | [d \"callsign\"]]"); printf("%s\n"," Normal : OPERA_Coding_Test \"callsign\""); printf("%s\n"," Help : OPERA_Coding_Test ?"); printf("%s\n"," Sample : OPERA_Coding_Test s"); printf("%s\n"," Debug : OPERA_Coding_Test d \"callsign\""); printf("%s\n"," Callsign format shall be like \"AA1AAA\". "); printf("%s\n"," Third character mast be a numeric character(0..9)."); } // end of help //******************************************************************** void print_short_int(const char *caption, short int *code, int length) //******************************************************************** { // This is service function for debugging int i = 0; printf("%s\n", caption); for (i = 0; i < length; i++) { printf("%d", code[i]); if (((i+1) % 4) == 0) printf(" "); if (((i+1) % 40) == 0) printf("\n"); } printf("\n"); } // end fo print_short_int //******************************************************************** void print_str(const char * caption, char * code) //******************************************************************** { // This is a service function for debugging int i = 0; printf("%s\n", caption); for (i = 0; i < strlen(code); i++) { printf("%c", code[i]); if (((i + 1) % 4) == 0) printf(" "); if (((i + 1) % 40) == 0) printf("\n"); } printf("\n"); } // end fo print_str //******************************************************* void strcpy_w(char * s1, char * s2, int length) //******************************************************* { int i; for (i = 0; i < length; i++) s1[i] = s2[i]; s1[length] = 0x00; } // end of strcpy_w //**************************************************************** void strcat_w(char * s1, char * s2, int lenS1, int lenS2) //**************************************************************** { int i; for (i = 0; i < lenS2; i++) s1[i + lenS1] = s2[i]; s1[lenS1 + lenS2]= 0x00; } // end of strcat_w() //************** End of Program ********************************