File indexing completed on 2024-05-05 05:46:08

0001 /***************************************************************************
0002  *   Copyright (C) 2005 by David Saxton                                    *
0003  *   david@bluehaze.org                                                    *
0004  *                                                                         *
0005  *   This program is free software; you can redistribute it and/or modify  *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  ***************************************************************************/
0010 
0011 #include "parallelportcomponent.h"
0012 #include "port.h"
0013 
0014 #include "ecnode.h"
0015 #include "itemdocument.h"
0016 #include "libraryitem.h"
0017 #include "pin.h"
0018 #include "resistance.h"
0019 
0020 #include <KLocalizedString>
0021 
0022 #include <QDebug>
0023 #include <QPainter>
0024 
0025 #include <cmath>
0026 
0027 void ParallelPortComponent_dataCallback(void *objV, bool state) {
0028     ParallelPortComponent *objT = static_cast<ParallelPortComponent*>(objV);
0029     objT->dataCallback(state);
0030 }
0031 void ParallelPortComponent_controlCallback(void *objV, bool state) {
0032     ParallelPortComponent *objT = static_cast<ParallelPortComponent*>(objV);
0033     objT->controlCallback(state);
0034 }
0035 
0036 Item *ParallelPortComponent::construct(ItemDocument *itemDocument, bool newItem, const char *id)
0037 {
0038     return new ParallelPortComponent(static_cast<ICNDocument *>(itemDocument), newItem, id);
0039 }
0040 
0041 LibraryItem *ParallelPortComponent::libraryItem()
0042 {
0043     return new LibraryItem(QStringList(QString("ec/parallel_port")), i18n("Parallel Port"), i18n("Connections"), "ic1.png", LibraryItem::lit_component, ParallelPortComponent::construct);
0044 }
0045 
0046 ParallelPortComponent::ParallelPortComponent(ICNDocument *icnDocument, bool newItem, const char *id)
0047     : Component(icnDocument, newItem, id ? id : "parallel_port")
0048 {
0049     m_name = i18n("Parallel Port");
0050 
0051     QPolygon pa(4);
0052     pa[0] = QPoint(-32, -112);
0053     pa[1] = QPoint(32, -104);
0054     pa[2] = QPoint(32, 104);
0055     pa[3] = QPoint(-32, 112);
0056     setItemPoints(pa);
0057 
0058     m_pParallelPort = new ParallelPort();
0059 
0060     for (unsigned i = 0; i < 24; ++i)
0061         m_pLogic[i] = nullptr;
0062 
0063     ECNode *pin = nullptr;
0064 
0065     // BEGIN Data register
0066     for (int i = 0; i < 8; ++i) {
0067         QString id = QString("D%1").arg(i);
0068         QString name = id;
0069 
0070         pin = createPin(-40, -80 + 16 * i, 0, id);
0071         addDisplayText(id, QRect(-28, -88 + 16 * i, 28, 16), name, true, Qt::AlignLeft | Qt::AlignVCenter);
0072 
0073         m_pLogic[i] = createLogicOut(pin, false);
0074         //m_pLogic[i]->setCallback(this, (CallbackPtr)(&ParallelPortComponent::dataCallback));
0075         m_pLogic[i]->setCallback2(ParallelPortComponent_dataCallback, this);
0076     }
0077     // END Data register
0078 
0079     // BEGIN Status register
0080     QString statusNames[] = {"ERR", "ON", "PE", "ACK", "BUSY"};
0081 
0082     // The statusIDs are referenced in the save file and must not change
0083     QString statusIDs[] = {"ERROR", "ONLINE", "PE", "ACK", "BUSY"};
0084 
0085     // Bits 0...2 in the Status register are not used
0086     for (int i = 3; i < 8; ++i) {
0087         QString id = statusIDs[i - 3];
0088         QString name = statusNames[i - 3];
0089 
0090         // Bit 3 (pin 15) doesn't not follow the same positioning pattern as
0091         // the other pins in the Status register.
0092         if (i == 3) {
0093             pin = createPin(40, -72, 180, id);
0094             addDisplayText(id, QRect(0, -80, 28, 16), name, true, Qt::AlignRight | Qt::AlignVCenter);
0095         } else {
0096             pin = createPin(-40, -16 + 16 * i, 0, id);
0097             addDisplayText(id, QRect(-28, -24 + 16 * i, 28, 16), name, true, Qt::AlignLeft | Qt::AlignVCenter);
0098         }
0099 
0100         m_pLogic[i + 8] = createLogicOut(pin, false);
0101     }
0102     // END Status register
0103 
0104     // BEGIN Control register
0105     QString controlNames[] = {"STR", "AUT", "INIT", "SEL"};
0106 
0107     // The controlIDs are referenced in the save file and must not change
0108     QString controlIDs[] = {"STROBE", "AUTO", "INIT", "SELECT"};
0109 
0110     // Bits 4..7 are not used (well; bit 5 is, but not as a pin)
0111     for (int i = 0; i < 4; ++i) {
0112         QString id = controlIDs[i];
0113         QString name = controlNames[i];
0114 
0115         if (i == 0) {
0116             pin = createPin(-40, -96, 0, id);
0117             addDisplayText(id, QRect(-28, -104, 28, 16), name, true, Qt::AlignLeft | Qt::AlignVCenter);
0118         } else if (i == 1) {
0119             pin = createPin(40, -88, 180, id);
0120             addDisplayText(id, QRect(0, -96, 28, 16), name, true, Qt::AlignRight | Qt::AlignVCenter);
0121         } else {
0122             pin = createPin(40, -88 + i * 16, 180, id);
0123             addDisplayText(id, QRect(0, -96 + i * 16, 28, 16), name, true, Qt::AlignRight | Qt::AlignVCenter);
0124         }
0125 
0126         m_pLogic[i + 16] = createLogicOut(pin, false);
0127         //m_pLogic[i + 16]->setCallback(this, (CallbackPtr)(&ParallelPortComponent::controlCallback));
0128         m_pLogic[i + 16]->setCallback2(ParallelPortComponent_controlCallback, this);
0129     }
0130     // END Control register
0131 
0132 #if 0
0133     // And make the rest of the pins ground
0134     for ( int i = 0; i < 8; ++i )
0135     {
0136         pin = createPin( 40, -24 + i*16, 180, QString("GND%1").arg( i ) );
0137         pin->pin()->setGroundType( Pin::gt_always );
0138     }
0139 #endif
0140 
0141     Variant *v = createProperty("port", Variant::Type::Combo);
0142     v->setAllowed(ParallelPort::ports());
0143     v->setCaption(i18n("Port"));
0144 }
0145 
0146 ParallelPortComponent::~ParallelPortComponent()
0147 {
0148     for (int i = 0; i < 24; i++) {
0149         if (m_pLogic[i]) {
0150 //             m_pLogic[i]->setCallback(nullptr, nullptr);
0151             m_pLogic[i]->setCallback2(nullptr, nullptr);
0152         }
0153     }
0154     delete m_pParallelPort;
0155 }
0156 
0157 void ParallelPortComponent::dataChanged()
0158 {
0159     initPort(dataString("port"));
0160 }
0161 
0162 void ParallelPortComponent::initPort(const QString &port)
0163 {
0164     if (port.isEmpty()) {
0165         m_pParallelPort->closePort();
0166         return;
0167     }
0168 
0169     if (!m_pParallelPort->openPort(port)) {
0170         p_itemDocument->canvas()->setMessage(i18n("Could not open port %1", port));
0171         return;
0172     }
0173 }
0174 
0175 void ParallelPortComponent::dataCallback(bool)
0176 {
0177     uchar value = 0;
0178     for (unsigned i = 0; i < 8; ++i)
0179         value |= m_pLogic[i + 0]->isHigh() ? 0 : (1 << i);
0180 
0181     m_pParallelPort->writeToData(value);
0182 }
0183 
0184 void ParallelPortComponent::controlCallback(bool)
0185 {
0186     uchar value = 0;
0187     for (unsigned i = 0; i < 4; ++i)
0188         value |= m_pLogic[i + 16]->isHigh() ? 0 : (1 << i);
0189 
0190     m_pParallelPort->writeToControl(value);
0191 }
0192 
0193 void ParallelPortComponent::stepNonLogic()
0194 {
0195     uchar status = m_pParallelPort->readFromRegister(ParallelPort::Status);
0196     // Bits 0...2 in the Status register are not used
0197     for (int i = 3; i < 8; ++i)
0198         m_pLogic[i + 8]->setHigh(status | (1 << i));
0199 }
0200 
0201 void ParallelPortComponent::drawShape(QPainter &p)
0202 {
0203     drawPortShape(p);
0204 }