Model Railroad System  2.2.1
C4TSR4_Block.tcl
1 #****************************************************************************
2 #
3 # System :
4 # Module :
5 # Object Name : $RCSfile$
6 # Revision : $Revision$
7 # Date : $Date$
8 # Author : $Author$
9 # Created By : Robert Heller
10 # Created : Mon Jul 13 10:23:04 2015
11 # Last Modified : <150717.1523>
12 #
13 # Description
14 #
15 # Notes
16 #
17 # History
18 #
19 #****************************************************************************
20 #
21 # Copyright (C) 2015 Robert Heller D/B/A Deepwoods Software
22 # 51 Locke Hill Road
23 # Wendell, MA 01379-9728
24 #
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.
29 #
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.
34 #
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.
38 #
39 #
40 #
41 #****************************************************************************
42 
43 package require Azatrax;# require the Azatrax package
44 package require snit;# require the SNIT OO framework
45 
46 
47 snit::type C4TSR4_Block {
48  ##
49  # @brief Block occupation detection using Circuits4Tracks Quad Occupancy Detectors and Azatrax SR4s
50  #
51  # @image html C4TSR4_Block-thumb.png
52  # @image latex C4TSR4_Block.png "Block detection with a Circuits4Tracks Quad Occupancy Detector and a SR4" width=5in
53  #
54  # Above is a simple diagram for using Circuits4Tracks Quad Occupancy
55  # Detectors for block occupation detection. A Circuits4Tracks Quad
56  # Occupancy board has four current sensors. One wires one side of the
57  # track power (either DCC or DC) to a common rail and the other side
58  # through the Circuits4Tracks Quad Occupancy Detector to rails isolated
59  # with gaps (possibly with insulating rail joiners). This code uses
60  # Azatrax SR4s to connect a Circuits4Tracks Quad Occupancy Detectors
61  # to the computer via USB. A small circuit board with two ASSR-4128s
62  # (dual Solid State Relays) and four 1,000 Ohm resistors and some headers
63  # connects the Circuits4Tracks board to the SR4.
64  #
65  # Typical usage:
66  #
67  #
68  # Four blocks in a loop:
69  #
70  # @code
71  # SR4 quadsense1 -this [Azatrax_OpenDevice 0400001234 $::Azatrax_idSR4Product]
72  # C4TSR4_Block block1 -sensorobj quadsense1 -bit 0 -signalobj signal1
73  # C4TSR4_Block block2 -sensorobj quadsense1 -bit 1 -signalobj signal2 -previousblock block1
74  # C4TSR4_Block block3 -sensorobj quadsense1 -bit 2 -signalobj signal3 -previousblock block2
75  # C4TSR4_Block block4 -sensorobj quadsense1 -bit 3 -signalobj signal4 -previousblock block3
76  # block1 configure -previousblock block4
77  # @endcode
78  # A Schematic of the layout would look like this:
79  # @image html 4circleblocks.png
80  # @image latex 4circleblocks.png "Four block circle" width=3in
81  # For the track work elements use "blockN occupiedp" for the track work
82  # elements' occupied command:
83  # eg Block1 would have 'block1 occupiedp' as its occupied command, that is
84  # its edit window would look like:
85  # @image html EditingBlock1.png
86  # @image latex EditingBlock1.png "Editing Block1" width=5in
87  # The other three blocks would be similar.
88  #
89  #
90  # Then in the Main Loop, you would have:
91  # @code
92  # while {true} {
93  # MainWindow ctcpanel invoke Block1
94  # MainWindow ctcpanel invoke Block2
95  # MainWindow ctcpanel invoke Block3
96  # MainWindow ctcpanel invoke Block4
97  # update;# Update display
98  # }
99  # @endcode
100  #
101  # @author Robert Heller \<heller\@deepsoft.com\>
102 
103  option -sensorobj -readonly yes -default {}
104  option -bit -readonly yes -default 0 -type {snit::integer -min 0 -max 3}
105  option -forwardsignalobj -readonly yes -default {}
106  option -reversesignalobj -readonly yes -default {}
107  option -previousblock -type C4TSR4_Block -default {}
108  option -nextblock -type C4TSR4_Block -default {}
109  option -direction -type {snit::enum -values {forward reverse}} -default forward
110  typemethod validate {object} {
111  ## Type validating code
112  # Raises an error if object is not either the empty string or a C4TSR4_Block
113  # type.
114 
115  if {$object eq ""} {
116  return $object;# Empty or null objects are OK
117  } elseif {[catch {$object info type} itstype]} {
118  error "$object is not a $type";# object is not a SNIT type
119  } elseif {$itstype eq $type} {
120  return $object;# Object is of our type (Block)
121  } else {
122  error "$object is not a $type";# object is something else
123  }
124  }
125  component sensor
126  ## @privatesection SR4 object
127  component forwardsignal
128  ## Signal object (typically a three color, one head block signal
129  component reversesignal
130  ## Signal object (typically a three color, one head block signal
131  variable isoccupied no
132  ## Saved occupation state.
133  typevariable sensemap -array {
134  0 Sense_1_Latch
135  1 Sense_2_Latch
136  2 Sense_3_Latch
137  3 Sense_4_Latch
138  }
139  ## Sensor bit mapping to sensor functions.
140 
141 
142  constructor {args} {
143  ## @publicsection @brief Constructor: initialize the block object.
144  #
145  # Create a lowlevel sensor object and install it as a component.
146  # Install the blocks signal (created elsewhere).
147  #
148  # @param name Name of the block object
149  # @param ... Options:
150  # @arg -sensorobj This is the SR4 for this (and up to three other
151  # blocks). This option is read-only and must be set at creation time.
152  # @arg -bit This defines the input bit on the SR4 for this block as an
153  # integer from 0 to 3, inclusive. This option is read-only and can
154  # 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
157  # empty string.
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
160  # empty string.
161  # @arg -previousblock Previous block (next block in reverse) -- used
162  # for 'propagating' signal aspects and must be a C4TSR4_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 C4TSR4_Block type object.
166  # The default is the empty string.
167  # @arg -direction Current running direction, either the word forward
168  # or reverse. The default is forward.
169  # @par
170 
171  ## Process any options
172  $self configurelist $args
173  # Install the sensor
174  set sensor [$self cget -sensorobj]
175  if {$sensor eq {}} {
176  error "The -sensorobj is required!"
177  }
178  # Install the signal component.
179  set signal [$self cget -signalobj]
180  }
181  method occupiedp {} {
182  ## The occupiedp method returns yes or no (true or false) indicating
183  # block occupation.
184 
185  # First read the current sensor state.
186  $sensor GetSenseData
187  if {[$sensor $sensemap($options(-bit))]} {
188  if {$isoccupied} {
189  # Already entered the block.
190  return $isoccupied
191  } else {
192  # Just entered the block
193  set isoccupied yes
194  $self _entering
195  return $isoccupied
196  }
197  } else {
198  if {$isoccupied} {
199  # Just left the block
200  set isoccupied no
201  $self _exiting
202  return $isoccupied
203  } else {
204  # Block still unoccupied
205  return $isoccupied
206  }
207  }
208  }
209  method _entering {} {
210  ## @privatesection Method for entering a block.
211 
212  if {[$self cget -direction] eq "forward"} {
213  # Set a red (stop and proceed) aspect.
214  if {$forwardsignal ne ""} {$forwardsignal setaspect red}
215  # Now propagate the signal to the previous block (if any)
216  if {$options(-previousblock) ne {}} {
217  # Set a yellow (approach) aspect on the previous block.
218  $options(-previousblock) propagate yellow $self -direction forward
219  }
220  } else {
221  if {$reversesignal ne ""} {$reversesignal setaspect red}
222  # Now propagate the signal to the previous block (if any)
223  if {$options(-nextblock) ne {}} {
224  # Set a yellow (approach) aspect on the previous block.
225  $options(-nextblock) propagate yellow $self -direction reverse
226  }
227  }
228  }
229  method _exiting {} {
230  ## Method for exiting a block.
231 
232  # Nothing here -- could be used for any sort of exit handling.
233  }
234  method propagate {aspect from args} {
235  ## @publicsection Method used to propagate distant signal states back down the line.
236  # @param aspect The signal aspect that is being propagated.
237  # @param from The propagating block (not used).
238  # @param ... Options:
239  # @arg -direction The direction of the propagation.
240 
241  ## First process any options
242  $self configurelist $args
243  ## If we are already occupiedp, don't do anything else.
244  if {[$self occupiedp]} {return}
245  if {[$self cget -direction] eq "forward"} {
246  # Set signal aspect
247  if {$forwardsignal ne ""} {$forwardsignal setaspect $aspect}
248  # If the new aspect was yellow, propagate a green (clear) signal
249  if {$aspect eq "yellow"} {
250  if {$options(-previousblock) ne {}} {
251  $options(-previousblock) propagate green $self -direction forward
252  }
253  }
254  } else {
255  # Set signal aspect
256  if {$reversesignal ne ""} {$reversesignal setaspect $aspect}
257  # If the new aspect was yellow, propagate a green (clear) signal
258  if {$aspect eq "yellow"} {
259  if {$options(-nextblock) ne {}} {
260  $options(-nextblock) propagate green $self -direction reverse
261  }
262  }
263  }
264  }
265 }
266 
267 
268 
269 package provide C4TSR4_Block 1.0
C4TSR4_Block
Block occupation detection using Circuits4Tracks Quad Occupancy Detectors and Azatrax SR4s.
Definition: C4TSR4_Block.tcl:59