001package jmri.jmrix.grapevine; 002 003import jmri.implementation.AbstractLight; 004import org.slf4j.Logger; 005import org.slf4j.LoggerFactory; 006 007/** 008 * Implementation of the Light interface using Grapevine signal ports. 009 * <p> 010 * The "On" state results in sending a "green" setting to the hardware port; 011 * the "Off" state results in sending a "dark" setting to the hardware. 012 * 013 * @author Dave Duchamp Copyright (C) 2004 014 * @author Bob Jacobsen Copyright (C) 2006, 2007, 2008 015 */ 016public class SerialLight extends AbstractLight { 017 018 private GrapevineSystemConnectionMemo memo = null; 019 020 /** 021 * Create a Light object, with only system name. 022 * 023 * @param systemName system name including prefix, previously validated in SerialLightManager 024 * @param _memo the associated SystemConnectionMemo 025 */ 026 public SerialLight(String systemName, GrapevineSystemConnectionMemo _memo) { 027 super(systemName); 028 memo = _memo; 029 // Initialize the Light 030 initializeLight(systemName); 031 } 032 033 /** 034 * Create a Light object, with both system and user names. 035 * 036 * @param systemName system name including prefix, previously validated in SerialLightManager 037 * @param userName free form name 038 * @param _memo the associated SystemConnectionMemo 039 */ 040 public SerialLight(String systemName, String userName, GrapevineSystemConnectionMemo _memo) { 041 super(systemName, userName); 042 memo = _memo; 043 initializeLight(systemName); 044 } 045 046 /** 047 * Set up system dependent instance variables and set system independent 048 * instance variables to default values. 049 * <p> 050 * Note: most instance variables are in AbstractLight.java 051 */ 052 private void initializeLight(String systemName) { 053 // Extract the Bit from the name 054 int num = SerialAddress.getBitFromSystemName(systemName, memo.getSystemPrefix()); // bit one is address zero 055 // num is 101-124, 201-224, 301-324, 401-424 056 output = (num % 100) - 1; // 0-23 057 bank = (num / 100) - 1; // 0 - 3 058 059 // Set initial state to OFF internally and on layout 060 setState(OFF); 061 } 062 063 /** 064 * System dependent instance variables 065 */ 066 int output; // output connector number, 0-23 067 int bank; // bank number, 0-3 068 069 /** 070 * Set the current state of this Light. This routine requests the hardware to 071 * change. If this is really a change in state of this bit (tested in 072 * SerialNode), a Transmit packet will be sent before this Node is next 073 * polled. 074 */ 075 @Override 076 protected void doNewState(int oldState, int newState) { 077 SerialNode mNode = SerialAddress.getNodeFromSystemName(getSystemName(), memo.getTrafficController()); 078 if (mNode != null) { 079 if (newState == ON) { 080 sendMessage(true); 081 } else if (newState == OFF) { 082 sendMessage(false); 083 } else { 084 log.warn("illegal state requested for Light: {}", getSystemName()); 085 } 086 } 087 } 088 089 protected void sendMessage(boolean on) { 090 SerialNode tNode = SerialAddress.getNodeFromSystemName(getSystemName(), memo.getTrafficController()); 091 if (tNode == null) { 092 // node does not exist, ignore call 093 log.error("Can't find node for {}, command ignored", getSystemName()); 094 return; 095 } 096 boolean high = (output >= 12); 097 int tOut = output; 098 if (high) { 099 tOut = output - 12; 100 } 101 if ((bank < 0) || (bank > 4)) { 102 log.error("invalid bank {} for Light {}", bank, getSystemName()); 103 bank = 0; 104 } 105 SerialMessage m = new SerialMessage(high ? 8 : 4); 106 int i = 0; 107 if (high) { 108 m.setElement(i++, tNode.getNodeAddress() | 0x80); // address 1 109 m.setElement(i++, 122); // shift command 110 m.setElement(i++, tNode.getNodeAddress() | 0x80); // address 2 111 m.setElement(i++, 0x10); // bank 1 112 m.setParity(i - 4); 113 } 114 m.setElement(i++, tNode.getNodeAddress() | 0x80); // address 1 115 m.setElement(i++, (tOut << 3) | (on ? 0 : 4)); // on is green, off is dark 116 m.setElement(i++, tNode.getNodeAddress() | 0x80); // address 2 117 m.setElement(i++, bank << 4); // bank is most significant bits 118 m.setParity(i - 4); 119 memo.getTrafficController().sendSerialMessage(m, null); 120 } 121 122 private final static Logger log = LoggerFactory.getLogger(SerialLight.class); 123 124}