Main Line Program Code |
This page contains the program code portion of the Basic Stamp 2 program that controls the main line automated functions. The complete code and documentation can be downloaded using this link: ReverseLoop.zip
' ====================================================================== ' ReverseLoop.bs2 2-05-2004 '{$STAMP BS2} ' Output bit definitions. T1Close CON $FE00 ' 74154 pin 1 T1Open CON $FE01 ' 74154 pin 2 T2Close CON $FE02 ' 74154 pin 3 T2Open CON $FE03 ' 74154 pin 4 T3Close CON $FE05 ' 74154 pin 6 This turnout is mounted T3Open CON $FE04 ' 74154 pin 5 backwards on the layout. T4Close CON $FE06 ' 74154 pin 7 Spare T4Open CON $FE07 ' 74154 pin 8 Spare T5Close CON $FE09 ' 74154 pin 10 This turnout operates T5Open CON $FE08 ' 74154 pin 9 normally open. T6Close CON $FE0A ' 74154 pin 11 T6Open CON $FE0B ' 74154 pin 13 T7Close CON $FE0C ' 74154 pin 14 T7Open CON $FE0D ' 74154 pin 15 T8Close CON $FE0E ' 74154 pin 16 Spare T8Open CON $FE0F ' 74154 pin 17 Spare ' Input bit definitions Sensor1 CON $EF00 ' pin 4 Sensor2 CON $EF01 ' pin 3 Sensor3 CON $EF02 ' pin 2 Block1 CON $EF03 ' pin 1 Block2 CON $EF04 ' pin 15 T1Pos CON $EF05 ' pin 14 T2Pos CON $EF06 ' pin 13 T3Pos CON $EF07 ' pin 12 T5Pos CON $DF00 ' pin 4 T6Pos CON $DF01 ' pin 3 T7Pos CON $DF02 ' pin 2 Sensor5 CON $DF03 ' pin 1 Sensor6 CON $DF04 ' pin 15 Sensor7 CON $DF05 ' pin 14 Sensor8 CON $DF06 ' pin 13 Sensor9 CON $DF07 ' pin 12 T5Req CON $BF00 ' pin 4 Manual T5 toggle (active low) T6Req CON $BF01 ' pin 3 Manual T6 toggle (active low) T7ReqOpen CON $BF02 ' pin 2 Manual T7 Open (active low) T7ReqClose CON $BF03 ' pin 1 Manual T7 Close track (active low) Sensor10 CON $BF04 ' pin 15 Sensor11 CON $BF05 ' pin 14 Sensor12 CON $BF06 ' pin 13 Sensor13 CON $BF07 ' pin 12 ChipReset CON $FF ' Inactive chip enable bits RelayLed CON $FD ' 74HC259 chip select ' Other program constants DefaultDir CON %1111111101101111 LedPin CON 5 SoundPin CON 6 ModePin VAR IN7 ' Retrigger timeout constants and variables RetrigValue CON $1A0 LongRetrig CON $FF ShortRetrig CON $80 OneSecond CON $40 RetrigCount VAR WORD ' S1 retriggerable timeout variable S5Count VAR BYTE ' S5 siding retriggerable timeout variable S6Count VAR BYTE ' S6 siding retriggerable timeout variable WyeCount VAR BYTE ' Wye retriggerable timeout variable ' Define other working variables BitValue VAR BIT ' Set by ReadBit BitAddr VAR WORD ' I/O bit address BitAddrHigh VAR BitAddr.HIGHBYTE BitAddrLow VAR BitAddr.LOWBYTE LedCount VAR BYTE ' Countdown time between Led state toggle TurnoutSel VAR WORD ' Set to turnout control output bit TurnoutSelHigh VAR TurnoutSel.HIGHBYTE TurnoutSelLow VAR TurnoutSel.LOWBYTE TurnoutPos VAR WORD ' Set to turnout sensor input bit TurnoutPosHigh VAR TurnoutPos.HIGHBYTE TurnoutPosLow VAR TurnoutPos.LOWBYTE TurnoutTst VAR BIT ' Used to verify turnout position TurnoutLast VAR WORD ' Last commanded turnout TurnoutCount VAR NIB ' Count for TurnoutLast SoundCount VAR BYTE ' Countdown time between sound "beeps" Control VAR WORD ' Program control bits S1NoCheck VAR Control.BIT0 ' 0 = normal, 1 = ignore S1 input LastB1B2 VAR Control.BIT1 ' 0 = Block2, 1 = Block1 TrainWreck VAR Control.BIT2 ' 0 = normal, 1 = both sidings occupied TurnoutBad VAR Control.BIT3 ' 0 = normal, 1 = turnout mis-position T5ReqState VAR Control.BIT4 ' 0 = normal, 1 = request processed T6ReqState VAR Control.BIT5 ' 0 = normal, 1 = request processed T7ReqCState VAR Control.BIT6 ' 0 = normal, 1 = request processed T7ReqOState VAR Control.BIT7 ' 0 = normal, 1 = request processed B6Inbound VAR Control.BIT8 ' 0 = normal, 1 = B6 train inbound at S7 T5Locked VAR Control.BIT9 ' 0 = normal, 1 = inhibit auto-reposition T6Locked VAR Control.BIT10 ' 0 = normal, 1 = inhibit auto-reposition T5LockCount VAR BYTE ' Time between button depressions T6LockCount VAR BYTE ' Time between button depressions Relay VAR BYTE ' Relay and hidden position control bits HiddenBits VAR Relay.HIGHNIB P1Relay VAR Relay.BIT0 ' 74HC259 pin 4 P2Relay VAR Relay.BIT1 ' 74HC259 pin 5 P3Relay VAR Relay.BIT2 ' 74HC259 pin 6 P4Relay VAR Relay.BIT3 ' 74HC259 pin 7 LedPos1a VAR Relay.BIT4 ' 74HC259 pin 9 LedPos1b VAR Relay.BIT5 ' 74HC259 pin 10 LedPos1c VAR Relay.BIT6 ' 74HC259 pin 11 LedPos1d VAR Relay.BIT7 ' 74HC259 pin 12 RelayCnt VAR NIB RelayWork VAR BYTE '-------------------------------------------------------------------------- ProgramStart: DIRS = DefaultDir ' Set default I/O direction bits OUTH = ChipReset ' Reset chip enable bits IF ModePin = 0 THEN Init0 ' Jump if not in manual mode ExerciseLoop: GOSUB Exercise ' Exercise turnouts and relays IF ModePin = 1 THEN ExerciseLoop '-------------------------------------------------------------------------- ' Set initial turnout positions based on current sensor states. Init0: GOSUB ResetAll ' Reset all program variables BitAddr = Sensor1 ' Select sensor S1 GOSUB ReadBit ' Read the bit IF BitValue = 0 THEN Init1 ' Jump if sensor is inactive GOSUB Sen1Sub Init1: BitAddr = Sensor2 ' Select sensor S2 GOSUB ReadBit ' Read the bit IF BitValue = 0 THEN Init2 ' Jump if sensor is inactive GOSUB Sen2Sub Init2: BitAddr = Sensor3 ' Select sensor S3 GOSUB ReadBit ' Read the bit IF BitValue = 0 THEN Init3 ' Jump if sensor is inactive GOSUB Sen3Sub Init3: BitAddr = Sensor5 ' Select sensor S5 GOSUB ReadBit ' Read the bit IF BitValue = 0 THEN Init4 ' Jump if sensor is inactive GOSUB SidingSetS5 ' Set T5 position Init4: BitAddr = Sensor6 ' Select sensor S6 GOSUB ReadBit ' Read the bit IF BitValue = 0 THEN MainLoop ' Jump if sensor is inactive GOSUB SidingSetS6 ' Set T6 position '-------------------------------------------------------------------------- ' Begin main program loop. Each loop decrements the LedCount (heartbeat) ' variable. The call to RetrigCountdown decrements the RetrigCount variable. ' The call to SidingCheck decrements the S5Count and S6Count variables. The ' WyeCount variable inhibits manual change of the T7 turnout. Calls are ' made to subroutines for processing of specific sensor inputs, buttons, ' and program control flags. MainLoop: IF LedCount <> 0 THEN MainLoop1 ' Jump if no Led change yet TOGGLE LedPin ' Toggle Led state. LedCount = OneSecond / 2 MainLoop1: LedCount = LedCount - 1 ' Heartbeat Led counter GOSUB RetrigCountdown ' Process S1 time delay counter GOSUB SidingCheck ' Check siding counters IF WyeCount = 0 THEN MainLoop2 ' Non-zero inhibits manual change WyeCount = WyeCount - 1 ' of turnout T7. MainLoop2: BitAddr = Sensor1 ' Select sensor S1 GOSUB ReadBit ' Read the bit IF BitValue = 0 THEN MainLoop3 ' Jump if Sensor S1 is inactive GOSUB S1Retrigger MainLoop3: BitAddr = Sensor2 ' Select sensor S2 GOSUB ReadBit ' Read the bit IF BitValue = 0 THEN MainLoop4 ' Jump if Sensor S2 is inactive GOSUB Sen2Sub MainLoop4: BitAddr = Sensor3 ' Select sensor S3 GOSUB ReadBit ' Read the bit IF BitValue = 0 THEN MainLoop5 ' Jump if Sensor S3 is inactive GOSUB Sen3Sub MainLoop5: BitAddr = Sensor5 ' Select sensor S5 GOSUB ReadBit ' Read the bit IF BitValue = 0 THEN MainLoop6 ' Jump if Sensor S5 is inactive GOSUB SidingSetS5 MainLoop6: BitAddr = Sensor6 ' Select sensor S6 GOSUB ReadBit ' Read the bit IF BitValue = 0 THEN MainLoop7 ' Jump if Sensor S6 is inactive GOSUB SidingSetS6 MainLoop7: BitAddr = Sensor7 ' Select sensor S7 GOSUB ReadBit ' Read the bit IF BitValue = 0 THEN MainLoop8 ' Jump if Sensor S7 is inactive GOSUB Sen7Sub MainLoop8: BitAddr = Sensor8 ' Select sensor S8 GOSUB ReadBit ' Read the bit IF BitValue = 0 THEN MainLoop9 ' Jump if Sensor S8 is inactive GOSUB Sen8Sub MainLoop9: BitAddr = Sensor9 ' Select sensor S9 GOSUB ReadBit ' Read the bit IF BitValue = 0 THEN MainLoopA ' Jump if Sensor S9 is inactive GOSUB Sen9Sub MainLoopA: RelayCnt = HiddenBits ' Remember current states HiddenBits = 0 ' Reset all bits BitAddr = Sensor10 ' Select sensor S10 GOSUB ReadBit ' Read the bit IF BitValue = 0 THEN MainLoopB ' Jump if Sensor S10 is inactive LedPos1a = 1 ' Illuminate indicator MainLoopB: BitAddr = Sensor11 ' Select sensor S11 GOSUB ReadBit ' Read the bit IF BitValue = 0 THEN MainLoopC ' Jump if Sensor S11 is inactive LedPos1b = 1 ' Illuminate indicator MainLoopC: BitAddr = Sensor12 ' Select sensor S12 GOSUB ReadBit ' Read the bit IF BitValue = 0 THEN MainLoopD ' Jump if Sensor S12 is inactive LedPos1c = 1 ' Illuminate indicator MainLoopD: BitAddr = Sensor13 ' Select sensor S13 GOSUB ReadBit ' Read the bit IF BitValue = 0 THEN MainLoopE ' Jump if Sensor S13 is inactive LedPos1d = 1 ' Illuminate indicator MainLoopE: IF RelayCnt = HiddenBits THEN MainLoopF ' Jump if no change GOSUB SetRelays ' Set hidden train position indicators MainLoopF: GOSUB InputCheck ' Check for manual turnout position input IF TrainWreck = 0 AND TurnoutBad = 0 THEN MainLoop GOSUB SoundTone PAUSE 100 GOTO MainLoop '-------------------------------------------------------------------------- ' Run this code when train sensor S1 is active. If both blocks are not ' occupied, then the LastB1B2 variable controls which siding we use. This ' adds some variability to things. Sen1Sub: BitAddr = Block1 ' Select Block1 detector bit GOSUB ReadBit ' Read the bit IF BitValue = 1 THEN Sen1Sub2 ' Jump if B1 siding is occupied BitAddr = Block2 ' Select Block2 detector bit GOSUB ReadBit ' Read the bit IF BitValue = 1 THEN Sen1Sub1 ' Jump if B2 siding is occupied LastB1B2 = ~LastB1B2 ' Neither siding occupied. IF LastB1B2 = 0 THEN Sen1Sub3 ' Alternate B1 and B2 siding use Sen1Sub1: TurnoutSel = T1Close TurnoutPos = T1Pos GOSUB Turnout ' Turnout T1 "straight" TurnoutSel = T2Close TurnoutPos = T2Pos GOSUB Turnout ' Turnout T2 "straight" TurnoutSel = T3Close TurnoutPos = T3Pos GOSUB Turnout ' Turnout T3 "straight" P1Relay = 0 ' Inbound P1 relay direction GOSUB SetRelays ' Set polarity relays RETURN Sen1Sub2: BitAddr = Block2 ' Select Block2 detector bit GOSUB ReadBit ' Read the bit IF BitValue = 1 THEN Sen1Sub4 ' Jump if B2 siding is occupied Sen1Sub3: TurnoutSel = T1Open TurnoutPos = T1Pos GOSUB Turnout ' Turnout T1 "open" TurnoutSel = T3Close TurnoutPos = T3Pos GOSUB Turnout ' Turnout T3 "straight" P2Relay = 0 ' Inbound P2 relay direction GOSUB SetRelays ' Set polarity relays TurnoutSel = T2Close TurnoutPos = T2Pos GOSUB Turnout ' Turnout T2 "straight" RETURN Sen1Sub4: SoundCount = 5 TrainWreck = 1 ' Both sidings are occupied! RETURN '-------------------------------------------------------------------------- ' Run this code when train sensor S2 is active. Sen2Sub: P1Relay = 1 ' Outbound P1 relay direction GOSUB SetRelays ' Set polarity relays TurnoutSel = T2Open TurnoutPos = T2Pos GOSUB Turnout ' Turnout T2 "open" TurnoutSel = T1Close TurnoutPos = T1Pos GOSUB Turnout ' Turnout T1 "straight" RetrigCount = 0 ' Stop any inprogress timeout S1NoCheck = 1 ' Ignore S1 signal RETURN '-------------------------------------------------------------------------- ' Run this code when train sensor S3 is active. Sen3Sub: P2Relay = 1 ' Outbound P2 relay direction GOSUB SetRelays ' Set polarity relays TurnoutSel = T3Open TurnoutPos = T3Pos GOSUB Turnout ' Turnout T3 "open" TurnoutSel = T1Open TurnoutPos = T1Pos GOSUB Turnout ' Turnout T1 "open" RetrigCount = 0 ' Stop any inprogress timeout S1NoCheck = 1 ' Ignore S1 signal RETURN '-------------------------------------------------------------------------- ' Run this code when train sensor S5 or S6 is active. Both turnouts are ' returned to their default positions when their respective siding count ' is 1. SidingSetS5: IF S5Count <> 0 THEN SidingS5Exit TurnoutSel = T5Close TurnoutPos = T5Pos GOSUB Turnout ' Turnout T5 "closed" SidingS5Exit: S5Count = ShortRetrig ' Use short delay count RETURN SidingSetS6: IF S6Count <> 0 THEN SidingS6Exit TurnoutSel = T6Open TurnoutPos = T6Pos GOSUB Turnout ' Turnout T6 "open" SidingS6Exit: S6Count = ShortRetrig ' Use short delay count RETURN SidingCheck: If S5Count = 0 THEN SidingChk1 ' Jump of no timeout inprogress S5Count = S5Count - 1 IF S5Count <> 0 THEN SidingChk1 ' Jump if S5Count still not 0. IF T5Locked = 1 THEN SidingChk1 ' Jump if locked TurnoutSel = T5Open TurnoutPos = T5Pos GOSUB Turnout ' Turnout T5 "open" SidingChk1: If S6Count = 0 THEN SidingChk2 ' Jump of no timeout inprogress S6Count = S6Count - 1 IF S6Count <> 0 THEN SidingChk2 ' Jump if S6Count still not 0. IF T6Locked = 1 THEN SidingChk2 ' Jump if locked TurnoutSel = T6Close TurnoutPos = T6Pos GOSUB Turnout ' Turnout T6 "closed" SidingChk2: IF T5LockCount = 0 THEN SidingChk3 ' Jump T5 lock timeout not in progress T5LockCount = T5LockCount - 1 SidingChk3: IF T6LockCount = 0 THEN SidingExit ' Jump T6 lock timeout not in progress T6LockCount = T6LockCount - 1 SidingExit: RETURN '-------------------------------------------------------------------------- ' Run this code when train sensor S7, S8 or S9 is active. This code controls ' the track polarity of the lead and yard tracks. The position of turnout 7 ' is used to set the polarity relay. Sen7Sub: GOSUB SetP3Relay RETURN Sen8Sub: TurnoutSel = T7Close TurnoutPos = T7Pos GOSUB Turnout ' Turnout T7 "closed" GOSUB SetP3Relay RETURN Sen9Sub: TurnoutSel = T7Open TurnoutPos = T7Pos GOSUB Turnout ' Turnout T7 "open" GOSUB SetP3Relay RETURN SetP3Relay: BitAddr = T7Pos ' Select T7 position bit GOSUB ReadBit ' Read the bit P3Relay = BitValue ' Set P3 control bit GOSUB SetRelays ' Set polarity relays WyeCount = ShortRetrig RETURN '-------------------------------------------------------------------------- ' Special processing for S1 sensor. Call this routine anytime Sensor S1 ' detects the presence of a train. Sensor S1 has a flag bit and RetrigCount ' associated with it. S1NoCheck when set (1) indicates that the code should ' ignore acting on an active S1 signal. It is set in Sen2Sub or Sen3Sub by ' an outbound train leaving a siding. It is reset (0) when the first active ' S1 signal is detected indicating an outbound train is present. ' ' RetrigCount is loaded when a train is detected by sensor S1. RetrigCount ' is decremented in each cycle of the MainLoop. Additional S1 detection ' signals within one second of the initial one cause the countdown to ' restart. After one second, a closely following train will be detected and ' directed to the free reverse loop siding (if any). ' ' Once RetrigCount reaches zero (approximately 5 seconds of S1 inactive), ' a train is assumed to be no longer in transit across the turnouts. The ' RetrigCountDown code will reset the turnouts and power polarity relays. ' ' S1 is also used as a trigger point for S1Outbound trains. Turnout T5 is ' set closed at the Midway siding if B5 is occupied. S1Retrigger: IF RetrigCount > (RetrigValue - OneSecond) THEN S1Retrigger2 IF S1NoCheck = 0 THEN S1Retrigger1 ' Inbound train S1NoCheck = 0 ' Outbound train GOTO S1Retrigger2 S1Retrigger1: GOSUB Sen1Sub S1Retrigger2: RetrigCount = RetrigValue RETURN '-------------------------------------------------------------------------- ' Run this code for processing the countdown timing for Sensor S1. When ' countdown equals 1, time delay is over. Reset turnouts and power relays ' to inbound settings. RetrigCountdown: IF RetrigCount = 0 THEN RetrigExit ' Jump if no retrigger operation RetrigCount = RetrigCount - 1 IF RetrigCount <> 1 THEN RetrigExit ' Jump if RetrigCount not 1. RetrigNoCount: TurnoutSel = T1Close TurnoutPos = T1Pos GOSUB Turnout ' Turnout T1 "straight" TurnoutSel = T2Close TurnoutPos = T2Pos GOSUB Turnout ' Turnout T2 "straight" TurnoutSel = T3Close TurnoutPos = T3Pos GOSUB Turnout ' Turnout T3 "straight" P1Relay = 0 ' Inbound P1 relay direction P2Relay = 0 ' Inbound P2 relay direction GOSUB SetRelays ' Set polarity relays RetrigExit: RETURN '-------------------------------------------------------------------------- ' Run this code to check for manual turnout position requests. Set turnouts ' T5, T6, or T7 appropriately. Request are ignored if the respective ' retriggerable timeout counter is non-zero. These inputs are active low. InputCheck: BitAddr = T5Req ' Select T5 toggle request input GOSUB ReadBit ' Read the bit IF BitValue = T5ReqState THEN InpChk4 ' Jump if no current request IF BitValue = 1 THEN InpChk2 ' Jump if inactive IF S5Count <> 0 THEN InpChk3 ' Ignore input if inprogress operation IF T5LockCount = 0 THEN InpChk1 ' Jump lock timeout not in progress T5Locked = 1 ' Lock turnout position T5LockCount = 0 ' Reset timer FREQOUT SoundPin, 25, 2092 T6Locked = 0 ' Unlock T6 TurnoutSel = T6Close TurnoutPos = T6Pos GOSUB Turnout ' Make sure T6 is "closed" GOTO InpChk3 InpChk1: GOSUB ToggleT5 T5ReqState = 0 T5Locked = 0 ' Unlock turnout position T5LockCount = 8 ' Set count for double press detection GOTO InpChk3 InpChk2: T5ReqState = 1 InpChk3: PAUSE 100 ' Button debounce InpChk4: BitAddr = T6Req ' Select T6 toggle request input GOSUB ReadBit ' Read the bit IF BitValue = T6ReqState THEN InpChk8 ' Jump if no current request IF BitValue = 1 THEN InpChk6 ' Jump if inactive IF S6Count <> 0 THEN InpChk7 ' Ignore input if inprogress operation IF T6LockCount = 0 THEN InpChk5 ' Jump lock timeout not in progress T6Locked = 1 ' Lock turnout position T6LockCount = 0 ' Reset timer FREQOUT SoundPin, 25, 2092 T5Locked = 0 ' Unlock T5 TurnoutSel = T5Open TurnoutPos = T5Pos GOSUB Turnout ' Make sure T5 is "open" GOTO InpChk7 InpChk5: GOSUB ToggleT6 T6ReqState = 0 T6Locked = 0 ' Unlock turnout position T6LockCount = 8 ' Set count for double press detection GOTO InpChk7 InpChk6: T6ReqState = 1 InpChk7: PAUSE 100 ' Button debounce InpChk8: BitAddr = T7ReqClose ' Select T7 close request input GOSUB ReadBit ' Read the bit IF BitValue = T7ReqCState THEN InpChkB ' Jump if no current request IF BitValue = 1 THEN InpChk9 ' Jump if inactive IF WyeCount <> 0 THEN InpChkA ' Ignore input if inprogress operation GOSUB Sen8Sub WyeCount = 0 ' No timeout for manual operation T7ReqCState = 0 GOTO InpChkA InpChk9: T7ReqCState = 1 InpChkA: PAUSE 20 ' Button debounce InpChkB: BitAddr = T7ReqOpen ' Select T7 open request input GOSUB ReadBit ' Read the bit IF BitValue = T7ReqOState THEN InpChkE ' Jump if no current request IF BitValue = 1 THEN InpChkC ' Jump if inactive IF WyeCount <> 0 THEN InpChkD ' Ignore input if inprogress operation GOSUB Sen9Sub WyeCount = 0 ' No timeout for manual operation T7ReqOState = 0 GOTO InpChkD InpChkC: T7ReqOState = 1 InpChkD: PAUSE 20 ' Button debounce InpChkE: RETURN ToggleT5: BitAddr = T5Pos ' Select T5 position bit GOSUB ReadBit ' Read the bit TurnoutSel = T5Close IF BitValue = 0 THEN ToggleT5_1 TurnoutSel = T5Open ToggleT5_1: TurnoutPos = T5Pos GOTO ToggleT6_2 ToggleT6: BitAddr = T6Pos ' Select T6 position bit GOSUB ReadBit ' Read the bit TurnoutSel = T6Open IF BitValue = 0 THEN ToggleT6_1 TurnoutSel = T6Close ToggleT6_1: TurnoutPos = T6Pos ToggleT6_2: GOSUB Turnout ' Set Turnout position ToggleExit: RETURN '-------------------------------------------------------------------------- ' Set turnout based upon values in TurnoutSel and TurnoutPos. This routine ' takes advantage of the fact that an 'open' command is an odd number and ' an open turnout sensor reports a 1. ' ' The TurnoutLast and TurnoutCount variables are used to protect aganst ' switch machine burnout in the event of a malfunctioning turnout position ' sensor. A maximum of 5 tries to position a turnout will be attempted. Turnout: IF TurnoutLast <> TurnoutSel THEN Turnout1 ' Jump if not the same turnout IF TurnoutCount > 4 THEN Turnout3 ' Jump if more than 4 attempts TurnoutCount = TurnoutCount + 1 ' Increment counter GOTO Turnout2 Turnout1: TurnoutCount = 0 ' Reset attempt counter TurnoutLast = TurnoutSel ' Remember last commanded turnout Turnout2: TurnoutTst = TurnoutSelLow // 2 ' Compute desired position value BitAddr = TurnoutPos ' Select turnout sensor bit GOSUB ReadBit ' Read the bit IF TurnoutTst = BitValue THEN Turnout3 ' Return if already positioned OUTA = TurnoutSelLow ' Select the turnout coil; bits 3-0 OUTH = TurnoutSelHigh ' Energize it PAUSE 200 ' Adjust for reliable turnout operation OUTH = ChipReset ' De-energize the turnout coil ' Verify the turnout moved to the commanded position. PAUSE 50 ' Make sure TurnoutPos bit is stable BitAddr = TurnoutPos ' Select turnout sensor bit GOSUB ReadBit ' Read the bit IF TurnoutTst = BitValue THEN Turnout3 SoundCount = (TurnoutSelLow / 2) + 1 TurnoutBad = 1 Turnout3: RETURN '-------------------------------------------------------------------------- ' Set power polarity relays and hidden train position indicators based upon ' the current value of the Relay variable. SetRelays: RelayWork = Relay FOR RelayCnt = 0 TO 7 RelayCnt.BIT3 = RelayWork.BIT0 OUTA = RelayCnt ' Set address and data OUTH = RelayLed ' Store data into selected latch OUTH = ChipReset ' Deselect 74HC259 RelayCnt.BIT3 = 0 ' Reset data bit RelayWork = RelayWork >> 1 NEXT RETURN '-------------------------------------------------------------------------- ' Sound warning tone. SoundCount specifies the number of "beeps" to sound. ' TrainWreck and TurnoutBad specify which tone frequency to use. The TrainWreck ' and TurnoutBad flags are reset once the required tone count is sounded. SoundTone: IF TrainWreck = 0 THEN SoundTone2 FREQOUT SoundPin, 100, 2092 IF SoundCount = 0 THEN SoundTone1 SoundCount = SoundCount - 1 IF SoundCount <> 0 THEN SoundTone4 PAUSE 2000 SoundTone1: TrainWreck = 0 GOTO SoundTone4 SoundTone2: IF TurnoutBad = 0 THEN SoundTone4 FREQOUT SoundPin, 100, 880 IF SoundCount = 0 THEN SoundTone3 SoundCount = SoundCount - 1 IF SoundCount <> 0 THEN SoundTone4 PAUSE 2000 SoundTone3: TurnoutBad = 0 SoundTone4: RETURN '-------------------------------------------------------------------------- ' Reads the bit specified by BitAddr and stores its value in BitValue. ReadBit: OUTA = BitAddrLow ' Set input selection bits 3-0 OUTH = BitAddrHigh ' Set chip enable bits 15-8 BitValue = IN4 ' Read bit value from input pin OUTH = ChipReset ' Deselect input bit RETURN '-------------------------------------------------------------------------- ' Reset chip enable bits so we don't damage the turnout coils. Then set the ' default turnout positions, power relay states, and program working ' variables. ResetAll: GOSUB RetrigNoCount ' T1, T2, and T3 "closed" TurnoutSel = T5Open TurnoutPos = T5Pos GOSUB Turnout ' Turnout T5 "open" TurnoutSel = T6Close TurnoutPos = T6Pos GOSUB Turnout ' Turnout T6 "closed" Relay = 0 ' Initialize relay value GOSUB SetP3Relay ' Set P3 relay to T7 position. TurnoutLast = 0 TurnoutCount = 0 Control = $00F0 ' Reset all program control bits RetrigCount = 0 ' Reset all retrigger counts S5Count = 0 ' Reset T5 delay counter S6Count = 0 ' Reset T6 delay counter WyeCount = 0 ' Reset T7 delay counter RETURN '-------------------------------------------------------------------------- ' This routine and the following data is used when in manual mode to exercise ' the turnouts. S5Count and S6Count are used for working variables. ' Exercise: TOGGLE LedPin ' Toggle Led state. READ Taddr, S6Count FOR S5Count = 1 TO S6Count STEP 2 READ Taddr+S5Count, TurnoutSelLow READ Taddr+S5Count+1, TurnoutSelHigh READ Tpos+S5Count, TurnoutPosLow READ Tpos+S5Count+1, TurnoutPosHigh GOSUB Turnout IF TurnoutBad = 0 THEN Exercise2 Exercise1: GOSUB SoundTone PAUSE 100 IF SoundCount <> 0 THEN Exercise1 Exercise2: PAUSE 500 NEXT Exercise3: Relay = 1 Exercise4: GOSUB SetRelays PAUSE 500 Relay = Relay << 1 ' Select next relay IF Relay <> 0 THEN Exercise4 GOSUB SetRelays ' Reset last relay PAUSE 500 RETURN Taddr DATA 24, WORD T1Open, WORD T1Close, WORD T2Open, WORD T2Close, WORD T3Open, WORD T3Close, WORD T5Close, WORD T5Open, WORD T6Open, WORD T6Close, WORD T7Open, WORD T7Close Tpos DATA 24, WORD T1Pos, WORD T1Pos, WORD T2Pos, WORD T2Pos, WORD T3Pos, WORD T3Pos, WORD T5Pos, WORD T5Pos, WORD T6Pos, WORD T6Pos, WORD T7Pos, WORD T7Pos
Navigation: Main line D&B Home Buczynski.com Index
Copyright © 2006 Don Buczynski
San Diego, California