001package jmri.jmrix.loconet.locoio; 002 003import jmri.jmrix.loconet.LnTrafficController; 004import jmri.jmrix.loconet.LocoNetMessage; 005 006/** 007 * Manage the communication to/from a LocoIO board. 008 * 009 * Uses the LOCONETSV1MODE programming mode. 010 * 011 * Uses LnProgrammer LOCOIO_PEER_CODE_SV_VER1 message format, comparable to DecoderPro LOCONETSV1MODE 012 * Currently (4.11.6) this tool does not work with the HDL LocoIO rev 3 and newer boards, 013 * with risk of breaking the stored config. 014 * 015 * @see jmri.jmrix.loconet.LnOpsModeProgrammer#message(LocoNetMessage) 016 * 017 * Programming SV's 018 * <p> 019 * The SV's in a LocoIO hardware module can be programmed using LocoNet OPC_PEER_XFER messages. 020 * <p> 021 * Commands for setting SV's: 022 * <p> 023 * PC to LocoIO LocoNet message (OPC_PEER_XFER) 024 * <pre><code> 025 * Code LOCOIO_SV_READ _or_ LOCOIO_SV_WRITE ---- 026 * 0xE5 OPC_PEER_XFER 027 * OPC_PEER_XFER 0x10 Message length 028 * SRCL 0x50 0x50 // low address byte of LocoBuffer 029 * DSTL LocoIO low address 030 * DSTH 0x01 0x01 // Fixed LocoIO high address PXCT1 031 * D1 LOCOIO_SV_READ _or_ LOCOIO_SV_WRITE // Read/Write command 032 * D2 SV number 033 * D3 0x00 0x00 034 * D4 0x00 Data to Write PXCT2 035 * D5 LocoIO Sub-address 036 * D6 0x00 0x00 037 * D7 0x00 0x00 038 * D8 0x00 0x00 039 * CHK Checksum Checksum 040 * </code></pre> 041 * 042 * LocoIO to PC reply message (OPC_PEER_XFER) 043 * <pre><code> 044 * Code LOCOIO_SV_READ _or_ LOCOIO_SV_WRITE ---- 045 * 0xE5 OPC_PEER_XFER 046 * 0x10 Message length 047 * SRCL LocoIO low address 048 * DSTL 0x50 0x50 // low address byte of LocoBuffer 049 * DSTH 0x01 0x01 // high address byte of LocoBuffer 050 * PXCT1 MSB LocoIO version // High order bit of LocoIO version 051 * D1 LOCOIO_SV_READ _or_ LOCOIO_SV_WRITE // Original Command 052 * D2 SV number requested 053 * D3 LSBs LocoIO version // Lower 7 bits of LocoIO version 054 * D4 0x00 0x00 PXCT2 MSB Requested Data // High order bit of requested data 055 * D5 LocoIO Sub-address 056 * D6 Requested Data 0x00 057 * D7 Requested Data + 1 0x00 058 * D8 Requested Data + 2 Written Data 059 * CHK Checksum Checksum 060 * </code></pre> 061 * 062 * @author John Plocher 2006, 2007 063 */ 064public class LocoIO { 065 066 public static final int LOCOIO_SV_WRITE = 0x01; 067 public static final int LOCOIO_SV_READ = 0x02; 068 public static final int LOCOIO_BROADCAST_ADDRESS = 0x1000; // LocoIO broadcast 069 070 public static final int LOCOIO_PEER_CODE_7BIT_ADDRS = 0x00; 071 public static final int LOCOIO_PEER_CODE_ANSI_TEXT = 0x00; // not used 072 public static final int LOCOIO_PEER_CODE_SV_VER1 = 0x08; 073 public static final int LOCOIO_PEER_CODE_SV_VER2 = 0x09; // not used 074 075 /** 076 * Create a new instance of LocoIO. 077 */ 078 public LocoIO() { 079 } 080 081 public static int SENSOR_ADR(int a1, int a2) { 082 return (((a2 & 0x0f) * 128) + (a1 & 0x7f)) + 1; 083 } 084 085 /** 086 * Compose a LocoNet message from the given ingredients for reading 087 * the value of one specific SV from a given LocoIO. 088 * 089 * @param locoIOAddress base address of the LocoIO board to read from 090 * @param locoIOSubAddress subAddress of the LocoIO board 091 * @param cv the SV index to query 092 * @return complete message to send 093 */ 094 public static LocoNetMessage readCV(int locoIOAddress, int locoIOSubAddress, int cv) { 095 int[] contents = {LOCOIO_SV_READ, cv, 0, 0, locoIOSubAddress, 0, 0, 0}; 096 097 return LocoNetMessage.makePeerXfr( 098 0x1050, // B'cast locobuffer address 099 locoIOAddress, 100 contents, // CV and SubAddr to read 101 LOCOIO_PEER_CODE_SV_VER1 102 ); 103 } 104 105 /** 106 * Compose a LocoNet message from the given ingredients for reading 107 * the value of one specific SV from a given LocoIO. 108 * 109 * @param locoIOAddress base address of the LocoIO board to read from 110 * @param locoIOSubAddress subAddress of the LocoIO board 111 * @param cv the SV index to change 112 * @param data the new value to store in the board's SV 113 * @return complete message to send 114 */ 115 public static LocoNetMessage writeCV(int locoIOAddress, int locoIOSubAddress, int cv, int data) { 116 int[] contents = {LOCOIO_SV_WRITE, cv, 0, data, locoIOSubAddress, 0, 0, 0}; 117 118 return LocoNetMessage.makePeerXfr( 119 0x1050, // B'cast locobuffer address 120 locoIOAddress, 121 contents, // CV and SubAddr to read 122 LOCOIO_PEER_CODE_SV_VER1 123 ); 124 } 125 126 /** 127 * Compose and send a message out onto LocoNet changing the LocoIO hardware board 128 * address of all connected LocoIO boards. 129 * <p> 130 * User is warned that this is a broadcast type operation. 131 * 132 * @param address the new base address of the LocoIO board to change 133 * @param subAddress the new subAddress of the board 134 * @param ln the TrafficController to use for sending the message 135 */ 136 public static void programLocoIOAddress(int address, int subAddress, LnTrafficController ln) { 137 LocoNetMessage msg; 138 msg = LocoIO.writeCV(0x0100, 0, 1, address & 0xFF); 139 ln.sendLocoNetMessage(msg); 140 if (subAddress != 0) { 141 msg = LocoIO.writeCV(0x0100, 0, 2, subAddress); 142 ln.sendLocoNetMessage(msg); 143 } 144 } 145 146 /** 147 * Send out a probe of all connected LocoIO units on a given LocoNet connection. 148 * 149 * @param ln the TrafficController to use for sending the message 150 */ 151 public static void probeLocoIOs(LnTrafficController ln) { 152 LocoNetMessage msg; 153 msg = LocoIO.readCV(0x0100, 0, 2); 154 ln.sendLocoNetMessage(msg); 155 } 156 157}