/*
Copyright (C) 2000 T. Scott Dattalo
This file is part of gpsim.
gpsim is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
gpsim is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with gpsim; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/*
Logic.cc
This is an example module library for interfacing with gpsim.
In here you'll find some simple logic devices:
AND2Gate - A 2-input AND gate
OR2Gate - A 2-input OR gate
*/
/* IN_MODULE should be defined for modules */
#define IN_MODULE
#include "../config.h" // get the definition for HAVE_GUI
#ifdef HAVE_GUI
/* XPM */
static char * and2_pixmap[] = {
"32 32 3 1",
" c black",
". c None",
"X c white",
" ............",
" ........",
" XXXXXXXXXXXXXXXXXX ........",
" XXXXXXXXXXXXXXXXXXXXXX ......",
" XXXXXXXXXXXXXXXXXXXXXX ......",
" XXXXXXXXXXXXXXXXXXXXXXXX ....",
" XXXXXXXXXXXXXXXXXXXXXXXX ...",
" XXXXXXXXXXXXXXXXXXXXXXXXX ...",
" XXXXXXXXXXXXXXXXXXXXXXXXXXX .",
" XXXXXXXXXXXXXXXXXXXXXXXXXXX .",
" XXXXXXXXXXXXXXXXXXXXXXXXXXX .",
" XXXXXX XXX XXX X XXXXXXX .",
" XXXXX X XX XX XX XX XXXXXX .",
" XXXX XXX X XX XX XX XXXXXXX ",
" XXXX XXX X X X XX XX XXXXXXX ",
" XXXX XXX X X X XX XX XXXXXXX ",
" XXXX X XX XX XX XXXXXXX ",
" XXXX XXX X XX XX XX XXXXXXX ",
" XXXX XXX X XXX XX XX XXXXXXX ",
" XXXX XXX X XXX X XXXXXXX .",
" XXXXXXXXXXXXXXXXXXXXXXXXXXX .",
" XXXXXXXXXXXXXXXXXXXXXXXXXXX .",
" XXXXXXXXXXXXXXXXXXXXXXXXXXX .",
" XXXXXXXXXXXXXXXXXXXXXXXXXXX .",
" XXXXXXXXXXXXXXXXXXXXXXXXX ...",
" XXXXXXXXXXXXXXXXXXXXXXXX ...",
" XXXXXXXXXXXXXXXXXXXXXXXX ....",
" XXXXXXXXXXXXXXXXXXXXXX ......",
" XXXXXXXXXXXXXXXXXXXXXX ......",
" XXXXXXXXXXXXXXXXXX ........",
" ........",
" ............"};
/* XPM */
static char * or2_pixmap[] = {
"32 32 3 1",
" c black",
". c None",
"X c white",
" ............",
" ........",
" XXXXXXXXXXXXXXXXXX ........",
" XXXXXXXXXXXXXXXXXXXXXX ......",
" XXXXXXXXXXXXXXXXXXXXXX ......",
". XXXXXXXXXXXXXXXXXXXXXXX ....",
". XXXXXXXXXXXXXXXXXXXXXXX ...",
". XXXXXXXXXXXXXXXXXXXXXXXX ...",
".. XXXXXXXXXXXXXXXXXXXXXXXXX .",
".. XXXXXXXXXXXXXXXXXXXXXXXXX .",
".. XXXXXXXXXXXXXXXXXXXXXXXXX .",
".. XXXXXXX XX XXXXXXXXX .",
"... XXXXX XXX X XXX XXXXXXXX .",
"... XXXXX XXX X XXX XXXXXXXXX ",
"... XXXXX XXX X XXX XXXXXXXXX ",
"... XXXXX XXX X XXXXXXXXXX ",
"... XXXXX XXX X X XXXXXXXXXXX ",
"... XXXXX XXX X XX XXXXXXXXXX ",
"... XXXXX XXX X XXX XXXXXXXXX ",
"... XXXXXX XX XXX XXXXXXXX .",
".. XXXXXXXXXXXXXXXXXXXXXXXXX .",
".. XXXXXXXXXXXXXXXXXXXXXXXXX .",
".. XXXXXXXXXXXXXXXXXXXXXXXXX .",
".. XXXXXXXXXXXXXXXXXXXXXXXXX .",
". XXXXXXXXXXXXXXXXXXXXXXXX ...",
". XXXXXXXXXXXXXXXXXXXXXXX ...",
". XXXXXXXXXXXXXXXXXXXXXXX ....",
" XXXXXXXXXXXXXXXXXXXXXX ......",
" XXXXXXXXXXXXXXXXXXXXXX ......",
" XXXXXXXXXXXXXXXXXX ........",
" ........",
" ............"};
static char * xor2_pixmap[] = {
"40 32 3 1",
" c None",
". c black",
"X c white",
" .................... ",
" .. .................... ",
" .... ........................ ",
" ... ..XXXXXXXXXXXXXXXXXX.... ",
" ... ..XXXXXXXXXXXXXXXXXXXXXX.. ",
" ... ..XXXXXXXXXXXXXXXXXXXXXX.. ",
" .... ..XXXXXXXXXXXXXXXXXXXXXXX.. ",
" ... ..XXXXXXXXXXXXXXXXXXXXXXX... ",
" ... ..XXXXXXXXXXXXXXXXXXXXXXXX.. ",
" ... ..XXXXXXXXXXXXXXXXXXXXXXXXX.. ",
" .... ..XXXXXXXXXXXXXXXXXXXXXXXXX.. ",
" ... ..XXXXXXXXXXXXXXXXXXXXXXXXX.. ",
" ... ..XXXX.XXX.XX...XX....XXXXX.. ",
" .. ..XXX.XXX.X.XXX.X.XXX.XXXX.. ",
" .. ..XXXX.X.XX.XXX.X.XXX.XXXXX..",
" .. ..XXXX.X.XX.XXX.X.XXX.XXXXX..",
" ... ..XXXXX.XXX.XXX.X....XXXXXX..",
" ... ..XXXX.X.XX.XXX.X.X.XXXXXXX..",
" ... ..XXXX.X.XX.XXX.X.XX.XXXXXX..",
" ... ..XXX.XXX.X.XXX.X.XXX.XXXXX..",
" ... ..XXX.XXX.XX...XX.XXX.XXXX.. ",
" ... ..XXXXXXXXXXXXXXXXXXXXXXXXX.. ",
" .. ..XXXXXXXXXXXXXXXXXXXXXXXXX.. ",
" ... ..XXXXXXXXXXXXXXXXXXXXXXXXX.. ",
" ... ..XXXXXXXXXXXXXXXXXXXXXXXXX.. ",
" ... ..XXXXXXXXXXXXXXXXXXXXXXXX.. ",
" ... ..XXXXXXXXXXXXXXXXXXXXXXX... ",
" ... ..XXXXXXXXXXXXXXXXXXXXXXX.. ",
" .... ..XXXXXXXXXXXXXXXXXXXXXX.. ",
" ..... ..XXXXXXXXXXXXXXXXXXXXXX.. ",
" .... ..XXXXXXXXXXXXXXXXXX.... ",
" .. ........................ "};
static char * not_pixmap[] = {
"32 32 3 1",
" c black",
". c None",
"X c white",
" ...............................",
" .............................",
" ...........................",
" X ..........................",
" XXX ........................",
" XXXX ......................",
" XXXXXX ....................",
" XXXXXXXX ...................",
" XXXXXXXXXX .................",
" XXXXXXXXXXX ...............",
" XXXXXXXXXXXXX ..............",
" XXXXXXXXXXXXXXX ............",
" XXXXXXXXXXXXXXXX ..... ..",
" XXXXXXXXXXXXXXXXXX .. XXX .",
" XXXXXXXXXXXXXXXXXXXX XXXXX ",
" XXXXXXXXXXXXXXXXXXXXXX XXXXX ",
" XXXXXXXXXXXXXXXXXXXX XXXXX ",
" XXXXXXXXXXXXXXXXXXX .. XXX .",
" XXXXXXXXXXXXXXXXX ..... ..",
" XXXXXXXXXXXXXXX ...........",
" XXXXXXXXXXXXXX .............",
" XXXXXXXXXXXX ...............",
" XXXXXXXXXXX ................",
" XXXXXXXXX ..................",
" XXXXXXX ...................",
" XXXXXX .....................",
" XXXX .......................",
" XXX ........................",
" X ..........................",
" ...........................",
" .............................",
" ..............................."};
#include <gtk/gtk.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <string>
#include "logic.h"
#include "../src/packages.h"
#include "../src/gpsim_interface.h"
#include "../src/attributes.h"
//--------------------------------------------------------------
// Led_Input
// This class is a minor extension of a normal IO_input. I may
// remove it later, but for now it does serve a simple purpose.
// Specifically, this derivation will intercept when a stimulus
// is being changed.
void Logic_Input::setDrivenState( bool new_state)
{
if(0)
cout << name()<< " setDrivenState= "
<< (new_state ? "high" : "low") << endl;
if(new_state != getDrivenState()) {
bDrivingState = new_state;
bDrivenState = new_state;
if(LGParent) {
LGParent->update_input_pin(m_iobit, new_state);
LGParent->update_state();
}
}
}
/*************************************************************
*
* LogicGate class
*/
LogicGate::LogicGate(void)
{
#ifdef HAVE_GUI
pixmap=0;
#endif
}
LogicGate::~LogicGate(void)
{
}
//--------------------------------------------------------------
void LogicGate::update_input_pin(unsigned int pin, bool bValue)
{
unsigned int mask = 1<<pin;
input_state &= ~mask;
input_state |= bValue ? mask : 0;
}
//--------------------------------------------------------------
// create_iopin_map
//
// This is where the information for the Module's package is defined.
// Specifically, the I/O pins of the module are created.
void LogicGate::create_iopin_map(void)
{
int i;
// Define the physical package.
// The Package class, which is a parent of all of the modules,
// is responsible for allocating memory for the I/O pins.
//
create_pkg(number_of_pins);
// Define the I/O pins and assign them to the package.
// There are two things happening here. First, there is
// a new I/O pin that is being created. For the binary
// indicator, both pins are inputs. The second thing is
// that the pins are "assigned" to the package. If we
// need to reference these newly created I/O pins (like
// below) then we can call the member function 'get_pin'.
// all logic gates have one or more inputs, but only one
// output. The output is arbitrarily assigned to position
// 0 on the I/O port while the inputs go to positions 1 and above
#define OUTPUT_BITPOSITION 0
#define INPUT_FIRST_BITPOSITION (OUTPUT_BITPOSITION + 1)
// Here, we name the port `pin'. So in gpsim, we will reference
// the bit positions as U1.pin0, U1.pin1, ..., where U1 is the
// name of the logic gate (which is assigned by the user and
// obtained with the name() member function call).
string outname = name() + ".out";
pOutputPin = new Logic_Output(this, OUTPUT_BITPOSITION, outname.c_str());
pOutputPin->update_direction(1,true); // make the bidirectional an output
// Position pin on middle right side of package
package->set_pin_position(1,2.5);
assign_pin(OUTPUT_BITPOSITION + 1, pOutputPin);
Logic_Input *LIP;
int j;
pInputPins = (IOPIN **) new char[sizeof (IOPIN *) * (number_of_pins-1)];
string inname;
for(i=j=INPUT_FIRST_BITPOSITION; i<number_of_pins; i++) {
char pin_number = i-j +'0';
inname = name() + ".in" + pin_number;
//p[2] = i-j +'0';
LIP = new Logic_Input(this, i-INPUT_FIRST_BITPOSITION,inname.c_str());
pInputPins[i-INPUT_FIRST_BITPOSITION] = LIP;
if(number_of_pins==2)
package->set_pin_position(i+1, 0.5); // Left side of package
else
package->set_pin_position(i+1, (float)((i-INPUT_FIRST_BITPOSITION)*0.9999)); // Left side of package
assign_pin(i+1, LIP ); // Pin numbers begin at 1
}
// Form the logic gate bit masks
input_bit_mask = (1<< (number_of_pins-1)) - 1;
initializeAttributes();
}
#ifdef HAVE_GUI
static gboolean expose(GtkWidget *widget,
GdkEventExpose *event,
LogicGate *lg)
{
if(lg->pixmap==0)
{
puts("LogicGate has no pixmap");
return 0;
}
gdk_draw_pixmap(widget->window,
widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
lg->pixmap,
event->area.x, event->area.y,
event->area.x, event->area.y,
event->area.width, event->area.height);
return 0;
}
GtkWidget *LogicGate::create_pixmap(char **pixmap_data)
{
GtkStyle *style;
GdkBitmap *mask;
GtkWidget *da;
int width,height;
style = gtk_style_new();
pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL,
gdk_colormap_get_system(),
&mask,
&style->bg[GTK_STATE_NORMAL],
pixmap_data);
#if GTK_MAJOR_VERSION >= 2
gdk_drawable_get_size(pixmap,&width,&height);
#else
gdk_window_get_size(pixmap,&width,&height);
#endif
da = gtk_drawing_area_new();
gtk_drawing_area_size(GTK_DRAWING_AREA(da),width,height);
gtk_signal_connect(GTK_OBJECT(da),"expose_event",
(GtkSignalFunc) expose,this);
return da;
}
#endif
//--------------------------------------------------------------
// construct
Module * AND2Gate::construct(const char *_new_name)
{
AND2Gate *a2gP = new AND2Gate ;
a2gP->new_name(_new_name);
a2gP->set_number_of_pins(3);
a2gP->create_iopin_map();
return a2gP;
}
AND2Gate::AND2Gate(void)
{
#ifdef HAVE_GUI
if(get_interface().bUsingGUI())
set_widget(create_pixmap(and2_pixmap));
#endif
}
AND2Gate::~AND2Gate(void)
{
}
void ANDGate::update_state(void)
{
pOutputPin->putState((input_state & input_bit_mask) == input_bit_mask);
if (pOutputPin->snode)
pOutputPin->snode->update();
}
//--------------------------------------------------------------
// construct
OR2Gate::OR2Gate(void)
{
#ifdef HAVE_GUI
if(get_interface().bUsingGUI())
set_widget(create_pixmap(or2_pixmap));
#endif
}
OR2Gate::~OR2Gate(void)
{
}
Module * OR2Gate::construct(const char *_new_name)
{
OR2Gate *o2gP = new OR2Gate ;
o2gP->new_name(_new_name);
o2gP->set_number_of_pins(3);
o2gP->create_iopin_map();
return o2gP;
}
void ORGate::update_state(void)
{
pOutputPin->putState((input_state & input_bit_mask) != 0);
}
//--------------------------------------------------------------
// construct NOT
Module * NOTGate::construct(const char *_new_name)
{
NOTGate *a2gP = new NOTGate ;
a2gP->new_name(_new_name);
a2gP->set_number_of_pins(2);
a2gP->create_iopin_map();
return a2gP;
}
NOTGate::NOTGate(void)
{
#ifdef HAVE_GUI
if(get_interface().bUsingGUI())
set_widget(create_pixmap(not_pixmap));
#endif
}
NOTGate::~NOTGate(void)
{
}
void NOTGate::update_state(void)
{
pOutputPin->putState((input_state & input_bit_mask) == 0);
}
//--------------------------------------------------------------
// construct
XOR2Gate::XOR2Gate(void)
{
#ifdef HAVE_GUI
if(get_interface().bUsingGUI())
set_widget(create_pixmap(xor2_pixmap));
#endif
}
XOR2Gate::~XOR2Gate(void)
{
}
Module * XOR2Gate::construct(const char *_new_name)
{
XOR2Gate *o2gP = new XOR2Gate ;
o2gP->new_name(_new_name);
o2gP->set_number_of_pins(3);
o2gP->create_iopin_map();
return o2gP;
}
void XORGate::update_state(void)
{
bool bNewOutputState=false;
unsigned int mask=input_bit_mask;
while(mask) {
unsigned int lsb = (~mask + 1) & mask;
mask ^= lsb;
bNewOutputState ^= (lsb & input_state) ? true : false;
}
pOutputPin->putState(bNewOutputState);
}
syntax highlighted by Code2HTML, v. 0.9.1