Классы амплитудных модуляторов



Министерство информационных технологий и связи РФ

 

Поволжская Государственная Академия Телекоммуникаций и Информатики

 

МЕТОДИЧЕСКИЕ УКАЗАНИЯ

 

к курсовой работе по дисциплине

«Программные технологии информационных сетей»

для студентов магистратуры специальности 090403

 

 

Одобрено Методическим Советом ПГУТИ

 

Автор-составитель:                     НАЗАРЕНКО П.А., к.т.н.

 

 

Редактор:                                        КОРАБЛИН М.А., д.т.н., профессор

 

Рецензент:                                       АЛЕКСЕЕВ А.П., к.т.н., доцент

 

Самара 2016


Содержание

 

Введение...................................................................................................................................... 3

Задание........................................................................................................................................ 3

Цели курсового проекта.......................................................................................................... 3

Рекомендации по выполнению курсового проекта......................................................... 4

Описание предметной области............................................................................................. 4

Виды модуляции сигнала....................................................................................................... 6

Разработка системы классов................................................................................................. 8

Класс сообщения...................................................................................................................... 8

Класс сигнала.......................................................................................................................... 10

Классы устройств................................................................................................................... 11

Классы модуляторов............................................................................................................. 12

Классы амплитудных модуляторов.................................................................................. 12

Класс программы................................................................................................................... 16

Классы шумов и каналов..................................................................................................... 18

Класс аддитивного шума..................................................................................................... 18

Класс сосредоточенной помехи......................................................................................... 19

Класс усилителя..................................................................................................................... 20

Класс канала........................................................................................................................... 20

Классы фильтров.................................................................................................................... 21

Класс фильтра FFT................................................................................................................. 21

Классы демодуляторов......................................................................................................... 22

Класс коммутатора................................................................................................................ 23

Классы передатчиков и приёмников................................................................................. 24

Класс звена списка................................................................................................................. 25

Иерархия классов................................................................................................................... 26

Модификация класса программы...................................................................................... 27

Требования к оформлению пояснительной записки..................................................... 31

Защита курсового проекта.................................................................................................. 31

Рекомендуемая литература................................................................................................. 32

 


Введение

 

Курсовая работа по дисциплине ”Программные технологии информационных сетей” предназначен для закрепления знаний по этой дисциплине, полученных на лекционных, лабораторных и практических занятиях. Работа направлена на создание реального программного продукта, требующего при своей разработке использования основных механизмов ООП.

Курсовая работа предназначен для выполнения студентами дневного и заочного отделений.

Отдельные этапы выполнения работы могут опережать изучение соответствующих тем на других видах занятий. В этом случае студентам рекомендуется пользоваться литературой, в том числе, если какие-либо вопросы не полностью отражены в настоящем методическом руководстве.

Курсовая работа ориентирована на использование языка Си++, в отдельных случаях допускается использование студентами других объектно-ориентированных языков (например, Object Pascal, Java, C#, Perl, Python), при условии, что исполнители проекта в достаточной степени знакомы с этими языками.

 

 

Задание

 

В курсовой работе требуется разработать объектную программу, реализующую модель цифровой или аналоговой системы связи и содержащую сообщения, сигналы, шумы, передатчики, приёмники, концентраторы, коммутаторы, маршрутизаторы, каналы связи, фильтры, усилители.

Программа должна позволять контролировать состояние сигнала в любом месте системы связи, т.е. иметь некоторый пользовательский интерфейс.

Все компоненты программы, включая интерфейс, должны быть объектами соответствующих классов. При разработке программы допускается использовать RAD- и CASE-средства, например Borland C++ Builder или IBM Rational Rose.

В программе постараться не использовать числовые константы, кроме как при инициализации глобальных переменных.

Использовать любой удобный способ (из 2-х) инициализации объектов классов, являющихся полями других классов (обычный объект или указатель).

Соответствующие базовые классы должны быть виртуальными.

Не использовать для типов данных char библиотечные функции работы со строками.

 

Цели курсовой работы

 

1. Цель разработки – создать с использованием технологии ООП программу, реализующую процессы в заданной предметной области, и удобную для пользователя.

2. Учебная цель – научиться использовать основные механизмы ООП, включая множественное наследование, полиморфизм, абстрактные классы и перегрузку операций.

При выполнении работы должно быть продемонстрировано умение использовать перегрузку операций, включая operator=, operator[], виртуальные функции, абстрактные классы, взаимодействие между объектами разных классов.

 

Рекомендации по выполнению курсового проекта

 

Разработку программы можно вести в соответствии со спиральной моделью жизненного цикла ПО []. В этом случае сначала создаётся прототип – программа, обладающая минимально необходимым набором функциональных качеств и пользовательским интерфейсом начального уровня. Набор функций расширяется на следующих этапах разработки, одновременно может усложняться интерфейс.

При использовании технологии ООП первыми следует разрабатывать базовые классы, как обладающие наиболее общими свойствами. Для нашего курсового проекта это означает, что разработку можно начать с класса сообщений, продолжив её классами сигналов, шумов и классом всей программы в целом.

Разработка крупных программных комплексов обычно начинается с предпроектных исследований предметной области [].

 

 

Описание предметной области

 

В аналоговых системах связи передача сообщений от источника до получателя происходит упрощённо следующим образом. Сообщением может служить звуковой сигнал, в том числе, речь или музыка, какое-либо изображение, набор символов и т.п. Сообщение перед собственно процессом передачи преобразуется в соответствующий ему электрический сигнал при помощи некоторого устройства. Например, звук преобразуется в аналоговый электрический сигнал при помощи микрофона и т.п. В цифровых системах связи сигнал дополнительно подвергается цифровому кодированию при передаче и декодированию при приёме, но в курсовом проекте эти операции рассматриваться не будут.

Электрический сигнал поступает на вход передатчика, основным компонентом которого в случае радиосвязи является модулятор, выполняющий модуляцию сигнала. В состав передатчика может входить усилитель, усиливающий сигнал перед поступлением его в канал связи. Модуляция сигнала представляет собой преобразование его частотных компонент и служит для превращения относительно широкополосного сигнала в узкополосный. Широкополосные сигналы, т.е. такие, ширина спектра которых сопоставима с полосой канала, подвергаются значительному затуханию при прохождении по каналу связи, а затухание узкополосных сигналов гораздо меньше. Дополнительным преимуществом от модуляции является возможность передать по одному и тому же каналу несколько (несколько тысяч и более) сигналов, разнесённых по частоте.

Модулированный и усиленный сигнал поступает в радио- или проводной канал связи. В любом случае может использоваться коммутатор. Например, для подключения к одному каналу нескольких передатчиков или для направления сигнала с одного передатчика на какой-либо выбранный канал из нескольких.

При передаче по каналу происходит ослабление (затухание) сигнала, а также сигнал подвергается воздействию различных помех. Одним из видов помех является присутствующий в канале шум, моделью которого обычно служит белый гауссовский шум (БГШ). Такой шум накладывается на сигнал (т.е. суммируется с ним), и поэтому называется аддитивным. Ещё один вид помехи – сосредоточенная по частоте помеха, например сигнал другого передатчика или какого-либо генератора. В курсовом проекте будем считать, что возможен случай отсутствия помех в канале. Такой канал назовём идеальным (но затухание сигнала при этом останется). Затухание и воздействие помех искажает сигнал и в приёмнике обычно требуется какая-либо коррекция искажений.

Модулированный высокочастотный сигнал из канала связи поступает на вход приёмника, обычно содержащего детектор и несколько фильтров и усилителей. Детектор выполняет операцию, обратную модуляции, т.е. восстанавливает из высокочастотного модулированного сигнала низкочастотный. Частот детектор называют демодулятором. Как входной, так и выходной сигнал детектора могут усиливаться (обычно так и бывает) и фильтроваться. Задача входного фильтра заключается в выделении (обычно с одновременным усилением) полезного сигнала и ослаблении побочных сигналов. В современных системах выходные фильтры обычно являются цифровыми и обеспечивают подавление аддитивных и импульсных шумов.

Упрощённая структурная схема системы связи показана на рисунке 1.

 

 

 

 


1 – источник сообщения      2 – передатчик 3 – модулятор 4 – усилитель

5 – коммутатор                       6 – канал связи 7 – шум            8 – приёмник

9 – входной фильтр               10 – детектор 11 – фильтр  12 – усилитель

13 – получатель сообщения

 

Рисунок 1. Структурная схема системы связи

 

В системах радиосвязи сигнал может подвергаться специфическому виду искажений, источником которых является отражение радиосигнала от зданий и элементов рельефа местности. В результате в приёмник поступает не один, а несколько сигналов с некоторой задержкой во времени относительно друг друга. Получающийся в результате сигнал оказывается искажённым из-за взаимного наложения нескольких, задержанных во времени сигналов. Такой вид искажений называется многолучевым приёмом и встречается, в том числе, в современных беспроводных сетях компьютерной связи (WiFi). Один из способов борьбы с многолучевым приёмом – использование нескольких приёмников, расположенных на некотором расстоянии друг от друга и суммирование сигналов от каждого приёмника.

 

 

Виды модуляции сигнала

Модуляция сигнала заключается в изменении какого-либо параметра высокочастотного сигнала (амплитуды, частоты, фазы, ширины импульса и т.п.) в соответствии с изменением активного параметра (например, амплитуды) модулирующего низкочастотного сигнала. В аналоговых системах связи в качестве высокочастотного модулируемого сигнала используется синусоидальное колебание напряжения или тока в цепях модулятора. Такой сигнал получил название несущего колебания или просто несущей (переносящего информацию).

Если в процессе модуляции изменяется амплитуда несущей по закону изменения амплитуды входного модулирующего сигнала, то такая модуляция называется амплитудной. Упрощённо амплитудную модуляцию можно представить как перемножение низкочастотного сигнала и несущей, хотя на самом деле математическое выражение, описывающее этот процесс, несколько сложнее и учитывает параметр глубины модуляции, которого мы касаться не будем.

Сигналы в системах связи часто представляют в виде их спектров, т.е. наборов частотных составляющих. Простейший спектр имеет неискажённое синусоидальное колебание – просто вертикальная линия, расположенная на оси частот на частоте этого колебания. Высота линии соответствует амплитуде колебания. Именно такой спектр имеет немодулированная несущая. На рисунке 2 показан спектр синусоидального колебания, полученный при помощи программы Mathcad 7.0. В этой программа синусоидальное колебание и его спектр формируются дискретными методами, поэтому спектр лишь приближённо соответствует простой вертикальной линии, но больше походит на спектр реального колебания, наблюдаемый, например, при помощи измерителя амплитудно-частотных характеристик.


 

Рисунок 2. Спектр синусоидального колебания, полученный программой Mathcad

Внешний вид простейшего амплитудно-модулированного колебания показан на рисунке 3, а его спектр – на рисунке 4.


Рисунок 3. Амплитудно-модулированное колебание


 

Рисунок 4. Спектр АМ-сигнала

 

Как видно на рисунке, спектральные компоненты исходного сигнала в случае амплитудной модуляции размещаются по обе стороны от несущей и образуют боковые полосы высокочастотного сигнала. Амплитудная модуляция является наиболее простым видом модуляции, но не самым эффективным с точек зрения полезного использования мощности передатчика, ширины занимаемого спектра и помехозащищённости сигнала.

При частотной модуляции (ЧМ, FM – frequency modulation) изменяется частота несущей, обычно по закону изменения амплитуды входного сигнала. ЧМ-сигнал обладает лучшей помехозащищённостью, чем АМ-сигнал, именно поэтому частотная модуляция применяется для стереофонического музыкального радиовещания. Но спектр ЧМ-сигнала значительно шире спектра АМ-сигнала, и именно поэтому такое вещание осуществляется в диапазоне ультракоротких радиоволн (УКВ), позволяющем разместить много широкополосных каналов. При фазовой модуляции (ФМ) изменяется фаза несущей. Ширина спектра ФМ-сигнала также превосходит ширину спектра АМ-сигнала. Частотная и фазовая модуляции относятся к угловой модуляции

Разновидностями амплитудной модуляции являются балансная модуляция (БАМ), называемая также модуляцией с подавленной несущей или двухполосной (DSB – Double Side Band, двойная боковая полоса), и однополосная модуляция (SSB – Single Side Band, одна боковая полоса). DSB-модуляция позволяет повысить эффективность использования мощности передатчика, поскольку в этом случае передается только полезный высокочастотный сигнал, на передачу несущей мощность не расходуется. SSB, дополнительно к этому, обеспечивает и повышение эффективности использования полосы канала, поскольку ширина спектра SSB-сигнала вдвое меньше спектра АМ- и DSB-сигналов.

В цифровых системах передачи или в том случае, когда в качестве несущей используется не синусоидальное колебание, а последовательность импульсов (обычно прямоугольных), используются амплитудно-импульсная (АИМ), частотно-импульсная (ЧИМ), фазо-импульсная (ФИМ) и широтно-импульсная (ШИМ) модуляции. Их подробности здесь рассматриваться не будут, многие детали совпадают со случаями АМ, ЧМ и ФМ. В современных системах беспроводной компьютерной связи (например, WiFi) используются достаточно сложные виды модуляции, которые также не будут применяться в курсовом проекте.

 

Разработка системы классов

Класс сообщения

Разработку системы классов начнём с класса сообщения. Рассмотрим компоненты данных этого класса. Сообщение может являться либо последовательностью отсчётов, либо последовательностью символов (или других значений), либо набором частотных компонент. Очевидно, что для хранения любого набора данных потребуется массив, а т.к. размер этого массива может быть заранее не известен, то будет использоваться динамический массив, адресуемый указателем. Таким образом, одно поле класса сообщения – указатель на тип данных, определяемый вариантом задания. Ещё одно поле – размер этого массива. С точки зрения состава полей класс сообщения оказывается аналогичным классу строки TString, рассмотренному в лекционном курсе. Аналогичным может быть и состав функций класса. Отличия у некоторых функций от функций класса TString в том, что не будут использоваться библиоттечные функции работы со строками.

Определение класса будет размещаться в отдельном файле с именем, например, "tmessage.h", который будет включаться в другие файлы, там где это необходимо, при помощи директивы препроцессора #include. Приведём файл с фрагментом определения класса сообщения:

#ifndef __TMESSAGE__

#define __TMESSAGE__

 

class TMessage

{

protected:

int len;

char *str;

// …

};

#endif

 

Набор директив

#ifndef __TMESSAGE__

#define __TMESSAGE__

#endif

предотвращает многократное включение файла в общий текст программы при компиляции и возникновение ошибок типа «повторное определение программного объекта или типа данных».

Класс сообщения будет использоваться в качестве базового, поэтому используется спецификатор protected. Набор конструкторов, деструктор и функции доступа к данным в этом классе совпадает с классом TString:

class TMessage

{

public:

TMessage() // стандартный конструктор

{ len=0; str=NULL; }

TMessage(int);

TMessage(const TMessage&); // конструктор копирования

TMessage(int,const char*);

~TMessage() // деструктор

{ delete[] str; }

int& GetLen() { return len; }

char* GetStr() { return str; }

// …

};

 

Определения конструкторов и функций класса поместим в отдельный файл с именем, например, "tmessage.cpp".

Определения конструкторов:

#include "tmessage.h"

TMessage::TMessage(int l)

{

len=l;

str=new type1[len];

}

TMessage::TMessage(const TMessage& So) // конструктор копирования

{

len=So.len;

str=new type1[len];

for(int i=0;i<len;i++)

str[i]=So.str[i];

}

TMessage::TMessage(int l,const char* S)

{

len=l;

str=new type1[len];

for(int i=0;i<len;i++)

str[i]=S[i];

}

Полезными для класса могут оказаться перегруженные операции =, [], и <<:

class TMessage

{

 //…

public:

TMessage& operator=(TMessage&);

char& operator[](int);

friend ostream& operator<<(ostream& is,TMessage& str);

};

Перегруженная операция присваивания во многом похожа на конструктор копирования:

TMessage& TMessage::operator=(TMessage& So)

{

if(&So==this)

return *this;

len=So.len;

str=new type1[len];

for(int i=0;i<So.len;i++)

str[i]=So.str[i];

return *this;

}

char& TMessage::operator[](int i)

{

if(i<len)

return str[i];

else

return str[len-1];

}

ostream& operator<<(ostream& os,TMessage& str)

{

for(int i=0;i<str.len;i++)

os<<int(str.str[i]);

return os;

}

 

Класс сигнала

Класс сигнала является производным от класса сообщения и отличается от него полем несущей частоты.

#ifndef TSIGNAL

#define TSIGNAL

 

#include "tmessage.h"

 

class TSignal:virtual public TMessage

{

// …

protected:

int CarrierFreq; // поле несущей частоты

};

#endif

 

Может потребоваться инициализация полей, унаследованных от класса TMessage, которая выполняется в соответствующем конструкторе:

class TSignal:virtual public TMessage

{

public:

TSignal(){ CarrierFreq=0; len=0; str=NULL; } // стандартный конструктор

TSignal(int n,const char* c,int f):TMessage(n,c),CarrierFreq(f)

{}

// …

};

Остальные конструкторы класса TSignal, а также функции доступа к данным и перегруженные операции, аналогичны таковым в классе TMessage и могут быть разработаны самостоятельно. Спецификатор virtual перед именем базового класса используется для вариантов, в которых возможно множественное наследование от классов, производных от TMessage. Если ситуация множественного наследования не возникает, то использование спецификатора virtual не обязательно.

 

Классы устройств

Все активные элементы системы связи, рассмотренные в §…, будут объектами соответствующих классов. Общими их свойствами будет то, что все они будут являться некоторыми устройствами, а также то, что все они будут выполнять над сигналом некоторое действие – модуляцию, усиление, ослабление, демодуляцию и т.п. В соответствии с этим обстоятельством сделаем классы этих устройств производными от класса некоторого абстрактного устройства, выполняющего абстрактную операцию. Пусть каждый объект производного класса характеризуется некоторым идентификатором (номером), который и будет полем базового класса устройств. Следует обратить внимание на то, что тип этого идентификатора должен совпадать с типом данных, составляющих сообщение, определяемым по варианту задания. Кроме этого поля и функции доступа к нему класс будет содержать конструкторы и прототип виртуальной функции, выполняющей в каждом производном классе специфические действия (файл tdevice.h):

#ifndef TDEVICE

#define TDEVICE

 

#include "TSignal.h"

#include "TMessage.h"

 

class TDevice

{

public:

TDevice(){}

TDevice(int n):Id(n){}

virtual TSignal Execute(TMessage&) = 0; // абстрактная функция

int& GetId() { return Id; }

protected:

int Id; // идентификатор объекта

};

#endif

Функция Execute является абстрактной, т.е. не выполняет никаких реальных действий, соответственно класс TDevice также является абстрактным. Результатом работы этой функции является объект класса TSignal (как результат преобразования), а источником данных является ссылка на объект базового для сигнала класса TMessage. Это позволяет использовать такую функцию для обработки объектов как класса TMessage, так класса TSignal. Использование этих классов требует включения в текущий файл заголовочных файлов "TSignal.h" и "TMessage.h" директивами #include.

 

Классы модуляторов

Первым активным устройством, выполняющим преобразование сигнала (или, в нашем случае, сообщения), является модулятор. В зависимости от варианта задания в курсовом проекте может быть более чем один модулятор, и все модуляторы будут выполнять модуляцию несовпадающего вида. Кроме того, модуляторы, выполняющие какой-либо вариант амплитудной модуляции, могут находиться между собой в более близком родстве, чем просто являться ”устройствами”, т.е. быть производными друг от друга. В этом случае может потребоваться класс абстрактного модулятора, производный от класса абстрактного устройства и служащий базовым для классов модуляторов конкретных типов. Общим свойством всех модуляторов может служить частота несущей и её уровень (т.е. величина сигнала несущей), которые и будут полями этого класса. Виртуальная функция может не переопределяться, в этом случае этот класс также будет абстрактным. Общая структура класса модулятора будет аналогичной классу TDevice, поэтому предлагается разработать этот класс самостоятельно.

Классы амплитудных модуляторов

Пусть сообщение и сигнал представлены набором спектральных компонент, тогда процесс модуляции будет выглядеть как формирование нового сигнала с другим набором спектральных компонент, причём наиболее просто это будет происходить для SSB-модуляции. Тогда DSB-модуляция будет усложнённым вариантом SSB-модуляции (класс DSB-модулятора будет производным от класса SSB-модулятора), а АМ-модуляция – усложнённым вариантом DSB (класс АМ-модулятора будет производным от класса DSB-модулятора).

Класс SSB-модулятора сделаем производным от класса модулятора вообще, причём единственное отличие между ними заключается в том, что функция Execute выполняет конкретные действия (файл ssb.h):

#ifndef _SSB_

#define _SSB_

 

#include "tmodulator.h"

 

class SSB:public TModulator

{

public:

SSB(int i,int c,type1 l=0):TModulator(i,c,l){} // Конструктор

TSignal Execute(TMessage&);

};

#endif

В определении класса видно, что инициализация его объектов на самом деле выполняется конструктором базового класса, которому конструктор текущего класса передаёт свои аргументы.

Приведём фрагмент функции Execute, на котором показано создание локального внутри функции объекта класса TSignal, применение для этого объекта перегруженной операции [] и возврат этого объекта (файл ssb.cpp):

#include "ssb.h"

TSignal SSB::Execute(TMessage& obj)

{

int Band=Carrier+obj.GetLen()+1;

TSignal local(Band);

local.GetCarrier()=Carrier;

local[Carrier]=Level;

// …

return local;

}

Основные действия функции Execute класса SSB по переносу спектра предлагается разработать самостоятельно, в соответствии со спектрами исходного сигнала и SSB-сигнала, приведёнными на рисунке 5.

Класс DSB-модулятора можно сделать производным от класса SSB. Отличие между ними будет заключаться только в действиях, выполняемых функцией Execute. Взаимодействие конструкторов производного и базового классов такое же, как в предыдущем случае:

DSB(int i,int c,char l=0):SSB(i,c,l){}

Рекомендуется разработать класс DSB-модулятора самостоятельно, по аналогии с классом SSB.


Рисунок 5. Спектр исходного и модулированного сигналов при SSB-модуляции

 

Функция Execute класса DSB может вызывать функцию Execute класса SSB:

TSignal DSB::Execute(TMessage& obj)

{

TSignal local(SSB::Execute(obj));

// …

return local;

}

 

Основные действия функции Execute класса DSB по переносу спектра предлагается разработать самостоятельно, в соответствии со спектрами исходного сигнала и DSB-сигнала, приведёнными на рисунке 6.

 

Рисунок 6. Спектр исходного и модулированного сигналов при DSB-модуляции

 

Класс AM-модулятора можно сделать производным от класса DSB. Отличие между ними также будет заключаться только в действиях, выполняемых функцией Execute, которую также предлагается разработать самостоятельно, в соответствии со спектрами исходного сигнала и AM-сигнала, приведёнными на рисунке 7. Взаимодействие конструкторов производного и базового классов такое же, как в предыдущем случае. Рекомендуется разработать класс АМ-модулятора самостоятельно, по аналогии с классом DSB.

 

 

Рисунок 7. Спектр исходного и модулированного сигналов при AM-модуляции

 

В том случае, если сообщение и сигнал представлены последовательностью отсчётов, классы амплитудных модуляторов, скорее всего, не будут производными друг от друга, а только будут иметь общий базовый класс абстрактного модулятора. Это объясняется достаточно большими отличиями в математических выражениях, описывающих эти виды модуляции. Так, амплитудная модуляция описывается выражением (упрощённо, без учёта фазы)

,                                   (1)

где U 0 – уровень несущей, U (t) – сообщение, КAM – коэффициент амплитудной модуляции, ω0 – частота несущей. Как видно из выражения (1), амплитудная модуляция не является простым перемножением двух сигналов, в отличие от балансной модуляции, описываемой выражением

.                                              (2)

В общем случае можно считать, что выражение (2) описывает и SSB-модуляцию, за исключением подавления одной из боковых полос (обычно, нижней). При выполнении курсового проекта рекомендуется самостоятельно продумать взаимоотношения между классами SSB- и DSB-модуляторов в зависимости от варианта задания.

Рассмотренное обстоятельство справедливо и для классов частотного и фазового модуляторов, независимо от формы представления сигнала, т.к. процесс формирования модулированного сигнала у этих модуляторов существенно отличается от семейства амплитудных модуляторов. Примерный вид спектра ЧМ-сигнала (и, в общем случае, ФМ-сигнала) показан на рисунке 8. Выражение, описывающее частотно-модулированный сигнал:

.                               (3)

При выполнении курсового проекта вычислять интеграл не требуется. Выражение для ФМ-сигнала:

.                                      (4)

 

 

 

Рисунок 8. Спектр исходного и ЧМ сигналов

 

Для тех вариантов задания, в которых сообщение и сигнал представляются набором отсчётов, функция Execute классов модуляторов должна выполнять одно из выражений (1) – (4).

 

Класс программы

На этом этапе разработки можно создать класс программы в целом, для проверки правильности построения функций уже созданных классов и демонстрации их работоспособности. Полями этого класса будут объекты (или указатели на объекты) классов TSignal, TMessage и, например, AM, а также строка, возможно объект класса TString, обеспечивающая интерфейс пользователя в виде меню допустимых команд. Функция в таком классе может быть только одна, не считая конструкторов (одного или нескольких). Определение класса разместим в отдельном файле, например, "tprogram.h".

#ifndef TPROGRAM

#define TPROGRAM

 

#include "tstring.cpp"

#include "tsignal.h"

#include "am.h"

 

class TProgram

{

public:

void Run();

TProgram(type1 *m1, char* m2, int i, int c, char L):

msg(m1),menu(m2),modulator(i,c,L) {}

private:

TMessage msg;

TSignal signal;

TString menu;

AM modulator;

// …

};

#endif

 

Функция Run() выполняет обработку команд пользователя и производит действия, соответствующие этим командам:

#include <conio.h>

#include "tprogram.h"

 

void TProgram::Run()

{

char key=1;

while(key!='0')

{

cout<<menu<<endl;

key=getch(); // Обработка нажатия клавиш

switch(key)

{

case '1': cout<<msg<<endl; break;

case '2': signal=modulator.Execute(msg); cout<<signal<<endl; break;

}

}

}

Объект класса TProgram будет создаваться в функции main(), находящейся в главном файле проекта. Этот файл может быть очень небольшим:

#include "tprogram.cpp"

#include "tmessage.cpp"

#include "ssb.cpp"

#include "dsb.cpp"

#include "am.cpp"

#include "tsignal.cpp"

int main()

{

char msg[10]={9,8,7,6,5,4,3,2,1,0}; // Пример сообщения

char menu[]="1-input 2-modulation 0-exit"; // Строка управляющего меню

int Freq=50,Id=1; // Аргументы конструктора класса TProgram

char CarrierLevel=30; // --//--

TProgram prog(msg,menu,Id,Freq,CarrierLevel);

prog.Run();

return 0;

}

В этом примере все файлы, включаемые директивой #include, кроме файла "tprogram.cpp", могут включаться в текст программы именно в файле "tprogram.cpp".

После разработки и отладки такого ядра программы можно наращивать состав классов и усложнять класс TProgram. В частности, потребуется создать класс шума (один или несколько, в зависимости от варианта задания) и класс канала связи, а также классы устройств на приёмной стороне.

 

Классы шумов и каналов

Различные виды шумов и помех являются неотъемлемым свойством каналов передачи информации, поэтому целесообразно разрабатывать классы этих объектов в связи друг с другом.

Класс аддитивного шума


Аддитивный, т.е. складывающийся с сигналом, шум, так же как и сообщение, может представлять собой набор спектральных компонент или отсчётов, и может ничем не отличаться от сообщения или сигнала. Но обычно шум как статистический процесс оценивают средним значением и средним отклонением от этого значения. Внешний вид шумового процесса показан на рисунке 9.

 

Рисунок 9. Аддитивный шум с нулевым средним значением

 

В курсовом проекте достаточно, чтобы аддитивный шум отличался от сообщения некоторым средним значением.

Таким образом, класс аддитивного или белого гауссовского шума, также как и класс сигнала, будет производным от класса сообщения:

#ifndef TNOISE

#define TNOISE

 

#include "tmessage.h"

 

class GaussNoise:public TMessage

{

public:

GaussNoise(){}

// …

GaussNoise(int n,type1 L);

protected:

char Level; // Уровень шума

};

#endif

Необходимые компоненты этого класса, в частности, конструктор с непустым списком аргументов и функцию доступа к полю уровня шума, предлагается разработать самостоятельно, по аналогии с ранее рассмотренными классами.

Вероятно, генерирование шума будет выполняться в конструкторе класса. Поскольку в курсовом проекте шум играет роль любого процесса, искажающего исходное сообщение, то не требуется, чтобы шум был обязательно случайным процессом, например, возможет такой способ генерации «шума»:

for(int i=0;i<len;i++)

str[i]=Level+i%3-1;

Выбор способа генерации шума оставляется на усмотрение студентов.

Класс сосредоточенной помехи

 

Сосредоточенная помеха, в сущности, представляет собой модулированный сигнал, частота несущей которого отличается от частоты несущей полезного сигнала. В зависимости от источника помехи, могут присутствовать или отсутствовать боковые полосы. В курсовом проекте для определённости примем, что боковых полос нет. Спектр, например, АМ-сигнала с наложенной сосредоточенной помехой показан на рисунке 10.

Рисунок 10. АМ-сигнал и сосредоточенная помеха

 

Класс сосредоточенной помехи может быть производным от класса сигнала, от которого он наследует массив значений и несущую частоту, и, в зависимости от варианта задания, от класса гауссовского шума, от которого он наследует значение уровня шума. В этом случае диаграмма наследования будет такой, как показано на рисунке 11.

 

 

 


Рисунок 11. Иерархия классов сообщения, сигнала и шумов

 

Предположим, что наличие шума или помехи является неотъемлемым свойством канала. В этом случае отношение между классами канала и шума может строиться двумя способами. Во-первых, класс канала может содержать в качестве поля объект соответствующего класса шума (или указатель на такой объект), и, во-вторых, класс канала может быть производным от класса шума. Второй вариант является более предпочтительным, поскольку в этом случае унаследованные поля будут инициализироваться конструктором базового класса.

Канал может считаться некоторым «устройством», выполняющим обработку сигнала (обработка будет заключаться в ослаблении сигнала и наложении на него шума). Как следствие, класс канала будет производным от класса абстрактного устройства, кроме того, ослабление сигнала как умножение его на некоторый коэффициент предполагает, что класс канала может быть производным от класса конкретного устройства, выполняющего подобную операцию. Таким устройством является усилитель.

Класс усилителя

Класс усилителя является производным от класса устройства, имеет очень простую структуру, – единственное собственное поле – коэффициент усиления, –и выполняет единственную операцию – умножение сигнала на коэффициент усиления. Поскольку эта же операция будет использоваться и для ослабления сигнала, то желательно, чтобы этот коэффициент был действительным числом, при ослаблении меньшим единицы. Саму операцию умножения следует предусмотреть как умножение объекта класса сигнала (или базового класса сообщения) на коэффициент, т.е. операция умножения должна быть перегружена в одном из этих классов. Такая перегрузка не представляет сложности, за исключением учёта того обстоятельства, что коэффициент является действительным числом. Для этого выполняется явное преобразование типов операндов:

str[i] = char (float (str[i]*Koef));

Остальные действия перегруженной операции умножения предлагается выполнить самостоятельно, так же как и разработку всего класса усилителя.

После создания класса усилителя можно завершить разработку класса канала.

Класс канала

Операция ослабления сигнала будет наследоваться от базового класса усилителя, параметры шума – от базового класса шума, собственной операцией этого класса будет наложение шума. Общую ”обработку” сигнала в канале можно выполнить несколькими способами. Рассмотрим один из них.

Заполнение массива значений шумом может выполняться в конструкторе класса шума. Но в том случае, когда при создании объекта класса шума размер массива значений в объекте сигнала ещё неизвестен, может потребоваться выполнить фактическую генерацию шума отдельной функцией, вызываемой непосредственно перед обработкой сигнала. Операции, выполняемые этой функцией – такие же, как в конструкторе класса шума.

Для ослабления сигнала перед наложением шума можно воспользоваться унаследованной от класса усилителя функцией. Тогда функция Execute в классе канала может выглядеть следующим образом:

TSignal TChannel::Execute(TMessage& obj)

{

TSignal local(TAmplifier::Execute(obj)); // ослабление

for(int i=0;i<local.GetLen();i++)

local[i]+=str[i]; // наложение шума

return local;

}

Полностью класс канала предлагается разработать самостоятельно.

 

Классы фильтров

Предположим, что все типы фильтров, независимо от варианта задания, характеризуются некоторым общим параметром, которым может быть граничная частота, выше (или ниже) которой сигнал (и шум) полностью ослабляется. Конкретной реализацией фильтрации отдельные типы фильтров могут (и будут) отличаться. Таким образом, в программе может быть несколько классов фильтров, которые будут производными от класса фильтра вообще. Этот класс будет производным от класса устройства, причём абстрактная функция Execute в нём не будет переопределена, т.е. класс фильтра останется абстрактным.

#ifndef TFILTER

#define TFILTER

 

#include "tdevice.h"

 

class TFilter:public TDevice

{

public:

TFilter(int i,int f):TDevice(i),SrezFreq(f){}

protected:

int SrezFreq; // Граничная частота

};

#endif

Класс фильтра FFT

Все классы фильтров строятся по одинаковому принципу и имеют очень простую структуру, которую рассмотрим на примере класса фильтра, выполняющего фильтрацию сигнала в частотной области, т.е. на основе быстрого преобразования Фурье (БПФ, FFTFast Fourier Transform) (файл fft.h ):

#ifndef FFTFILTER

#define FFTFILTER

 

#include "tfilter.h"

 

class FFTfilter:public TFilter

{

public:

FFTfilter(int i,int f):TFilter(i,f){}

TSignal Execute(TMessage&);

};

#endif

Функция фильтрации для случая представления сигнала набором частотных компонент будет очень простой (файл fft.cpp):

#include "fft.h"

TSignal FFTfilter::Execute(TMessage& obj)

{

for(int i=0;i<SrezFreq;i++)

obj.GetStr()[i]=0;

return obj;

}

В этой функции преобразование Фурье как таковое не используется, в курсовом проекте это не имеет значения.

Классы фильтров, соответствующих другим вариантам задания предлагается разработать самостоятельно, в соответствии с математическими выражениями фильтрации (5), (6).

Фильтрация во временнОй области является цифровой фильтрацией и для фильтра нижних частот (ФНЧ) в простейшем случае определяется выражением

.                                       (5)

Также цифровой является медианная фильтрация, которая требует сортировки данных; в случае трёх отсчётов определяется выражением

.                              (6)

При разработке функций, реализующих выражения (5) и (6), следует иметь в виду, что результат фильтрации S’ должен помещаться в отдельный (вспомогательный) массив.

 

Классы демодуляторов

Демодуляторы или детекторы выполняют операцию, обратную выполняемой модуляторами. Классы демодуляторов могут проектироваться по такому же принципу, что и классы модуляторов. В случае представления сигнала набором частотных компонент соответствующий детектор выполняет формирование низкочастотного сигнала по известному модулированному сигналу и известной частоте несущей (рисунки 5 – 7). Для всех типов амплитудных детекторов низкочастотный сигнал формируется по верхней боковой полосе, независимо от типа модуляции (выполняется перенос этой полосы вниз по спектру). Эта операция очень простая и оставляется на самостоятельную разработку. Для частотной и фазовой модуляции кроме переноса по спектру следует учесть увеличение ширины боковых полос (рисунок 8).

В случае представления сигнала набором отсчётов демодуляция может свестись к вычислению значений U’(t) по известному значению S(t) по выражениям, обратным выражениям (1) – (4), причём для целей курсового проекта выражения не обязательно должны быть сложными с точки зрения математики.

 

Класс коммутатора

Коммутатор является устройством (это означает, что его класс будет производным от класса устройства), выполняющим подачу сигнала (в этом и будет заключаться действие функции Execute) на один (активный) из нескольких каналов (т.е. полем класса будет массив каналов). При разработке класса следует учесть важное обстоятельство – в зависимости от варианта задания коммутируемые каналы могут обладать различными свойствами, в частности, аддитивным шумом, либо сосредоточенной помехой. Для этих каналов будут вызываться соответствующие виртуальные функции Execute. Это означает, что в массиве каналов должны использоваться не объекты класса канала, а указатели на базовый для канала класс, в котором есть виртуальная функция, т.е. на класс TDevice. Поскольку количество каналов заранее не определено, массив должен быть динамическим и для указания его размера следует использовать отдельное поле. Также для доступа к элементам массива целесообразно перегрузить для этого класса операцию []. Таким образом, на этом этапе разработки определение класса коммутатора может быть таким (файл tcommutator.h):

#ifndef TCOMMUTATOR

#define TCOMMUTATOR

 

#include "tdevice.h"

#include "tchannel.h"

 

class TCommutator:public TDevice

{

int NChannels,Active; // Количество каналов и номер активного канала

TDevice **Vyhod; // Динамический массив указателей на каналы

public:

TCommutator(int i,int n):TDevice(i),NChannels(n),Active(0)

{

Vyhod=new TDevice*[NChannels];

}

TDevice*& operator[](int);

TSignal Execute(TMessage&);

};

#endif

Использование массива указателей, а не массива объектов, обладает тем преимуществом, что сами объекты класса канала не хранятся в объекте класса коммутатора. В этом случае для заполнения массива каналов используется соответствующая функция (прототип её в классе TCommutator не показан):

void TCommutator::SetChannel(int n,TDevice* pobj)

{

Vyhod[n]=pobj;

}

Функция активизации выбранного канала (прототип также не показан):

void TCommutator::SetActive(int n)

{

if(n<NChannels)

Active=n;

else

Active=NChannels-1;

}

Перегруженная операция [] и функция Execute:

TDevice*& TCommutator::operator[](int i)

{

if(i<NChannels && i>=0)

return Vyhod[i];

else

return Vyhod[0];

}

 

TSignal TCommutator::Execute(TMessage& obj)

{

TSignal local=Vyhod[Active]->Execute(obj);

return local;

}

 


Дата добавления: 2018-05-12; просмотров: 689; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!