#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include "rdf1.h"
#define TWO_TO_16 65536 // 2^16
typedef union {
struct { unsigned char one; unsigned char two; } __attribute__ ((packed)) byte ;
uint16_t uint16;
} twobytes_t;
// Таблица для быстрого разделения потоков
static twobytes_t stream_separate_table[TWO_TO_16];
/* Если рассматривать байты со смещением 2*i и 2*i+1 в rdf данных как 16-битовое
целое без знака j, то stream_separate_table[j].byte.one и
stream_separate_table[j].byte.two содержат, соответственно, байты со смещением i
из первого и второго потоков */
int // Инициализация обработки
rdf1_open(char* path, time_t* start_time,
char* channels /* 'I', 'Q', 'A' или 'R' */ ,
rdr_mode_t* rdr_mode){
// Инициализация чтения rdf-файла (с помощью mmap)
int fp, rval, j, length;
rdr_mode_t rdr_mode_v;
time_t start_time_v;
rdf1_header_t rdf_data;
struct tm time_date;
void *addr, *ptr_rdf;
rdf1_header_t rdf_header;
unsigned char *ptr_in, *ptr_out;
/*****************************************************************************/
fp = open(path, O_RDONLY); // Открытие файла данных (режим чтения)
length = TWO_TO_16*2 + sizeof(rdf_data); // Количество байт, отражаемых в память
// (сумма размера таблицы и размера заголовка)
addr = mmap(0, length, PROT_READ, MAP_SHARED, fp, 0); // Отражение файла в память
close(fp); // Закрытие файла
if(addr == MAP_FAILED) { // Проверка корректности отражения
printf("Ошибка использования mmap\n");
return (MMAP_ERR); // MMAP_ERR = -1
exit(1);
};
ptr_rdf = memcpy(&rdf_data, addr, sizeof(rdf_data)); // Копирование отраженной области,
//соответствующей заголовку исходного RDF-файла в переменную rdf_data
if (strcmp(rdf_data.file_type,"RDF1") != 0) { // Проверка идентификатора формата файла
return(RDF1_BAD_ID_STRUCT);
exit(1);
}
if (strcmp(rdf_data.mode,"DEC") == 0){ // Идентификация характеристики видеоконвертора
rdr_mode_v = rdr_mode_dec;
rdr_mode = &rdr_mode_v;
}
else
if (strcmp(rdf_data.mode,"DAS") == 0){
rdr_mode_v = rdr_mode_das;
rdr_mode = &rdr_mode_v;
}
else {
rdr_mode_v = rdr_mode_undef;
rdr_mode = &rdr_mode_v;
return(RDF1_BAD_RDR_MODE);
exit(1);
}
// Считывание информации из заголовка
strptime(rdf_data.utc,"%Y %j-%T",&time_date); // Преобразование времени из строки в
// структурный тип tm
start_time_v = mktime(&time_date); // Преобразование времени в POSIX-формат
start_time = &start_time_v;
channels = &rdf_data.channels; // Мода RDF-файла
/**********************************************************************************/
// Заполнение stream_separate_table (с помощью rdf1_separate_stream)
ptr_in = (unsigned char*)addr + sizeof(rdf_data); // Смещение указателя на начало
// блока радио-данных
for (j = 0; j <= TWO_TO_16; j++) {
rdf1_separate_streams(ptr_in, ptr_out); // Разделение потоков
stream_separate_table[j].byte.one = *ptr_out; // Заполнение ячеек таблицы
stream_separate_table[j].byte.two = *(ptr_out+1);
ptr_in = ptr_in + 2;
}
//Распечатка первых двух элементов таблицы (для отладки, потом будет удалено)
printf("Значения, содержащиеся в 1-м и 2-м байтах данных (в восьмеричном формате):\n");
printf("x1 = %o\n", stream_separate_table[0].byte.one);
printf("x2 = %o\n", stream_separate_table[0].byte.two);
return(RDF1_OK);
};
/***************************************************************************/
// ВСПОМОГАТЕЛЬНЫЕ ПОДПРОГРАММЫ
void // Разделение потоков данных
rdf1_separate_streams(unsigned char* rdf, unsigned char* streams){
unsigned char str_in_1, str_in_2; // Значения, содержащиеся в 1-м и 2-м байтах
// входного потока rdf-данных до разделения потоков
unsigned char str_out_1, str_out_2; // Значения, содержащиеся в 1-м и 2-м байтах
// после разделения потоков
unsigned char s1_0, s2_0, s1_1, s2_1, s1_2, s2_2, s1_3, s2_3; // Промежуточные переменные,
// соответствующие парам битов rdf-данных: s1_0 <--> S1L(0) и S1U(0) и т.д.
str_in_1 = *rdf;
str_in_2 = *(rdf+1);
// Выделение пар битов, соответствующих двум круговым поляризациям S1 и S2
// в моменты времени 0, 1, 2, 3:
s1_0 = str_in_1 & 3;
s2_0 = (str_in_1 >> 2) & 3;
s1_1 = (str_in_1 >> 4) & 3;
s2_1 = (str_in_1 >> 6) & 3;
s1_2 = str_in_2 & 3;
s2_2 = (str_in_2 >> 2) & 3;
s1_3 = (str_in_2 >> 4) & 3;
s2_3 = (str_in_2 >> 6) & 3;
// Разделение потоков ("сборка" новых чисел, соответствующим первому и второму потокам)
str_out_1 = (s1_0 << 6) | (s1_1 << 4) | (s1_2 << 2) | s1_3;
str_out_2 = (s2_0 << 6) | (s2_1 << 4) | (s2_2 << 2) | s2_3;
*streams = str_out_1;
*(streams + 1) = str_out_2;
return;
}