#! /usr/bin/perl

# Name:			CEAmp1.pl
# Author:		James M. Lynes, Jr.
# Created:		May 1, 2015
# Modified By:		James M. Lynes, Jr.
# Last Modified:	May 7, 2015
# Change Log:		5/1/2015 - Program Created
#                       5/2/2015 - Fixed $IcqText box for blank field case
#                                - Move $title into the verticle sizer
#                                - Move Design & Exit buttons to the right
#                       5/6/2015 - Modify Sizer layout
#			5/7/2015 - Change TextCtrls to SpinCtrls - prevents divide by 0 possibility
#                                - Used Eagle to draw a border around the schematic bitmap
#                                - Added comments throughout
# Description:		Common Emitter Amp Designer
#                                  Given Vcc, Vceq, Icq, Beta, & Av
#                                  Calculate Bias, Collector, & Emitter Resistor Values
#

package main;
use strict;
use warnings;
my $app = App->new();
$app->MainLoop;

package App;
use strict;
use warnings;
use base 'Wx::App';
sub OnInit {
    Wx::InitAllImageHandlers();
    my $frame = Frame->new();
    $frame->Show(1);
}

package Frame;
use strict;
use warnings;
use Wx qw(:everything);
use base qw(Wx::Frame);
use CEAmp;
use Data::Dumper;

sub new {
    my ($class, $parent) = @_;

    my $self = $class->SUPER::new($parent, -1, "Common Emitter Amplifier Designer", wxDefaultPosition, wxDefaultSize);

#   Create an instance of a CE Amp object(defined in CEAmp.pm)

    $self->{AMP1} = CEAmp::Data->new();

#   Create the Schematic Bitmap(Created in Eagle and exported to a PNG file)

    my $bmp = Wx::Bitmap->new("CEAmpImg1.png", wxBITMAP_TYPE_PNG);
    my $sbm = Wx::StaticBitmap->new($self, wxID_ANY, $bmp, wxDefaultPosition, wxDefaultSize);

# Create Controls

    my $title = Wx::StaticText->new($self, wxID_ANY, "Common Emitter Amplifier Designer",
                                    wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);

    my $VccLabel = Wx::StaticText->new($self, wxID_ANY, "   Vcc,v", wxDefaultPosition, wxDefaultSize); 
    my $VccText = Wx::SpinCtrl->new($self, wxID_ANY, "12", wxDefaultPosition, wxDefaultSize, 
                                    wxSP_ARROW_KEYS | wxSP_WRAP | wxALIGN_RIGHT, 1, 24, 12);
 
    my $VceqLabel = Wx::StaticText->new($self, wxID_ANY, "   Vceq,v", wxDefaultPosition, wxDefaultSize); 
    my $VceqText = Wx::SpinCtrl->new($self, wxID_ANY, "5", wxDefaultPosition, wxDefaultSize,
                                    wxSP_ARROW_KEYS | wxSP_WRAP | wxALIGN_RIGHT, 1, 24, 5);

    my $IcqLabel = Wx::StaticText->new($self, wxID_ANY, "   Icq,ma", wxDefaultPosition, wxDefaultSize); 
    my $IcqText = Wx::SpinCtrl->new($self, wxID_ANY, "4", wxDefaultPosition, wxDefaultSize,
                                    wxSP_ARROW_KEYS | wxSP_WRAP | wxALIGN_RIGHT, 1, 40, 4);

    my $BetaLabel = Wx::StaticText->new($self, wxID_ANY, "   Beta", wxDefaultPosition, wxDefaultSize); 
    my $BetaText = Wx::SpinCtrl->new($self, wxID_ANY, "150", wxDefaultPosition, wxDefaultSize,
                                    wxSP_ARROW_KEYS | wxSP_WRAP | wxALIGN_RIGHT, 1, 300, 150);

    my $AvLabel = Wx::StaticText->new($self, wxID_ANY, "   Av", wxDefaultPosition, wxDefaultSize); 
    my $AvText = Wx::SpinCtrl->new($self, wxID_ANY, "5", wxDefaultPosition, wxDefaultSize,
                                    wxSP_ARROW_KEYS | wxSP_WRAP | wxALIGN_RIGHT, 1, 100, 5);

    my $R1Label = Wx::StaticText->new($self, wxID_ANY, "R1", wxDefaultPosition, wxDefaultSize); 
    my $R1Text = Wx::TextCtrl->new($self, wxID_ANY, "0", wxDefaultPosition, wxDefaultSize, wxTE_READONLY);

    my $R2Label = Wx::StaticText->new($self, wxID_ANY, "R2", wxDefaultPosition, wxDefaultSize); 
    my $R2Text = Wx::TextCtrl->new($self, wxID_ANY, "0", wxDefaultPosition, wxDefaultSize, wxTE_READONLY);

    my $RcLabel = Wx::StaticText->new($self, wxID_ANY, "Rc", wxDefaultPosition, wxDefaultSize); 
    my $RcText = Wx::TextCtrl->new($self, wxID_ANY, "0", wxDefaultPosition, wxDefaultSize, wxTE_READONLY);

    my $ReLabel = Wx::StaticText->new($self, wxID_ANY, "Re", wxDefaultPosition, wxDefaultSize); 
    my $ReText = Wx::TextCtrl->new($self, wxID_ANY, "0", wxDefaultPosition, wxDefaultSize, wxTE_READONLY);

# Create Buttons

    my $designButtonID = 1000;
    my $designButton = Wx::Button->new($self, $designButtonID, "Design", wxDefaultPosition, wxDefaultSize);
    my $exitButton = Wx::Button->new($self, wxID_EXIT, "", wxDefaultPosition, wxDefaultSize);

# Create Sizers

    my $verticalSizerFrame = Wx::BoxSizer->new(wxHORIZONTAL);
    $self->SetSizer($verticalSizerFrame);

    my $leftSizer = Wx::BoxSizer->new(wxVERTICAL);
    my $rightSizer = Wx::BoxSizer->new(wxVERTICAL);
    my $verticalSizerControls = Wx::BoxSizer->new(wxVERTICAL);
    my $horizontalSizerOutputs = Wx::BoxSizer->new(wxHORIZONTAL);
    my $horizontalSizerButtons = Wx::BoxSizer->new(wxHORIZONTAL);

# Layout Sizers

    $verticalSizerFrame->Add($leftSizer, 0, 0, 0);
    $verticalSizerFrame->Add($rightSizer, 0, 0, 0);

    $leftSizer->Add($verticalSizerControls, 0, 0, 0);
    $rightSizer->AddSpacer(50);
    $rightSizer->Add($sbm, 0, 0, 0);
    $rightSizer->AddSpacer(20);
    $rightSizer->Add($horizontalSizerOutputs, 0, 0, 0);
    $rightSizer->AddSpacer(40);
    $rightSizer->Add($horizontalSizerButtons, 0, 0, 0);

    $verticalSizerControls->Add($title, 0, 0, 0);
    $verticalSizerControls->AddSpacer(30);
    $verticalSizerControls->Add($VccLabel, 0, 0, 0);
    $verticalSizerControls->Add($VccText, 0, 0, 0);
    $verticalSizerControls->AddSpacer(15);
    $verticalSizerControls->Add($VceqLabel, 0, 0, 0);
    $verticalSizerControls->Add($VceqText, 0, 0, 0);
    $verticalSizerControls->AddSpacer(15);
    $verticalSizerControls->Add($IcqLabel, 0, 0, 0);
    $verticalSizerControls->Add($IcqText, 0, 0, 0);
    $verticalSizerControls->AddSpacer(15);
    $verticalSizerControls->Add($BetaLabel, 0, 0, 0);
    $verticalSizerControls->Add($BetaText, 0, 0, 0);
    $verticalSizerControls->AddSpacer(15);
    $verticalSizerControls->Add($AvLabel, 0, 0, 0);
    $verticalSizerControls->Add($AvText, 0, 0, 0);
    $verticalSizerControls->AddSpacer(15);

    $horizontalSizerOutputs->Add($R1Label, 0, 0, 0);
    $horizontalSizerOutputs->Add($R1Text, 0, 0, 0);
    $horizontalSizerOutputs->AddSpacer(10);
    $horizontalSizerOutputs->Add($R2Label, 0, 0, 0);
    $horizontalSizerOutputs->Add($R2Text, 0, 0, 0);
    $horizontalSizerOutputs->AddSpacer(10);
    $horizontalSizerOutputs->Add($RcLabel, 0, 0, 0);
    $horizontalSizerOutputs->Add($RcText, 0, 0, 0);
    $horizontalSizerOutputs->AddSpacer(10);
    $horizontalSizerOutputs->Add($ReLabel, 0, 0, 0);
    $horizontalSizerOutputs->Add($ReText, 0, 0, 0);

    $horizontalSizerButtons->AddSpacer(300);
    $horizontalSizerButtons->Add($designButton, 0, 0, 0);
    $horizontalSizerButtons->AddSpacer(40);
    $horizontalSizerButtons->Add($exitButton, 0, 0, 0);

# Create Event Handlers

    Wx::Event::EVT_BUTTON($self, $designButton, sub {
                          my ($self, $event) = @_;
                          CEAmp->design($self, $self->{AMP1});		# Run the Design Calculations
                          $R1Text->SetValue($self->{AMP1}->R1);		# Copy results back to Output Controls
                          $R2Text->SetValue($self->{AMP1}->R2);
                          $RcText->SetValue($self->{AMP1}->Rc);
                          $ReText->SetValue($self->{AMP1}->Re);});

    Wx::Event::EVT_BUTTON($self, $exitButton, sub {			# Exit
                          my ($self, $event) = @_;
                          $self->Close;});

    Wx::Event::EVT_TEXT($self, $VccText, sub {				# Copy changed input field to object
                        my ($self, $event) = @_;
                        $self->{AMP1}->Vcc($VccText->GetValue);});

    Wx::Event::EVT_TEXT($self, $VceqText, sub {				# Copy changed input field to object
                        my ($self, $event) = @_;
                        $self->{AMP1}->Vceq($VceqText->GetValue);});

    Wx::Event::EVT_TEXT($self, $IcqText, sub {				# Copy changed input field to object
                        my ($self, $event) = @_;
                         $self->{AMP1}->Icq($IcqText->GetValue / 1000)});

    Wx::Event::EVT_TEXT($self, $BetaText, sub {				# Copy changed input field to object
                        my ($self, $event) = @_;
                        $self->{AMP1}->Beta($BetaText->GetValue);});

    Wx::Event::EVT_TEXT($self, $AvText, sub {				# Copy changed input field to object
                        my ($self, $event) = @_;
                        $self->{AMP1}->Av($AvText->GetValue);});


    $verticalSizerFrame->Fit($self);
    $verticalSizerFrame->Layout();

    return $self;
}
1;

