diff --git a/drone/drone.c b/drone/drone.c new file mode 100644 index 0000000..7affa25 --- /dev/null +++ b/drone/drone.c @@ -0,0 +1,140 @@ +// +// Simple FSQ beacon for Arduino, with the Etherkit Si5351A Breakout +// Board, by Jason Milldrum NT7S. +// +// Original code based on Feld Hell beacon for Arduino by Mark +// Vandewettering K6HX, adapted for the Si5351A by Robert +// Liesenfeld AK6L . Timer setup +// code by Thomas Knutsen LA3PNA. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject +// to the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TONE_SPACING 8789 // ~8.7890625 Hz +#define BAUD_2 7812 // CTC value for 2 baud +#define BAUD_3 5208 // CTC value for 3 baud +#define BAUD_4_5 3472 // CTC value for 4.5 baud +#define BAUD_6 2604 // CTC value for 6 baud + +#define LED_PIN 13 + +#define bool char +#define false 0 +#define true 1 + +// Global variables + +unsigned long freq = 0;//7105350; // Base freq is 1350 Hz higher than dial freq in USB +uint8_t cur_tone = 0; +static uint8_t crc8_table[256]; +char callsign[10] = "F5OEO"; +char tx_buffer[40]; +uint8_t callsign_crc; +int FileText; +int FileFreqTiming; +// Global variables used in ISRs +volatile bool proceed = false; + + +void WriteTone(double Frequency,uint32_t Timing) +{ + typedef struct { + double Frequency; + uint32_t WaitForThisSample; + } samplerf_t; + samplerf_t RfSample; + + RfSample.Frequency=Frequency; + RfSample.WaitForThisSample=Timing; //en 100 de nanosecond + //printf("Freq =%f Timing=%d\n",RfSample.Frequency,RfSample.WaitForThisSample); + if (write(FileFreqTiming, &RfSample,sizeof(samplerf_t)) != sizeof(samplerf_t)) { + fprintf(stderr, "Unable to write sample\n"); + } + +} + + + +int main(int argc, char **argv) +{ + char *sText; + if (argc > 2) + { + sText=(char *)argv[1]; + //FileText = open(argv[1], O_RDONLY); + + char *sFileFreqTiming=(char *)argv[2]; + FileFreqTiming = open(argv[2], O_WRONLY|O_CREAT); + } + else + { + printf("usage : pidrone StringToTransmit file.ft\n"); + exit(0); + } + + //100KHZ + int Freq_span = 100000; + int NbStep = 2000; + int i; + for(i=1;i0) + { + WriteTone(25000,1250e3); + printf("1"); + } + else + { + WriteTone(-25000,1250e3); + printf("0"); + } + + } + WriteTone(25000,1250e3);//Stop bit + printf("\n"); + } + + WriteTone(00000,250e6); + close(FileFreqTiming); +} + diff --git a/opera/decode b/opera/decode new file mode 100755 index 0000000..43a173b Binary files /dev/null and b/opera/decode differ diff --git a/opera/decode_opera.cpp b/opera/decode_opera.cpp new file mode 100644 index 0000000..9520026 --- /dev/null +++ b/opera/decode_opera.cpp @@ -0,0 +1,761 @@ +// OPERA_Decode_Test.cpp : Defines the entry point for the console application. +// +// Purpose : to study coding and decoding of OPERA which was developed by EA5HVK. +// +// Usage : "OPERA_Decode_Test [? | d | s | w] +// where : s= help, d = debug, s = AA1AA and w = 7L1RLL +// +// Version : 1.0.3, 11/27/2015 change print_char() to print_str() +// Version : 1.0.2, 11/27/2015 bug fix at unpack(), and add 7L1RLL as a 2nd sample. +// Version : 1.0.1, 11/27/2015 Add a function of print_char() +// Version : 1.0.0, 11/25/2015 Initial Release, but under construction on error correction. +// +// Copyright : 7L1RLL(Rick Wakatori) 2015 under Terms of The GNU General +// Public License. +// +// Environments : Microsoft Visual C++ 2010 Express under Windows 10. +// Compiler version : 10.0.40219.1 SPIRel +// +// Acknowledgements : +// a)EA5HVK(Jose) for work on OPERA +// b)F4GCB(Patrick) for PIC program on CRC16 which is a copy into this program. +// c)PE1NNZ(Guido), for Article titled Opera Protocol Specification. + +//#include "stdafx.h" +#include "stdio.h" +#include "math.h" +#include "string.h" + +short int call_AA1AA[239] = +{ // callsign = "AA1AA" + 1,0,1,1, 0,1,0,0, 1,0,1,1, 0,0,1,0, // 0xB4, 0xB2 + 1,1,0,0, 1,1,0,1, 0,0,1,1, 0,0,1,0, // 0xCD, 0x32 + 1,0,1,0, 1,1,0,0, 1,0,1,1, 0,0,1,1, // 0xAC, 0xB3 + 0,1,0,0, 1,0,1,0, 1,1,0,0, 1,1,0,0, // 0x4A, 0xCC + 1,1,0,0, 1,1,0,1, 0,0,1,1, 0,0,1,0, // 0xCD, 0x32 + 1,0,1,0, 1,0,1,1, 0,0,1,1, 0,1,0,1, // 0xA9, 0x35 + 0,1,0,0, 1,1,0,0, 1,1,0,1, 0,1,0,0, // 0x4C, 0xD4 + 1,0,1,1, 0,1,0,0, 1,0,1,0, 1,1,0,1, // 0xB4, 0xAD + 0,0,1,1, 0,1,0,0, 1,1,0,1, 0,1,0,0, // 0x34, 0xD4 + 1,1,0,0, 1,0,1,0, 1,0,1,1, 0,0,1,1, // 0xCA, 0xB3 + 0,0,1,0, 1,0,1,0, 1,1,0,1, 0,1,0,0, // 0x2A, 0xD4 + 1,0,1,0, 1,1,0,1, 0,1,0,1, 0,1,0,1, // 0xAD, 0x55 + 0,1,0,0, 1,0,1,0, 1,1,0,1, 0,0,1,1, // 0x4A, 0xD3 + 0,0,1,1, 0,1,0,1, 0,0,1,0, 1,1,0,0, // 0x35, 0x2C + 1,1,0,1, 0,1,0,0, 1,1,0,0, 1,0,1 // 0xD4, 0xCA +}; + +short int call_F5OEO[239] = {1,0,1,1, 0,1,0,1, 0,0,1,0, 1,1,0,1, 0,1,0,1, 0,1,0,1, 0,1,0,0, 1,1,0,1, 0,1,0,0, 1,1,0,0, +1,1,0,0, 1,1,0,0, 1,0,1,0, 1,1,0,1, 0,1,0,1, 0,0,1,0, 1,0,1,0, 1,1,0,1, 0,0,1,1, 0,1,0,0, +1,0,1,0, 1,0,1,1, 0,1,0,1, 0,1,0,1, 0,0,1,0, 1,0,1,0, 1,1,0,1, 0,0,1,1, 0,0,1,1, 0,0,1,0, +1,1,0,0, 1,1,0,1, 0,0,1,0, 1,1,0,1, 0,1,0,1, 0,1,0,0, 1,0,1,1, 0,1,0,0, 1,0,1,1, 0,0,1,1, +0,1,0,1, 0,0,1,1, 0,1,0,1 ,0,1,0,0, 1,0,1,0, 1,0,1,0, 1,1,0,1, 0,1,0,0, 1,1,0,1, 0,1,0,1, +0,0,1,0, 1,0,1,1, 0,0,1,0, 1,1,0,1 ,0,0,1,1, 0,1,0,1, 0,0,1,1, 0,1,0,0, 1,1,0,0, 1,0,1 +}; + + + +short int call_7L1RLL[239] = +{ + 1,0,1,0, 1,1,0,1, 0,0,1,0, 1,1,0,1, // 0xAD, 0x2D + 0,0,1,0, 1,0,1,0, 1,1,0,0, 1,0,1,0, // 0x2A, 0xCA + 1,0,1,0, 1,0,1,0, 1,0,1,1, 0,1,0,0, // 0xAA, 0xB4 + 1,0,1,1, 0,0,1,0, 1,0,1,0, 1,0,1,1, // 0xB2, 0xAB + 0,0,1,1, 0,1,0,1, 0,0,1,0, 1,0,1,0, // 0x35, 0x2A + 1,0,1,0, 1,0,1,1, 0,1,0,1, 0,0,1,1, // 0xAB, 0x53 + 0,0,1,1, 0,0,1,0, 1,1,0,0, 1,1,0,0, // 0x32, 0xCC + 1,1,0,1, 0,0,1,0, 1,0,1,0, 1,0,1,1, // 0xD2, 0xAB + 0,0,1,1, 0,0,1,0, 1,1,0,0, 1,0,1,1, // 0x32, 0xCB + 0,1,0,0, 1,1,0,0, 1,1,0,1, 0,1,0,1, // 0x4C, 0xD5 + 0,1,0,1, 0,0,1,1, 0,1,0,1, 0,0,1,1, // 0x53, 0x53 + 0,0,1,0, 1,1,0,0, 1,1,0,0, 1,1,0,1, // 0x2C, 0xCD + 0,1,0,0, 1,1,0,1, 0,1,0,0, 1,0,1,1, // 0x4D, 0x4B + 0,1,0,0, 1,1,0,0, 1,0,1,1, 0,1,0,0, // 0x4C, 0xB4 + 1,0,1,0, 1,0,1,0, 1,0,1,0, 1,1,0 // 0xAA, 0xAC +}; + +short int interleave_target[119] = +{ //after interleave + 1,0,0,1, 1,0,1,1, 0,1,0,0, 1,0,1,1, //0x9B, 0x4B + 1,1,0,1, 1,0,1,0, 0,1,1,1, 0,1,0,1, //0xDA, 0x75 + 0,1,0,0, 1,0,1,1, 1,1,1,0, 1,0,0,0, //0x4B, 0xE8 + 0,1,0,1, 0,0,0,1, 1,0,0,1, 1,1,0,0, //0x51, 0x9C + 1,0,0,1, 0,0,0,1, 0,1,1,1, 1,0,1,0, //0x91, 0x7A + 1,1,1,1, 0,0,0,1, 1,1,0,0, 0,0,0,0, //0xF1, 0xC0 + 0,1,1,1, 0,0,1,0, 1,0,0,0, 1,1,0,1, //0x72, 0x8D + 0,0,0,1, 0,1,1 //0x16 +}; + +short int before_interleave_target[119] = +{ // before interleave + 1,1,0,1, 0,0,1,0, 0,0,0,0, 0,0,0,1, // 0xD2, 0x01 + 1,0,0,1, 1,1,1,0, 0,1,1,0, 1,0,1,1, // 0x9E, 0x6B + 0,1,0,0, 1,1,1,1, 0,0,1,0, 1,0,1,0, // 0x4F, 0x2A + 1,1,0,1, 0,1,0,1, 0,1,1,1, 1,0,0,1, // 0xD5, 0x79 + 1,0,1,0, 0,1,0,1, 1,1,1,0, 0,0,0,0, // 0xA5, 0xE0 + 0,0,0,0, 1,1,0,0, 1,1,0,0, 0,0,1,1, // 0x0C, 0xC3 + 1,1,1,1, 0,0,1,1, 0,1,0,1, 0,1,0,1, // 0xF3, 0x55 + 1,1,0,1, 0,0,1 // 0xD2 +}; + +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} +}; + +short int pseudo_sequence[51] = +{ + 1,1,1,0, 0,0,0,1, 0,1,0,1, 0,1,1,1, // 0xE1, 0x57 + 1,1,1,0, 0,1,1,0, 1,1,0,1, 0,0,0,0, // 0xE6, 0xD0 + 0,0,0,1, 1,0,0,1, 0,0,0,1, 0,1,0,1, // 0x19, 0x15 + 0,1,1 // 0x60 +}; + +char before_scramble_target[52] = + "000000000110110001101111000011110001111000001100100"; + +short int before_WH_target[52] = +{ + 1,1,1,0, 0,0,0,1, 0,0,1,1, 1,0,1,1, // 0xE1, 0x3B + 1,0,0,0, 1,0,0,1, 1,1,0,1, 1,1,1,1, // 0x89, 0xDF + 0,0,0,0, 0,1,1,1, 0,0,0,1, 1,0,0,1, // 0x07, 0x19 + 1,1,1 // 0xE0 +}; + +char packed_target[29] ="0000011011000110111100001111"; //0x0606F0F + +char call_target[7] = "AA1AA "; + +// **** Grobal variables **** +short int symbol[239]; // to be decode +short int interleaved[119]; +short int before_interleave[119]; +short int error_position[239]; // does not use in V1.0.0 +short int before_WH[51]; +char before_scramble[51]; +char packed[28]; +char call[7]; +short int DEBUG = 0; + +// **** functions **** +void decode_opera(short int symbol[239]); +void manchester_decode(short int symbol[239], short int interleaved[119]); +void de_interleave(short int interleaved[119], short int before_interleave[119]); +void de_walsh_matrix(short int before_interleave[119], short int before_WH[51]); +void de_scramble(short int befor_WH[51], char before_scramble[51]); +void de_crc(char before_scramble[51], char packed[28]); +void generate_crc(char datas[28], char crc[17], int length); +void unpack(char packed[28], char call[7]); +char de_normalizer(int bc, int byte_num); +void print_help(); +void print_short_int(const char* caption, short int* code, int length); +void print_str(const char* caption, char* code); +void strcpy_w(char * s1, char * s2, int length); +void strcat_w(char * s1, char * s2, int lenS1, int lenS2); + +//********************************** +int main(int argc, char* argv[]) +//********************************** +{ + char s1 = 0x00; + int i; + + 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 == '?') && (argv[1][1] == 0x00)) + { + printf("%s\n", "Help selected"); + print_help(); + return 0; + } + else if ((s1 == 'd' || s1 == 's' || s1 == 'w') && (argv[1][1] == 0x00)) + { + if (s1 =='d') + { + printf("%s\n", "Debug selected."); + DEBUG = 1; + for (i = 0; i < 239; i++) + symbol[i] = call_AA1AA[i]; + decode_opera(symbol); + DEBUG = 0; + return 0; + } + else if (s1 == 's') + { + printf("%s\n", "Sample selected."); + for (i = 0; i < 239; i++) + symbol[i] = call_F5OEO[i]; + decode_opera(symbol); + DEBUG = 0; + return 0; + } + else + { + printf("%s\n", "Sample 7L1RLL selected."); + DEBUG = 0; + for (i = 0; i < 239; i++) + symbol[i] = call_7L1RLL[i]; + decode_opera(symbol); + DEBUG = 0; + return 0; + } + } + } + default : // 3 arguments + { + printf("%s\n", "Too many arguments."); + print_help(); + return 0; + } + } +} // end of _tmain() + +//************************************************** +void decode_opera(short int * symbol) +//************************************************** +{ + print_short_int("symbol given =", symbol, 239); + manchester_decode(symbol, interleaved); + print_short_int("de_manchester code =", interleaved, 119); + if (DEBUG) + print_short_int("de_manchester_target =", interleave_target, 119); + de_interleave(interleaved, before_interleave); + print_short_int("de_interleave =", before_interleave, 119); + if (DEBUG) + print_short_int("de_interleave_target =", before_interleave_target, 119); + de_walsh_matrix(before_interleave, before_WH); + print_short_int("de_Walsh-Hamadard =", before_WH, 51); + if (DEBUG) + print_short_int("de_WH_target =", before_WH_target, 51); + de_scramble(before_WH, before_scramble); + print_str("de_scramble = ", before_scramble); + if (DEBUG) + print_str("de_scramble_target = ", before_scramble_target); + de_crc(before_scramble, packed); + print_str("de_CRC = ", packed); + if (DEBUG) + print_str("de_CRC_target = ", packed_target); + unpack(packed, call); + printf("unpached call = %s\n", call); + if (DEBUG) + printf("call_target = %s\n", call_target); +} // end of decode_opera() + +//*********************************************************************** +void manchester_decode(short int* symbol, short int* symbol_interleaving) +//*********************************************************************** +{ + int i = 0; + int idx = 0; // delete start 2 bit + + while (idx < 238) + { + if ((symbol[idx + 1] == 1) && (symbol[idx + 2] == 0)) + { + symbol_interleaving[i] = (short) 0; + } + else if ((symbol[idx + 1] == 0) && (symbol[idx + 2] == 1)) + { + symbol_interleaving[i] = (short) 1; + } + else + { + error_position[idx] = (short) 1; + } + i++; idx += 2; + } +} // end of manchester_decode() + +//************************************************************************ +void de_interleave(short int* interleaved, short int* before_interleave) +//************************************************************************ +{ + int i =0, idx = 0, j = 0; + + for (i = 0; i < 7; i++) + { + for (j = i; j < 119; j += 7) + { + before_interleave[j] = interleaved[idx]; + idx++; + } + } +} // end of de_interleave + +//********************************************************************* +void de_walsh_matrix(short int* vector_to_tx, short int* symbol_coding) +//********************************************************************* +{ // 119 bit to 51 bit + int idx = 0, i, j, k, data = 0; + short int temp[7]; + + for (i = 0; i < 119; i += 7) + { + for(j = 0; j < 7; j++) temp[j] = vector_to_tx[i + j]; + temp[7]=0x00; + + // search the value for match + data = 0; + for (k = 0; k < 7; k++) + { + if (k < 6) + { + data = data + (int) pow((double)(temp[k]*2), (6 - k)); + } + else if (k == 6) + { + if (temp[6] == 1) data = data + 1; + } + } + if (data == 0) // 0000000 = 0 + { + symbol_coding[idx + 0] = 0; + symbol_coding[idx + 1] = 0; + symbol_coding[idx + 2] = 0; + } + else if (data == 85) // 1010101 = 2^6 + 2^4 + 2^2 + 1 = 85 + { + symbol_coding[idx + 0] = 0; + symbol_coding[idx + 1] = 0; + symbol_coding[idx + 2] = 1; + } + else if (data == 51) // 0110011 = 2^5 + 2^4 + 2 + 1 = 51 + { + symbol_coding[idx + 0] = 0; + symbol_coding[idx + 1] = 1; + symbol_coding[idx + 2] = 0; + } + else if (data == 102) // 1100110 = 2^6 + 2^5 + 2^2 + 2 = 102 + { + symbol_coding[idx + 0] = 0; + symbol_coding[idx + 1] = 1; + symbol_coding[idx + 2] = 1; + } + else if (data == 15) // 0001111 = 2^3 + 2^2 + 2 + 1 = 15 + { + symbol_coding[idx + 0] = 1; + symbol_coding[idx + 1] = 0; + symbol_coding[idx + 2] = 0; + } + else if (data == 90) // 1011010 = 2^6 + 2^4 + 2^3 + 2 = 90 + { + symbol_coding[idx + 0] = 1; + symbol_coding[idx + 1] = 0; + symbol_coding[idx + 2] = 1; + } + else if (data == 60) //0111100 = 2^5 + 2^4 + 2^3 + 2^2 = 60 + { + symbol_coding[idx + 0] = 1; + symbol_coding[idx + 1] = 1; + symbol_coding[idx + 2] = 0; + } + else if (data == 105) // 1101001 = 2^6 + 2^5 + 2^3 + 1 = 105 + { + symbol_coding[idx + 0] = 1; + symbol_coding[idx + 1] = 1; + symbol_coding[idx + 2] = 1; + } + else printf("xxxx"); + + idx +=3; + + } +} // enf of de-WH + +//************************************************************ +void de_scramble(short int * vector_to_tx, char * vector) +//************************************************************ +{ // | 51 bit | to | 51 bit | + short int vector_temp[51]; + int i; + + // convert binary to ASCII + for (i = 0; i < 51; i++) + { + vector_temp[i] = vector_to_tx[i] ^ pseudo_sequence[i]; + vector[i] = (char) vector_temp[i] + 0x30; + } +} //end of de_scramble() + +//************************************************* +void de_crc(char * vector, char * packed) +//************************************************* +{ // 51 bits to 28bits + + char crc1[17], crc1a[17], crc2[4], crc2a[4]; + int i, crc_ok; + char temp[52] = {0}; + + // extract packed from received data + for (i = 0; i < 28; i++) //4..31 for packed + packed[i] = temp[i] = vector[i + 4]; + packed[28] = temp[28] = 0x00; + + if (DEBUG) + print_str("temp in de_crc = ", temp); + if (DEBUG) + print_str("packed in de_crc = ", packed); + + // extract crc1 from received data + for (i = 0; i < 16; i++) //32..47 for crc1 + crc1[i] = vector[i + 32]; + crc1[16] = 0x00; + + if (DEBUG) + print_str("crc1 exracted from received data = ", crc1); + + //crc2 extracted from received data + for (i = 0; i < 3; i++) //48..50 for crc2 + crc2[i] = vector[i + 48]; + crc2[3] = 0x00; + + if (DEBUG) + print_str("crc2 extracted from received data = ", crc2); + + generate_crc(temp, crc1a, 16); + if (DEBUG) + print_str("temp before crc add = ", temp); + if (DEBUG) + print_str("crc1a calcurated = ", crc1a); + strcat_w(temp, crc1a, 28, 16); // 28 + 16 = 44 + + generate_crc(temp, crc2a, 3); + strcat_w(temp, crc2a, 44, 3); // 44 + 3 = 47 + + // verify crc1 and crc2 + crc_ok = 1; + for (i = 0; i < 16; i++) + if (crc1[i] != crc1a[i]) crc_ok = 0; + for (i = 0; i < 3; i++) + if (crc2[i] != crc2a[i]) crc_ok = 0; + if (crc_ok) + printf("CRC : OK\n"); + else + { + printf("CRC : No good\n"); + print_str("crc1a calcurated = ", crc1a); + print_str("crc1_received = ", crc1); + print_str("crc2a calcurated = ", crc2a); + print_str("crc2a_received = ", crc2); + } + +} //end of de_crc() + +//************************************************************************ +void generate_crc(char * datas, char * crc, int length) +//************************************************************************ +{ // 32 + 16(length) = 48 or 48 + 3(length) = 51 + // CRC16-IBM : Polynominal = X16+X15+X2+1 = 1000 0000 0000 0101 + // This function is a copy of JUMA TX136/500 control program + // whitch was written by F4GCB (Patrick). Thanks Patrick. + + int i, j, k, len; + char buffer[52]; + short int wcrc[17] = {0}, byte1 = 0, byte2 = 0; + + len = strlen(datas); + for (i = 0; i < len; i++) + buffer[i] = datas[i]; + buffer[len] = 0x00; + if (DEBUG) + print_str("input datas in generate_crc =", buffer); + + for (i = 0; i < len; i++) + { + for (j = 0; j < 8; j++) + { + if (j > 0) buffer[i] = buffer[i] >> 1; + byte1 = buffer[i] & 0x01; + byte2 = byte1 ^ wcrc[0]; // XOR with X16 + wcrc[0] = byte2 ^ wcrc[1]; // XOR with X15 + for (k = 1; k < 13; k++) + wcrc[k] = wcrc[k + 1]; + wcrc[13] = byte2 ^ wcrc[14]; // XOR with X2 + wcrc[14] = wcrc[15]; // + wcrc[15] = byte2; // + } + } + + // if msb byte crc = 0 then value at 27 + byte2 = 0; + for (i = 0; i < 8; i++) + byte2 = byte2 + (int)(wcrc[i] * pow (2.0, i)); + if (byte2 == 0) byte2 = 27; // 0x1B = 0b0001 1011 + + // if lsb byte crc = 0 then value at 43 + byte1 = 0; + for (i = 8; i < 16; i++) + byte1 = byte1 + (int)(wcrc[i] * pow(2.0, i - 8)); + if (byte1 == 0) byte1 = 43; // 0x2B = 0b0010 1011 + + if (DEBUG) + printf("byte1 before replace =%2x, byte2 =%2x\n", byte1, byte2); + + // merge crc into a bit string + for (i = 0; i < 8; i++) + { + if (i > 0) byte2 = byte2 >> 1; + wcrc[7 - i] = byte2 & 0x01; // (binary) + if (i > 0) byte1 = byte1 >> 1; + wcrc[15 - i] = byte1 & 0x01; // (binary) + } + if (length > 16) length = 16; + for (i = 16 - length; i < 16; i++) + crc[i - (16 - length)] = wcrc[i] + 0x30; + crc[length]= 0x00; + if (DEBUG) + print_str("crc =", crc); +} // end of generate_crc() + +//************************************* +void unpack(char * packed, char * call) +//************************************* +{ // 28 bits to 48 bits + int i; + int temp; + unsigned long code_sum = 0, remains = 0; + + if (DEBUG) + print_str("packed in unpack = ", packed); + + // separate a string to coded callsign + + for (i = 0; i < 28; i++) + code_sum = code_sum + (unsigned long)(packed[27 - i] - '0') * pow(2.0, i); + + // de_normalizer of callsign + remains = 36*10*27*27*27; + if (DEBUG) + { + printf(" 0 : code_sum = %9Lu\n", code_sum); + printf(" 0 : remains = %9Lu\n", remains); + } + + if (code_sum > remains) + { + temp = code_sum / remains; + code_sum %= remains; + } + else temp = 0; + if (DEBUG) + printf(" 0 : temp = %9Lu\n", temp); + call[0] = de_normalizer(temp, 0); + + remains = 10*27*27*27; + if (DEBUG) + { + printf(" 1 : code_sum = %9Lu\n", code_sum); + printf(" 1 : remains = %9Lu\n", remains); + } + if (code_sum >= remains) + { + temp = code_sum / remains; + code_sum %= remains; + } + else temp = 0; + if (DEBUG) + printf(" 1 : temp = %9Lu\n", temp); + call[1] = de_normalizer(temp, 1); + + remains = 27*27*27; + if (DEBUG) + { + printf(" 2 : code_sum = %9Lu\n", code_sum); + printf(" 2 : remains = %9Lu\n", remains); + } + if (code_sum >= remains) + { + temp = code_sum / remains; + code_sum %= remains; + } + else temp = 0; + if (DEBUG) + printf(" 2 : temp = %9Lu\n", temp); + call[2] = de_normalizer(temp, 2); + + remains = 27*27; + if (DEBUG) + { + printf(" 3 : code_sum = %9Lu\n", code_sum); + printf(" 3 : remains = %9Lu\n", remains); + } + if (code_sum >= remains) + { + temp = code_sum / remains; + code_sum %= remains; + } + else temp = 0; + if (DEBUG) + printf(" 3 : temp = %9Lu\n", temp); + call[3] = de_normalizer(temp, 3); + + remains = 27; + if (DEBUG) + { + printf(" 4 : code_sum = %9Lu\n", code_sum); + printf(" 4 : remains = %9Lu\n", remains); + } + if (code_sum >= remains) + { + temp = code_sum / remains; + code_sum %= remains; + } + else temp = 0; + if (DEBUG) + printf(" 4 : temp = %9Lu\n", temp); + call[4] = de_normalizer(temp, 4); + + remains = 1; + if (DEBUG) + { + printf(" 5 : code_sum = %9Lu\n", code_sum); + printf(" 5 : remains = %9Lu\n", remains); + } + if (code_sum >= remains) + { + temp = code_sum; + //code_sum %= remains; + } + else temp = 0; + if (DEBUG) + printf(" 5 : temp = %9Lu\n", temp); + call[5] = de_normalizer(temp, 5); + + call[6] = 0x00; +} // end of unpack + +//******************************** +char de_normalizer(int bc, int n) +//******************************** +{ + char cc = 0; + + if (DEBUG) + printf(" %u : input of de_normalizer, bc = %9Lu\n", n, bc); + switch (n) + { + case 0 : + { + if (bc == 0) cc = ' '; + else if (bc >= 1 && bc <= 26) cc = bc - 1 +'A'; + else if (bc >= 27 && bc <= 37) cc = bc - 27 + '0'; + break; + } + case 1 : + { + if (bc >= 0 && bc <= 25) cc = bc + 'A'; + else if (bc >= 26 && bc <= 36) cc = bc - 26 + '0'; + break; + } + case 2 : + { + if (bc >= 0 && bc <= 9) cc = bc + '0'; + break; + } + case 3: case 4: case 5: + { + if (bc == 0) cc = ' '; + else if (bc >= 1 && bc <= 26) cc = bc - 1 + 'A'; + break; + } + default : break; + } + if (DEBUG) + printf(" %u : output of de_normalizer, cc = %c\n", n, cc); + return (cc); +} // end of de _normlizer + +//******************************************************************** +void print_short_int(const char *caption, short int *code, int length) +//******************************************************************** +{ // This is a service function for debugging + int i = 0; + + printf("%s\n", caption); + for (i = 0; i < length; i++) + { + printf("%u", code[i]); + if (((i + 1) % 4) == 0) printf(" "); + if (((i + 1) % 40) == 0) printf("\n"); + } + printf("\n"); +} // end fo print_short_int + +//******************************************************************** +void print_short_char(const char * caption, char * code, int length) +//******************************************************************** +{ // This is a service function for debugging + int i = 0; + + printf("%s\n", caption); + for (i = 0; i < length; i++) + { + printf("%c", code[i]); + if (((i + 1) % 4) == 0) printf(" "); + if (((i + 1) % 40) == 0) printf("\n"); + } + printf("\n"); +} // end fo print_short_char + +//******************************************************************** +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_char +//******************************************************* +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() + +//*************** +void print_help() +//*************** +{ + printf("%s\n","Usage : OPERA_Decode_Test [ ? | d | s | w]"); + printf("%s\n"," Help : OPERA_Decode_Test ?"); + printf("%s\n"," Debug : OPERA_Decode_Test d"); + printf("%s\n"," AA1AA : OPERA_Decode_Test s"); + printf("%s\n"," 7L1RLL : OPERA_Decode_Test w"); + printf("%s\n"," Sample callsign is \"AA1AA\". "); +} // end of help + +//************** End of Program ************************************** diff --git a/opera/opera b/opera/opera new file mode 100755 index 0000000..4f2c04c Binary files /dev/null and b/opera/opera differ diff --git a/opera/opera.c b/opera/opera.c new file mode 100644 index 0000000..3338c9c --- /dev/null +++ b/opera/opera.c @@ -0,0 +1,80 @@ +#include +#include +#include + +char* itoa(unsigned long val, int n, char* buf, int radix) +{ + char c[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + int i = 0; + while (n-i) { + unsigned long d = (unsigned long)pow(radix, n-i-1); + buf[i++] = c[val/d]; + val = val%d; + } + buf[i] = '\0'; + return buf; +} + +int crc16op(char* msg, int n) +{ + int i,j,crc=0; // crc-16 (0x8005 poly, flip in and out, 2 zero bytes in tail) of msg[0..n-1] + for(i=0;i!=n+2;i++){ + + for(j=0;j!=8;j++) + crc = crc&1 ? (crc>>1) ^ 0xa001 : crc>>1; + } + // replace, swap and store crc in msg[32..48] + crc = crc&0xff00 ? ( crc&0x00ff ? crc : 0x001b|(crc&0xff00) ) : 0x2b00|(crc&0x00ff); + crc = ((crc&0x00ff)<<8); // amp="amp" crc="crc" xff00="xff00">>8); + return crc; +} + +int main(int argc, const char* argv[]){ + if(argc != 2){ + printf("usage: opera [callsign]\n"); + return 0; + } + const char* call = argv[1]; + char msg[239]; + int i,j; + + char c[]=" "; //align last prefix digit at c[2] and fill gaps with blanks + int aligned = isdigit(call[2]); + strncpy(aligned ? c : &c[1], call, aligned ? 6 : 5); + //strupr(c); To implement : for now warning, should be in CAPITAL + + unsigned long n1=(c[0]>='0'&&c[0]<='9'?c[0]-'0'+27:c[0]==' '?0:c[0]-'A'+1); // packing call e.g. " K1JT ", "AA1AA " into n1 + n1=36*n1+(c[1]>='0'&&c[1]<='9'?c[1]-'0'+26:c[1]-'A'); + n1=10*n1+c[2]-'0'; + n1=27*n1+(c[3]==' '?0:c[3]-'A'+1); + n1=27*n1+(c[4]==' '?0:c[4]-'A'+1); + n1=27*n1+(c[5]==' '?0:c[5]-'A'+1); + itoa(n1, 28, &msg[4], 2); //msg[4..32] = binary representation n1 in ASCII + itoa(crc16op(&msg[4], 28), 16, &msg[32], 2); //store bin-crc of msg[4..31] in msg[32..47] + itoa(crc16op(&msg[4], 28+16) & 0x07, 3, &msg[48], 2); //store bin-crc of msg[4..47] in msg[48..51] + msg[0]=msg[1]=msg[2]=msg[3]='0'; //unused bits msg[0-3] + + const char* prn_vec = "111000010101011111100110110100000001100100010101011"; + for(i=0; i!=51; i++) //scramble + msg[i] = ((msg[i]-'0') ^ (prn_vec[i]-'0')) +'0'; + + const char* wh[] = {"0000000", "1010101", "0110011", "1100110", "0001111", "1011010", "0111100", "1101001"}; + for(i=(51/3)-1; i>=0; i--){ // Walsh-Hadamard encoding to msg[0..118] + char b = (msg[i*3+0]-'0')*4+(msg[i*3+1]-'0')*2+(msg[i*3+2]-'0')*1; + for(j=0; j!=7;j++) + msg[i*7+j] = wh[b][j]; + } + + for(i=0; i!=7; i++) // interleave 7x17 to msg[121..240] + for(j=0; j!=17; j++) + msg[121+j+17*i] = msg[i+7*j]; + + for(i=0; i!=119; i++){ // Manchester encoding to msg[2..120] + msg[2*i+1+2] = msg[121+i]; + msg[2*i+0+2] = (msg[2*i+1+2] == '0') + '0'; + } + msg[0] = msg[1] ='1'; // head + msg[239] = '\0'; // tail + + printf("message=%s symbols=%s\n", c, msg); +} diff --git a/opera/opera.rfa b/opera/opera.rfa new file mode 100644 index 0000000..65b4da6 Binary files /dev/null and b/opera/opera.rfa differ diff --git a/opera/opera2 b/opera/opera2 new file mode 100755 index 0000000..93eee74 Binary files /dev/null and b/opera/opera2 differ diff --git a/opera/opera2.c b/opera/opera2.c new file mode 100644 index 0000000..aa2dfdb --- /dev/null +++ b/opera/opera2.c @@ -0,0 +1,531 @@ +//****************************************************************************** +// 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 "stdio.h" +#include "string.h" +#include +#include + #include + #include +#include "stdint.h" +#include "math.h" + +//#define __VCpp__ TRUE + +// Grobal Variables + +int FileFreqTiming; +// Test program using SNDFILE +// see http://www.mega-nerd.com/libsndfile/api.html for API + +void WriteTone(double Frequency,uint32_t Timing) +{ + typedef struct { + double Frequency; + uint32_t WaitForThisSample; + } samplerf_t; + samplerf_t RfSample; + + RfSample.Frequency=Frequency; + RfSample.WaitForThisSample=Timing; //en 100 de nanosecond + //printf("Freq =%f Timing=%d\n",RfSample.Frequency,RfSample.WaitForThisSample); + if (write(FileFreqTiming,&RfSample,sizeof(samplerf_t)) != sizeof(samplerf_t)) { + fprintf(stderr, "Unable to write sample\n"); + } + +} + +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); +void encodepitx(short int *code, int length,float Nop); + +#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] = ""; + + + switch (argc) + { + case 1 : // Help required + case 2 : // Help required + { + printf("Usage : %s CALLSIGN file.rfa \n", argv[0]); + //print_help(); + return 0; + } + case 3: // 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; + } + + FileFreqTiming = open( argv[2], O_WRONLY|O_CREAT, 0644); + genn_opera(); + return 0; + } + } + + 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); + encodepitx(symbol,239,1); + +} // 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 encodepitx(short int *code, int length,float Nop) +{ + int i = 0; + int j=0; + /*and each of the +239 symbols are transmitted by keying the transmitter as CW on and off with a symbol +rate of 0.256*n s/symbol, where n is the integer of operation mode OPn that corresponds +with the Opera frequency recommendation: */ + //WriteTone(1*32767,1e6*(256*Nop)); + WriteTone(1*32767,1e6*(256*Nop)); + for (i = 0; i < length-1; i++) + { + //for(j=0;j<1000;j++) + WriteTone(code[i]*32767,1e6*(256*Nop)); + } +} + + +//******************************************************************** +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 ******************************** diff --git a/opera/operadjl.rfa b/opera/operadjl.rfa new file mode 100644 index 0000000..ca3eb3f Binary files /dev/null and b/opera/operadjl.rfa differ diff --git a/opera/piopera.c b/opera/piopera.c new file mode 100644 index 0000000..1573985 --- /dev/null +++ b/opera/piopera.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define ln(x) (log(x)/log(2.718281828459045235f)) +#define BUFFER_LEN 1024*8 + +int FileFreqTiming; +// Test program using SNDFILE +// see http://www.mega-nerd.com/libsndfile/api.html for API + +void WriteTone(double Frequency,uint32_t Timing) +{ + typedef struct { + double Frequency; + uint32_t WaitForThisSample; + } samplerf_t; + samplerf_t RfSample; + + RfSample.Frequency=Frequency; + RfSample.WaitForThisSample=Timing; //en 100 de nanosecond + //printf("Freq =%f Timing=%d\n",RfSample.Frequency,RfSample.WaitForThisSample); + if (write(FileFreqTiming,&RfSample,sizeof(samplerf_t)) != sizeof(samplerf_t)) { + fprintf(stderr, "Unable to write sample\n"); + } + +} + +int main(int argc, char **argv) { + float data [2*BUFFER_LEN] ; + float data_filtered[2*BUFFER_LEN] ; // we generate complex I/Q samples + SNDFILE *infile, *outfile ; + SF_INFO sfinfo ; + + int readcount, nb_samples ; + char *infilename ; + char *outfilename ; + int k ; + float x ; + + if( argc < 2 ) { + printf("Usage : %s in.wav [out.wav]\n", argv[0]); + return(1); + } + infilename = argv[1]; + if( argc == 3 ) { + outfilename = argv[2]; + } else { + outfilename = (char *)malloc( 128 ); + sprintf( outfilename, "%s", "out.ft"); + } + if (! (infile = sf_open (infilename, SFM_READ, &sfinfo))) + { /* Open failed so print an error message. */ + printf ("Not able to open input file %s.\n", infilename); + /* Print the error message from libsndfile. */ + puts (sf_strerror (NULL)); + return 1; + } + + if( sfinfo.samplerate != 48000 ) { + printf("Input rate must be 48K.\n"); + return 1; + } + + FileFreqTiming = open(outfilename, O_WRONLY|O_CREAT, 0644); + + /** **/ + printf ("Reading file : %s\n", infilename ); + printf ("Sample Rate : %d\n", sfinfo.samplerate); + printf ("Channels : %d\n", sfinfo.channels); + printf ("----------------------------------------\n"); + printf ("Writing file : %s\n", outfilename ); + + /* While there are.frames in the input file, read them, process + ** them and write them to the output file. + */ + + while ((readcount = sf_readf_float(infile, data, BUFFER_LEN))) + { + nb_samples = readcount / sfinfo.channels; + for( k=0 ; k < nb_samples ; k++ ) { + x = data[k*sfinfo.channels]; + if( sfinfo.channels == 2 ) { + // stereo file, avg left + right + x += data[k*sfinfo.channels+1]; + x /= 2; + } + //printf("%f \n",x); + float FactAmplitude=2.0; // To be analyzed more deeply ! + /* + double A = 87.7f; // compression parameter + double ampf=x/32767.0; + ampf = (fabs(ampf) < 1.0f/A) ? A*fabs(ampf)/(1.0f+ln(A)) : (1.0f+ln(A*fabs(ampf)))/(1.0f+ln(A)); //compand + x= (int)(round(ampf * 32767.0f)); + */ + WriteTone(x*32767*FactAmplitude,1e9/48000.0); + + } + + } + + /* Close input and output files. */ + sf_close (infile) ; + close(FileFreqTiming); + + return 0; +} diff --git a/src/RpiTx.c b/src/RpiTx.c index 1dc0227..43c1dfe 100644 --- a/src/RpiTx.c +++ b/src/RpiTx.c @@ -89,6 +89,10 @@ int FREQ_MINI_TIMING=157; int PWMF_MARGIN = 1120; //A Margin for now at 1us with PCM ->OK int globalppmpll=0; + +int CalibrationTab[PWM_STEP_MAXI]; +uint32_t *Shuffle[PWM_STEP_MAXI]; + typedef unsigned char uchar; // 8 bit typedef unsigned short uint16; // 16 bit typedef unsigned int uint; // 32 bits @@ -108,6 +112,7 @@ int Randomize=0; uint32_t GlobalTabPwmFrequency[50]; + //End F5OEO char EndOfApp=0; @@ -441,7 +446,7 @@ inline void FrequencyAmplitudeToRegister(double TuneFrequency,uint32_t Amplitude static uint32_t CompteurDebug=0; #define DEBUG_RATE 20000 - int PwmNumberStep; + int PwmNumberStep=0; CompteurDebug++; static uint32_t TabPwmAmplitude[18]={0x00000000, 0x80000000,0xA0000000,0xA8000000,0xAA000000, @@ -472,9 +477,19 @@ inline void FrequencyAmplitudeToRegister(double TuneFrequency,uint32_t Amplitude if(SampleRate!=0) WaitNanoSecond = (1e9/SampleRate); } - - PwmNumberStep=WaitNanoSecond/FREQ_MINI_TIMING; - if(PwmNumberStep>PWM_STEP_MAXI) PwmNumberStep=PWM_STEP_MAXI; + + int i; + for(i=1;i=WaitNanoSecond) + { + + break; + } + } + PwmNumberStep=i; + //PwmNumberStep=WaitNanoSecond/FREQ_MINI_TIMING; + //if(PwmNumberStep>PWM_STEP_MAXI) PwmNumberStep=PWM_STEP_MAXI; // ********************************** PWM FREQUENCY PROCESSING ***************************** @@ -517,22 +532,22 @@ inline void FrequencyAmplitudeToRegister(double TuneFrequency,uint32_t Amplitude //if((CompteurDebug%200)==0) printf("PwmNumberStep =%d TuneFrequency %f : FreqTuning %f FreqStep %f PwmFreqStep %f fPWMFrequency %f PWMFrequency %d f1 %f f2 %f %x %x\n",PwmNumberStep,TuneFrequency,FreqTuning,FreqStep,FreqStep/PwmNumberStep,fPWMFrequency,PWMFrequency,f1,f2,RegisterF1,RegisterF2); - int i; + static int NbF1,NbF2,NbF1F2; NbF1=0; NbF2=0; NbF1F2=0; - + int BeginShuffle=rand()%PwmNumberStep; int AdaptPWMFrequency; - if((PwmNumberStep-PWMFrequency-(PWMF_MARGIN+FREQ_DELAY_TIME)/FREQ_MINI_TIMING)>PwmNumberStep/2) + if((PwmNumberStep-PWMFrequency)/*-(PWMF_MARGIN+FREQ_DELAY_TIME)/FREQ_MINI_TIMING)*/>PwmNumberStep/2) { RegisterF1=0x5A000000 | (FreqDividerf1<<12) | (FreqFractionnalf1); RegisterF2=0x5A000000 | (FreqDividerf2<<12) | (FreqFractionnalf2); AdaptPWMFrequency=PWMFrequency; NbF1=0; - NbF2=(PWMF_MARGIN+FREQ_DELAY_TIME)/FREQ_MINI_TIMING; + NbF2=0;//PWMFrequency;//(PWMF_MARGIN+FREQ_DELAY_TIME)/FREQ_MINI_TIMING; } else // SWAP F1 AND F2 @@ -542,7 +557,7 @@ inline void FrequencyAmplitudeToRegister(double TuneFrequency,uint32_t Amplitude RegisterF1=0x5A000000 | (FreqDividerf2<<12) | (FreqFractionnalf2); AdaptPWMFrequency=PwmNumberStep-PWMFrequency; NbF1=0; - NbF2=(PWMF_MARGIN+FREQ_DELAY_TIME)/FREQ_MINI_TIMING; + NbF2=0;//PWMFrequency;//(PWMF_MARGIN+FREQ_DELAY_TIME)/FREQ_MINI_TIMING; } i=0; @@ -561,13 +576,15 @@ inline void FrequencyAmplitudeToRegister(double TuneFrequency,uint32_t Amplitude { if(NbF1sample[NoSample].FrequencyTab[i++]=RegisterF1; + ctl->sample[NoSample].FrequencyTab[Shuffle[PwmNumberStep][(i+BeginShuffle)%PwmNumberStep]/*rand()%(PwmNumberStep)*/]=RegisterF1; + i++; NbF1++; NbF1F2++; } if(NbF2sample[NoSample].FrequencyTab[i++]=RegisterF2; + ctl->sample[NoSample].FrequencyTab[Shuffle[PwmNumberStep][(i+BeginShuffle)%PwmNumberStep]/*rand()%(PwmNumberStep)*/]=RegisterF2; + i++; NbF2++; NbF1F2++; } @@ -644,7 +661,7 @@ int GetDMADelay(int Step) dma_cb_t *cbp = ctl->cb; cur_cb = (uint32_t)virtbase; // DMA AT 1st CBS dma_reg[DMA_CONBLK_AD+DMA_CHANNEL*0x40]=mem_virt_to_phys((void*)cur_cb); - usleep(100); + //usleep(100); int samplecnt; for (samplecnt = 0; samplecnt < NUM_SAMPLES ; samplecnt++) { @@ -655,10 +672,10 @@ int GetDMADelay(int Step) } dma_reg[DMA_CS+DMA_CHANNEL*0x40] = DMA_CS_PRIORITY(7) | DMA_CS_PANIC_PRIORITY(7) | DMA_CS_DISDEBUG |DMA_CS_ACTIVE; // START DMA : go, mid priority, wait for outstanding writes :7 Seems Max Priority - usleep(5000); //Wait to be sure DMA is running stable + //usleep(500); //Wait to be sure DMA is running stable int i; int SumDelay=0; - for(i=0;i<10;i++) + for(i=0;i<4;i++) { @@ -690,7 +707,7 @@ int GetDMADelay(int Step) time_difference = gettime_now.tv_nsec - start_time; if(time_difference<0) time_difference+=1E9; - //printf("Delay = %d\n",time_difference/free_slots); + //printf("Delay = %d (time_diff %ld freesolt %d \n",time_difference/free_slots,time_difference,free_slots); SumDelay+=time_difference/free_slots; } @@ -702,7 +719,7 @@ int GetDMADelay(int Step) dma_reg[DMA_CS+DMA_CHANNEL*0x40] |= DMA_CS_RESET; //BCM2708_DMA_ABORT|BCM2708_DMA_RESET; udelay(100); - return SumDelay/10; + return SumDelay/4; } int CalibrateSystem(int *ppm,int *BaseDelayDMA,int *StepDelayDMA) @@ -715,33 +732,71 @@ int CalibrateSystem(int *ppm,int *BaseDelayDMA,int *StepDelayDMA) ntx.modes = 0; /* only read */ status = ntp_adjtime(&ntx); double clockppm; - + int hFileCsv; + hFileCsv=open("calib.csv",O_CREAT | O_WRONLY); + if (status != TIME_OK) { printf("Error: NTP\n"); - return 0; + //return 0; } clockppm = (double)ntx.freq/(double)(1 << 16); if(abs(clockppm)<200) *ppm=clockppm; //printf("Clock PPM = %f\n",ppm); int i; - int BaseDelay=0; - BaseDelay=GetDMADelay(0); + int BaseDelay=1; + /*BaseDelay=GetDMADelay(0); *BaseDelayDMA=BaseDelay; - *StepDelayDMA=(GetDMADelay(PWM_STEP_MAXI/2)-(*BaseDelayDMA))/(PWM_STEP_MAXI/2); - //for(i=1;i<200;i+=10) - //printf("Step %d =%d\n",i,(GetDMADelay(i)-BaseDelay)/i); + *StepDelayDMA=(GetDMADelay(PWM_STEP_MAXI/2)-(*BaseDelayDMA))/(PWM_STEP_MAXI/2);*/ + char csvline[255]; + for(i=0;i<200;i+=1) + { + int Delay=GetDMADelay(i); + printf("Step %d :%d \n",i,Delay);//,(GetDMADelay(i)-BaseDelay)/i); + sprintf(csvline,"%d:%d\n",i,Delay); + CalibrationTab[i]=Delay; + write(hFileCsv,csvline,strlen(csvline)); + + } return 1; } +void InitShuffle() +{ + int i,j; + for(i=1;iOK @@ -1270,7 +1325,8 @@ int pitx_run( { // SHOULD NOT EXEED 200 STEP*500ns; SAMPLERATE SHOULD BE MAX TO HAVE PRECISION FOR PCM // BUT FIFO OF PCM IS 16 : SAMPLERATE MAYBE NOT EXCESS 16*80000 ! CAREFULL BUGS HERE - #define MAX_DELAY_WAIT (PWM_STEP_MAXI/2*FREQ_MINI_TIMING-PWMF_MARGIN) + //#define MAX_DELAY_WAIT (PWM_STEP_MAXI/2*FREQ_MINI_TIMING-PWMF_MARGIN) + int MAX_DELAY_WAIT = CalibrationTab[199]; static int CompteSample=0; static uint32_t TimeRemaining=0; static samplerf_t SampleRf; @@ -1341,15 +1397,26 @@ int pitx_run( int i; //printf("Begin free %d\n",free_slots); + static int Up=1; for(i=0;i