1 #*****************************************************************************
5 # Object Name : $RCSfile$
6 # Revision : $Revision$
9 # Created By : Robert Heller
10 # Created : Mon Jul 13 12:42:15 2015
11 # Last Modified : <150820.1252>
19 #*****************************************************************************
21 # Copyright (C) 2015 Robert Heller D/B/A Deepwoods Software
23 # Wendell, MA 01379-9728
25 # This program is free software; you can redistribute it and/or modify
26 # it under the terms of the GNU General Public License as published by
27 # the Free Software Foundation; either version 2 of the License, or
28 # (at your option) any later version.
30 # This program is distributed in the hope that it will be useful,
31 # but WITHOUT ANY WARRANTY; without even the implied warranty of
32 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 # GNU General Public License for more details.
35 # You should have received a copy of the GNU General Public License
36 # along with this program; if not, write to the Free Software
37 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
41 #*****************************************************************************
43 package require CmriSupport;# require the Cmri Support
package
44 package require snit;# require the SNIT OO framework
48 # @brief Block occupation detection using Circuits4Tracks Quad Occupancy Detectors and Azatrax SR4s
50 # @image html C4TSMINI_Block-thumb.png
51 # @image latex C4TSMINI_Block.png "Block detection with a Circuits4Tracks Quad Occupancy Detector and a Chubb SMINI card" width=5in
53 # Above is a simple diagram for using Circuits4Tracks Quad Occupancy
54 # Detectors for block occupation detection. A Circuits4Tracks Quad
55 # Occupancy board has four current sensors. One wires one side of the
56 # track power (either DCC or DC) to a common rail and the other side
57 # through the Circuits4Tracks Quad Occupancy Detector to rails isolated
58 # with gaps (possibly with insulating rail joiners). This code uses
59 # a Chubb SMINI board to connect a Circuits4Tracks Quad Occupancy Detectors
60 # to the computer via a serial interface.
65 # Four blocks in a loop:
68 # # Connect to the cmribus through a USB RS485 adapter at /dev/ttyUSB0
69 # CmriSupport::CmriNode openport /dev/ttyUSB0
70 # # SMINI board at address 0
71 # CmriSupport::CmriNode SMINI0 -type SMINI -address 0
72 # # The first four bits of the first port are wired to the Circuits4Tracks
73 # # Quad Occupancy Detector
74 # C4TSR4_Block block1 -nodeobj SMINI0 -port 0 -bit 0 -signalobj signal1
75 # C4TSR4_Block block2 -nodeobj SMINI0 -port 0 -bit 1 -signalobj signal2 -previousblock block1
76 # C4TSR4_Block block3 -nodeobj SMINI0 -port 0 -bit 2 -signalobj signal3 -previousblock block2
77 # C4TSR4_Block block4 -nodeobj SMINI0 -port 0 -bit 3 -signalobj signal4 -previousblock block3
78 # block1 configure -previousblock block4
80 # A Schematic of the layout would look like this:
81 # @image html 4circleblocks.png
82 # @image latex 4circleblocks.png "Four block circle" width=3in
83 # For the track work elements use "blockN occupiedp" for the track work
84 # elements' occupied command:
85 # eg Block1 would have 'block1 occupiedp' as its occupied command, that is
86 # its edit window would look like:
87 # @image html EditingBlock1.png
88 # @image latex EditingBlock1.png "Editing Block1" width=5in
89 # The other three blocks would be similar.
92 # Then in the Main Loop, you would have:
95 # MainWindow ctcpanel invoke Block1
96 # MainWindow ctcpanel invoke Block2
97 # MainWindow ctcpanel invoke Block3
98 # MainWindow ctcpanel invoke Block4
99 # update;# Update display
103 # @author Robert Heller \<heller\@deepsoft.com\>
105 option -nodeobj -readonly yes -
default {} -type ::CmriSupport::CmriNode
106 option -port -readonly yes -
default 0 -type {snit::integer -min 0}
107 option -bit -readonly yes -
default 0 -type {snit::integer -min 0 -max 7}
108 option -forwardsignalobj -readonly yes -
default {}
109 option -reversesignalobj -readonly yes -
default {}
112 option -direction -type {snit::enum -values {forward reverse}} -
default forward
113 typemethod validate {
object} {
114 ## Type validating code
115 # Raises an error if object is not either the empty string or a C4TSMINI_Block
119 return $object;# Empty or
null objects are OK
120 } elseif {[
catch {$object info type} itstype]} {
121 error
"$object is not a $type";#
object is not a SNIT type
122 } elseif {$itstype eq $type} {
123 return $object;# Object is of our type (Block)
125 error
"$object is not a $type";#
object is something
else
129 ## @privatesection SMINI node object
130 component forwardsignal
131 ## Signal object (typically a three color, one head block signal
132 component reversesignal
133 ## Signal object (typically a three color, one head block signal
134 variable isoccupied no
135 ## Saved occupation state.
139 ## @publicsection @brief Constructor: initialize the block object.
141 # Create a lowlevel node object and install it as a component.
142 # Install the blocks signal (created elsewhere).
144 # @param name Name of the block object
145 # @param ... Options:
146 # @arg -nodeobj This is the Cmri node for this block. This is a
147 # CmriNode object, defined in the Control Support package. This option
148 # is read-only and must be set at creation time.
149 # @arg -port The input port on the Cmri node. This is an integer
150 # greater or equal to 0. This option is read-only and can only be
151 # set at creation time. The default is 0.
152 # @arg -bit This defines the input bit on the input port for this
153 # block. This is an integer from 0 to 7 inclusive and is read-only
154 # and can only be set at creation time. The default is 0.
155 # @arg -forwardsignalobj This block's forward signal. This option is
156 # read-only and can only be set at creation time. The default is the
158 # @arg -reversesignalobj This block's reverse signal. This option is
159 # read-only and can only be set at creation time. The default is the
161 # @arg -previousblock Previous block (next block in reverse) -- used
162 # for 'propagating' signal aspects and must be a C4TSMINI_Block type
163 # object. The default is the empty string.
164 # @arg -nextblock Next block (previous block in reverse) -- used for
165 # 'propagating' signal aspects and must be a C4TSMINI_Block type
166 # object. The default is the empty string.
167 # @arg -direction Current running direction, either the word forward
168 # or reverse. The default is forward.
171 ## Process any options
172 $self configurelist $args
174 set node [$self cget -nodeobj]
176 error
"The -nodeobj is required!"
178 # Install the signal component.
179 set forwardsignal [$self cget -forwardsignalobj]
180 set reversesignal [$self cget -reversesignalobj]
182 method occupiedp {} {
183 ## The occupiedp method returns yes or no (true or false) indicating
186 # First read the current sensor state.
187 set inputs [$node inputs]
188 set port [lindex $inputs [$self cget -port]]
189 set bit [expr {($port >> [$self cget -bit]) & 0x01}]
190 # The outputs of the OD are active negative, so we need to invert the
192 set bit [expr {(~$bit) & 0x01}]
195 # Already entered the block.
198 # Just entered the block
205 # Just left the block
210 # Block still unoccupied
215 method _entering {} {
216 ## @privatesection Method for entering a block.
218 if {[$self cget -direction] eq
"forward"} {
219 # Set a red (stop and proceed) aspect.
220 if {$forwardsignal ne
""} {$forwardsignal setaspect red}
221 # Now propagate the signal to the previous block (if any)
222 if {$options(-previousblock) ne {}} {
223 # Set a yellow (approach) aspect on the previous block.
224 $options(-previousblock) propagate yellow $self -direction forward
227 if {$reversesignal ne
""} {$reversesignal setaspect red}
228 # Now propagate the signal to the previous block (if any)
229 if {$options(-nextblock) ne {}} {
230 # Set a yellow (approach) aspect on the previous block.
231 $options(-nextblock) propagate yellow $self -direction reverse
236 ## Method for exiting a block.
238 # Nothing here -- could be used for any sort of exit handling.
240 method propagate {aspect from args} {
241 ## @publicsection Method used to propagate distant signal states back down the line.
242 # @param aspect The signal aspect that is being propagated.
243 # @param from The propagating block (not used).
244 # @param ... Options:
245 # @arg -direction The direction of the propagation.
247 ## First process any options
248 $self configurelist $args
249 ## If we are already occupiedp, don't do anything else.
250 if {[$self occupiedp]} {
return}
251 if {[$self cget -direction] eq
"forward"} {
253 if {$forwardsignal ne
""} {$forwardsignal setaspect $aspect}
254 # If the new aspect was yellow, propagate a green (clear) signal
255 if {$aspect eq
"yellow"} {
256 if {$options(-previousblock) ne {}} {
257 $options(-previousblock) propagate green $self -direction forward
262 if {$reversesignal ne
""} {$reversesignal setaspect $aspect}
263 # If the new aspect was yellow, propagate a green (clear) signal
264 if {$aspect eq
"yellow"} {
265 if {$options(-nextblock) ne {}} {
266 $options(-nextblock) propagate green $self -direction reverse
273 package provide C4TSMINI_Block 1.0