001package jmri.jmrix.can.adapters.lawicell; 002 003import jmri.jmrix.AbstractMRListener; 004import jmri.jmrix.AbstractMRMessage; 005import jmri.jmrix.AbstractMRReply; 006import jmri.jmrix.can.CanListener; 007import jmri.jmrix.can.CanMessage; 008import jmri.jmrix.can.CanReply; 009import org.slf4j.Logger; 010import org.slf4j.LoggerFactory; 011 012/** 013 * Traffic controller for the LAWICELL protocol. 014 * <p> 015 * Lawicell adapters use messages transmitted as an ASCII string of up to 24 016 * characters of the form: ;ShhhhNd0d1d2d3d4d5d6d7: The S indicates a standard 017 * CAN frame hhhh is the two byte header N or R indicates a normal or remote 018 * frame d0 - d7 are the (up to) 8 data bytes 019 * 020 * @author Andrew Crosland Copyright (C) 2008 021 * @author Bob Jacobsen Copyright (C) 2008 022 */ 023public class LawicellTrafficController extends jmri.jmrix.can.TrafficController { 024 025 public LawicellTrafficController() { 026 super(); 027 } 028 029 /** 030 * Forward a CanMessage to all registered CanInterface listeners. 031 */ 032 @Override 033 protected void forwardMessage(AbstractMRListener client, AbstractMRMessage m) { 034 ((CanListener) client).message((CanMessage) m); 035 } 036 037 /** 038 * Forward a CanReply to all registered CanInterface listeners. 039 * {@inheritDoc} 040 */ 041 @Override 042 protected void forwardReply(AbstractMRListener client, AbstractMRReply r) { 043 ((CanListener) client).reply((CanReply) r); 044 } 045 046 // Current state 047 public static final int NORMAL = 0; 048 public static final int BOOTMODE = 1; 049 050 public int getgcState() { 051 return gcState; 052 } 053 054 public void setgcState(int s) { 055 gcState = s; 056 log.debug("Setting gcState {}",s); 057 } 058 059 public boolean isBootMode() { 060 return gcState == BOOTMODE; 061 } 062 063 /** 064 * Forward a preformatted message to the actual interface. 065 * {@inheritDoc} 066 */ 067 @Override 068 public void sendCanMessage(CanMessage m, CanListener reply) { 069 log.debug("TrafficController sendCanMessage() {}", m.toString()); 070 sendMessage(m, reply); 071 } 072 073 /** 074 * Forward a preformatted reply to the actual interface. 075 * {@inheritDoc} 076 */ 077 @Override 078 public void sendCanReply(CanReply r, CanListener reply) { 079 log.debug("TrafficController sendCanReply() {}", r.toString()); 080 notifyReply(r, reply); 081 } 082 083 /** 084 * Add trailer to the outgoing byte stream. 085 * 086 * @param msg The output byte stream 087 * @param offset the first byte not yet used 088 */ 089 @Override 090 protected void addTrailerToOutput(byte[] msg, int offset, AbstractMRMessage m) { 091 } 092 093 /** 094 * Determine how much many bytes the entire message will take, including 095 * space for header and trailer 096 * 097 * @param m The message to be sent 098 * @return Number of bytes 099 */ 100 @Override 101 protected int lengthOfByteStream(AbstractMRMessage m) { 102 return m.getNumDataElements(); 103 } 104 105 // New message for hardware protocol 106 @Override 107 protected AbstractMRMessage newMessage() { 108 log.debug("New Message created"); 109 Message msg = new Message(); 110 return msg; 111 } 112 113 /** 114 * Make a CanReply from a Lawicell-specific reply. 115 * {@inheritDoc} 116 */ 117 @Override 118 public CanReply decodeFromHardware(AbstractMRReply m) { 119 log.debug("Decoding from hardware: {}", m ); 120 CanReply ret = new CanReply(); 121 try { 122 Reply gc = (Reply) m; 123 ret = gc.createReply(); 124 log.debug("Decoded {} as {} ",gc,ret); 125 } catch (java.lang.ClassCastException cce){ 126 log.error("Unable to cast Reply {}",m); 127 } 128 return ret; 129 } 130 131 /** 132 * Encode a CanMessage into Lawicell format for the hardware. 133 * {@inheritDoc} 134 */ 135 @Override 136 public AbstractMRMessage encodeForHardware(CanMessage m) { 137 Message ret = new Message(m); 138 log.debug("Encoding for hardware as {}",ret); 139 return ret; 140 } 141 142 // New reply from hardware 143 @Override 144 protected AbstractMRReply newReply() { 145 log.debug("New Reply created"); 146 Reply reply = new Reply(); 147 return reply; 148 } 149 150 /** 151 * Normal Lawicell replies will end with CR; errors are BELL. 152 * {@inheritDoc} 153 */ 154 @Override 155 protected boolean endOfMessage(AbstractMRReply r) { 156 return endNormalReply(r); 157 } 158 159 boolean endNormalReply(AbstractMRReply r) { 160 // Detect if the reply buffer ends with bell or cr 161 int num = r.getNumDataElements() - 1; 162 if (r.getElement(num) == 0x0D) { 163 return true; 164 } 165 return r.getElement(num) == 0x07; 166 } 167 168 private int gcState; 169 170 private final static Logger log = LoggerFactory.getLogger(LawicellTrafficController.class); 171}