ram.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2005 by David Saxton                                    *
00003  *   david@bluehaze.org                                                    *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  ***************************************************************************/
00010 
00011 #include "libraryitem.h"
00012 #include "logic.h"
00013 #include "ram.h"
00014 #include "variant.h"
00015 
00016 #include <cmath>
00017 #include <klocale.h>
00018 
00019 Item* RAM::construct( ItemDocument *itemDocument, bool newItem, const char *id )
00020 {
00021         return new RAM( (ICNDocument*)itemDocument, newItem, id );
00022 }
00023 
00024 LibraryItem* RAM::libraryItem()
00025 {
00026         return new LibraryItem(
00027                 QString("ec/ram"),
00028                 i18n("RAM"),
00029                 i18n("Integrated Circuits"),
00030                 "ic2.png",
00031                 LibraryItem::lit_component,
00032                 RAM::construct
00033                         );
00034 }
00035 
00036 RAM::RAM( ICNDocument *icnDocument, bool newItem, const char *id )
00037         : Component( icnDocument, newItem, id ? id : "ram" )
00038 {
00039         m_name = i18n("RAM");
00040         m_desc = i18n("This RAM stores data as a collection of words; each of which contains <i>word size</i> bits of data.<br><br>To read data, set the CS (<i>chip select</i>) and the OE (<i>output enable</i>) pins high, and select the word using the address pins <i>A*</i>. The word is outputted on the data-out pins: <i>DO*</i>.<br><br>To write data, set the CS (<i>chip select</i>) and the WE (<i>write enable</i>) pins high, and select the address to write to with the <i>A*</i> pins. Write to the selected word using the data-in pins: <i>DI*</i>.<br><br>The <i>Address Size</i> is the number of bits that determine an address; so the total number of words stored will be 2^<sup><i>Address Size</i></sup>.");
00041         
00042         m_data = 0;
00043         m_pCS = 0;
00044         m_pOE = 0;
00045         m_pWE = 0;
00046         m_wordSize = 0;
00047         m_addressSize = 0;
00048         
00049         createProperty( "wordSize", Variant::Type::Int );
00050         property("wordSize")->setCaption( i18n("Word Size") );
00051         property("wordSize")->setMinValue(1);
00052         property("wordSize")->setMaxValue(256);
00053         property("wordSize")->setValue(2);
00054         
00055         createProperty( "addressSize", Variant::Type::Int );
00056         property("addressSize")->setCaption( i18n("Address Size") );
00057         property("addressSize")->setMinValue(1);
00058         property("addressSize")->setMaxValue(32);
00059         property("addressSize")->setValue(4);
00060         
00061         m_data = createProperty( "data", Variant::Type::Raw )->value().asBitArray();
00062 }
00063 
00064 RAM::~RAM()
00065 {
00066 }
00067 
00068 
00069 void RAM::dataChanged()
00070 {
00071         m_wordSize = dataInt("wordSize");
00072         m_addressSize = dataInt("addressSize");
00073         
00074         int newSize = int( m_wordSize * std::pow( 2., m_addressSize ) );
00075         m_data.resize(newSize);
00076         
00077         initPins();
00078 }
00079 
00080 
00081 void RAM::inStateChanged( bool newState )
00082 {
00083         Q_UNUSED(newState);
00084         
00085         bool cs = m_pCS->isHigh();
00086         bool oe = m_pOE->isHigh();
00087         bool we = m_pWE->isHigh();
00088         
00089         if ( !cs || !oe )
00090         {
00091                 for ( int i = 0; i < m_wordSize; ++i )
00092                         m_dataOut[i]->setHigh(false);
00093         }
00094         
00095         if ( !cs || (!oe && !we) )
00096                 return;
00097         
00098         unsigned address = 0;
00099         for ( int i = 0; i < m_addressSize; ++i )
00100                 address += (m_address[i]->isHigh() ? 1 : 0) << i;
00101         
00102         if (we)
00103         {
00104                 for ( int i = 0; i < m_wordSize; ++i )
00105                         m_data[ m_wordSize * address + i ] = m_dataIn[i]->isHigh();
00106         }
00107         
00108         if (oe)
00109         {
00110                 for ( int i = 0; i < m_wordSize; ++i )
00111                         m_dataOut[i]->setHigh( m_data[ m_wordSize * address + i ] );
00112         }
00113 }
00114 
00115 
00116 void RAM::initPins()
00117 {
00118         int oldWordSize = m_dataIn.size();
00119         int oldAddressSize = m_address.size();
00120         
00121         int newWordSize = dataInt("wordSize");
00122         int newAddressSize = dataInt("addressSize");
00123         
00124         if ( newAddressSize == oldAddressSize &&
00125                         newWordSize == oldWordSize )
00126                 return;
00127         
00128         QStringList leftPins; // Pins on left of IC
00129         leftPins << "CS" << "OE" << "WE";
00130         for ( int i = 0; i < newAddressSize; ++i )
00131                 leftPins << QString("A%1").arg( QString::number(i) );
00132         
00133         QStringList rightPins; // Pins on right of IC
00134         for ( unsigned i = newWordSize; i > 0; --i )
00135                 rightPins << QString("DI%1").arg( QString::number(i-1) );
00136         for ( unsigned i = newWordSize; i > 0; --i )
00137                 rightPins << QString("DO%1").arg( QString::number(i-1) );
00138         
00139         // Make pin lists of consistent sizes
00140         for ( unsigned i = leftPins.size(); i < rightPins.size(); ++i )
00141                 leftPins.append("");
00142         for ( unsigned i = rightPins.size(); i < leftPins.size(); ++i )
00143                 rightPins.prepend("");
00144         
00145         QStringList pins = leftPins + rightPins;
00146         
00147         initDIPSymbol( pins, 72 );
00148         initDIP(pins);
00149         
00150         ECNode *node;
00151         
00152         if (!m_pCS)
00153         {
00154                 node =  ecNodeWithID("CS");
00155                 m_pCS = createLogicIn(node);
00156                 m_pCS->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) );
00157         }
00158         
00159         if (!m_pOE)
00160         {
00161                 node =  ecNodeWithID("OE");
00162                 m_pOE = createLogicIn(node);
00163                 m_pOE->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) );
00164         }
00165         
00166         if (!m_pWE)
00167         {
00168                 node =  ecNodeWithID("WE");
00169                 m_pWE = createLogicIn(node);
00170                 m_pWE->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) );
00171         }
00172         
00173         if ( newWordSize > oldWordSize )
00174         {
00175                 m_dataIn.resize(newWordSize);
00176                 m_dataOut.resize(newWordSize);
00177                 
00178                 for ( int i = oldWordSize; i < newWordSize; ++i )
00179                 {
00180                         node = ecNodeWithID( QString("DI%1").arg( QString::number(i) ) );
00181                         m_dataIn.insert( i, createLogicIn(node) );
00182                         m_dataIn[i]->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) ); 
00183                         
00184                         node = ecNodeWithID( QString("DO%1").arg( QString::number(i) ) );
00185                         m_dataOut.insert( i, createLogicOut(node, false) );
00186                 }
00187         }
00188         else if ( newWordSize < oldWordSize )
00189         {
00190                 for ( int i = newWordSize; i < oldWordSize; ++i )
00191                 {
00192                         QString id = QString("DO%1").arg( QString::number(i) );
00193                         removeDisplayText(id);
00194                         removeElement( m_dataIn[i], false );
00195                         removeNode(id);
00196                         
00197                         id = QString("DI%1").arg( QString::number(i) );
00198                         removeDisplayText(id);
00199                         removeElement( m_dataOut[i], false );
00200                         removeNode(id);
00201                 }
00202                 
00203                 m_dataIn.resize(newWordSize);
00204                 m_dataOut.resize(newWordSize);
00205         }
00206         
00207         if ( newAddressSize > oldAddressSize )
00208         {
00209                 m_address.resize(newAddressSize);
00210                 
00211                 for ( int i = oldAddressSize; i < newAddressSize; ++i )
00212                 {
00213                         node = ecNodeWithID( QString("A%1").arg( QString::number(i) ) );
00214                         m_address.insert( i, createLogicIn(node) );
00215                         m_address[i]->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) );
00216                 }
00217         }
00218         else if ( newAddressSize < oldAddressSize )
00219         {
00220                 for ( int i = newAddressSize; i < oldAddressSize; ++i )
00221                 {
00222                         QString id = QString("A%1").arg( QString::number(i) );
00223                         removeDisplayText(id);
00224                         removeElement( m_address[i], false );
00225                         removeNode(id);
00226                 }
00227                 
00228                 m_address.resize(newAddressSize);
00229         }
00230 }
00231 
00232 

Generated on Tue May 8 17:05:32 2007 for KTechLab by  doxygen 1.5.1