/******************************************************************************* * Copyright (c) 2003-2005, 2013 Till Zoppke. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * * Contributors: * Till Zoppke - initial API and implementation ******************************************************************************/ /* * Created on 28.05.2004 */ package eniac.data.model.unit; import java.util.Observable; import eniac.data.PulseInteractor; import eniac.data.model.Connector; import eniac.data.model.CyclingLights; import eniac.data.model.EData; import eniac.data.model.parent.ConstantTransmittionLights; import eniac.data.model.parent.ProgramConnectorPair; import eniac.data.model.sw.Switch; import eniac.data.model.sw.SwitchAndFlag; import eniac.data.type.EType; import eniac.simulation.EEvent; import eniac.simulation.EEventListener; /** * @author zoppke */ public class ConstantTransmitter1 extends Unit implements EEventListener, PulseInteractor { private static final int[] SEND_1P = {1, 3, 5, 7, 9}; private static final int[] SEND_2P = {2, 3, 4, 5, 6, 7, 8, 9}; private static final int[] SEND_2AP = {4, 5, 8, 9}; private static final int[] SEND_4P = {6, 7, 8, 9}; private boolean _transmitting; private long _startTime; private SwitchAndFlag _program; public void init() { super.init(); // init as eventlinstener CyclingLights lights = getConfiguration().getCyclingLights(); lights.addEEventListener(this, EEvent.CPP); lights.addEEventListener(this, EEvent.PULSE_1P); lights.addEEventListener(this, EEvent.PULSE_2P); lights.addEEventListener(this, EEvent.PULSE_2AP); lights.addEEventListener(this, EEvent.PULSE_4P); lights.addEEventListener(this, EEvent.PULSE_1AP); // observe our switches and toggles in order to notify the lights EData[] kinder = getGarten().getAllKinder(); for (int i = 0; i < kinder.length; ++i) { if (kinder[i].getType() != EType.PROGRAM_CONNECTOR_PAIR) { kinder[i].addObserver(this); } } } /** * @return @see eniac.data.model.unit.Unit#getHeaters() */ public Switch getHeaters() { return (Switch) getGarten().getKind(EType.HEATERS_01, 0); } public boolean isTransmitting() { return _transmitting; } /** * @param o * @param arg * @see java.util.Observer#update(java.util.Observable, java.lang.Object) */ public void update(Observable o, Object args) { if (o instanceof Switch) { Switch sw = (Switch) o; if (sw.getType() == EType.HEATERS_01) { boolean power = sw.isValue(); if (!power) { // power switched of. delete program transmittion data _program = null; _startTime = -1; _transmitting = false; } } // notify constantTransmittionLights to repaint its number setChanged(); notifyObservers(ConstantTransmittionLights.PAINT_LIGHTS); } } public long getNumber() { // if no program, return 0 if (_program == null) { return 0; } // if number is reiceived from ibm card reader, return 0 if (_program.getType() != EType.CONSTANT_SELECTOR_SWITCH_JK) { // TODO: implement ibm card reader. return 0; } // constant transmitter panel 2 ConstantTransmitter2 trans2 = (ConstantTransmitter2) getConfiguration().getGarten().getKind( EType.CONSTANT_TRANSMITTER_2_UNIT, 0); // if trans2 has no power, we cannot get a number and return 0 if (!trans2.hasPower()) { return 0; } // getting number long number = 0; int index = _program.isFlag() ? 10 : 0; if (_program.getValue() <= 1) { // left for (int i = 0; i < 5; ++i) { Switch sw = (Switch) trans2.getGarten().getKind(EType.CONSTANT_SWITCH, index + i); number *= 10; number += sw.getValue(); } } if (_program.getValue() >= 1) { // right for (int i = 5; i < 10; ++i) { Switch sw = (Switch) trans2.getGarten().getKind(EType.CONSTANT_SWITCH, index + i); number *= 10; number += sw.getValue(); } } return number; } public boolean isNegative() { // if no program, we are not negative if (_program == null) { return false; } // if constant selector doesn't point to the transmittor 2, // return as nonegative in order to not send the complement of 0. if (!(_program.getType() == EType.CONSTANT_SELECTOR_SWITCH_JK)) { return false; } // get transition partner Switch sw; ConstantTransmitter2 trans2 = (ConstantTransmitter2) getConfiguration().getGarten().getKind( EType.CONSTANT_TRANSMITTER_2_UNIT, 0); // no power means not negative if (!trans2.hasPower()) { return false; } // determine sign if (_program.getValue() <= 1) { if (!_program.isFlag()) { sw = (Switch) trans2.getGarten().getKind(EType.CONSTANT_SIGN_TOGGLE_JL, 0); } else { sw = (Switch) trans2.getGarten().getKind(EType.CONSTANT_SIGN_TOGGLE_KL, 0); } } else { if (!_program.isFlag()) { sw = (Switch) trans2.getGarten().getKind(EType.CONSTANT_SIGN_TOGGLE_JR, 0); } else { sw = (Switch) trans2.getGarten().getKind(EType.CONSTANT_SIGN_TOGGLE_KR, 0); } } return !sw.isValue(); } /** * @param e * @see eniac.simulation.EEventListener#process(eniac.simulation.EEvent) */ public void process(EEvent e) { switch (e.type) { case EEvent.CPP : if (_transmitting && hasPower() && _startTime < e.time) { _transmitting = false; sendProgram(e.time, this); setChanged(); notifyObservers(ConstantTransmittionLights.PAINT_LIGHTS); } break; case EEvent.PULSE_1P : maybeSendBy(SEND_1P, e.time); break; case EEvent.PULSE_2P : maybeSendBy(SEND_2P, e.time); break; case EEvent.PULSE_2AP : maybeSendBy(SEND_2AP, e.time); break; case EEvent.PULSE_4P : maybeSendBy(SEND_4P, e.time); break; case EEvent.PULSE_1AP : if (_transmitting && hasPower() && isNegative()) { sendDigit(e.time, 1, this); } } } private static long toComplement(long number) { return 9999999999L - number; } private void maybeSendBy(int[] ciphers, long time) { // if we are not transmitting, don't send. if (!_transmitting || !hasPower()) { return; } // get number long number = getNumber(); boolean negative = isNegative(); if (negative) { number = toComplement(number); } // compute pulse long factor = 1; long pulse = 0; while (number > 0) { int cipher = (int) (number % 10); for (int i = 0; i < ciphers.length; ++i) { if (ciphers[i] == cipher) { pulse += factor; } } factor *= 10; number /= 10; } if (negative) { pulse += factor; } // send pulse sendDigit(time, pulse, this); } // ========================= pulseinteractor methods // ======================== public boolean canReceiveProgram(long time, PulseInteractor source) { return hasPower(); } public void receiveProgram(long time, PulseInteractor source) { // send program pulse, if a program ended just now. if (_transmitting) { sendProgram(time, this); } _transmitting = true; _startTime = time; int index = ((EData) source).getIndex(); int modIndex = index % 10; int row = index / 10; if (modIndex < 2) { _program = (SwitchAndFlag) getGarten().getKind(EType.CONSTANT_SELECTOR_SWITCH_AB, row * 2 + modIndex); } else if (modIndex < 4) { _program = (SwitchAndFlag) getGarten().getKind(EType.CONSTANT_SELECTOR_SWITCH_CD, row * 2 + modIndex - 2); } else if (modIndex < 6) { _program = (SwitchAndFlag) getGarten().getKind(EType.CONSTANT_SELECTOR_SWITCH_EF, row * 2 + modIndex - 4); } else if (modIndex < 8) { _program = (SwitchAndFlag) getGarten().getKind(EType.CONSTANT_SELECTOR_SWITCH_GH, row * 2 + modIndex - 6); } else { _program = (SwitchAndFlag) getGarten().getKind(EType.CONSTANT_SELECTOR_SWITCH_JK, row * 2 + modIndex - 8); } setChanged(); notifyObservers(ConstantTransmittionLights.PAINT_LIGHTS); } public void sendProgram(long time, PulseInteractor source) { int index = _program.getIndex(); if (index > 2) { index += 8; } else if (index > 4) { index += 16; } if (_program.getType() == EType.CONSTANT_SELECTOR_SWITCH_CD) { index += 2; } else if (_program.getType() == EType.CONSTANT_SELECTOR_SWITCH_EF) { index += 4; } else if (_program.getType() == EType.CONSTANT_SELECTOR_SWITCH_GH) { index += 6; } else if (_program.getType() == EType.CONSTANT_SELECTOR_SWITCH_JK) { index += 8; } ProgramConnectorPair pair = (ProgramConnectorPair) getGarten().getKind(EType.PROGRAM_CONNECTOR_PAIR, index); pair.sendProgram(time, this); } /** * @param time * @param source * @return @see eniac.data.PulseInteractor#canReceiveDigit(long, * eniac.data.PulseInteractor) */ public boolean canReceiveDigit(long time, PulseInteractor source) { return false; } public void receiveDigit(long time, long value, PulseInteractor source) { // cannot receive digit, so nothing to do. } public void sendDigit(long time, long value, PulseInteractor source) { Connector con = (Connector) getGarten().getKind(EType.DIGIT_CONNECTOR_CROSS, 0); con.sendDigit(time, value, this); } }