Stop light system implemented in Zilog Z80 assembly In this we will be focusing on a standard intersection of two, two-lane highways For example, there is a single lane northbound and a single lane southbound similarly, there is a single lane east bound and a single lane westbound 3||4 2 || 5 ---------++-------- ---------++-------- 1 || 6 8||7 As displayed the '|' shows North and South bound lanes '-' displays East and West bound lanes This is a North American traffic pattern, driving is done in the right hand lane from the prespective of the driver Each lane has a unique number Due to the driving pattern -The odd numbered lanes approach to the light -The even numbered lanes leave the light Only odd numbered lanes need to be factored when controlling this stoplight To establish timing, each cycle should start on a 20 second timer. Yello & red cycles are 5 seconds long Fully red cycles are 5 seconds long Durning green each vehicle that passes over the electromagnetic sensor will add +5 seconds to the countdown The maxium cycle time must be no more than 35 seconds If there is any unforseen issue with this system, it must default to All-Way flashing red **************************************************************************************************************************** ----------- |Data pins| ----------- In the documentation, the schematic labeled data_pins.jpg shows the role of each data pin on the Z80 microprocessor Since this intersection is quite simple, we can abstract pairs of lights to either North and South bound or East and West bound. North and South bound traffic will approach at lanes 3 and 7 East and West bound traffic will approach at lanes 1 and 5 In this pattern 3 and 7 must be the same state Similarly 1 and 5 must be the same state This means we can use 3 bits to control 2 lights and 3 more bits to control the other 2 lights. D0 -> North and South traffic red lights D1 -> North and South traffic yella lights D2 -> North and South traffic green lights D3 -> East and West traffic red lights D4 -> East and West traffic yella lights D5 -> East and West traffic green lights Quick note the rightmost least significant bit is D0, to the left is D1 and so on so for an intersection that is fully red or 001001: D5 D4 D3 D2 D1 D0 0 0 1 0 0 1 An abstracted schematic is showing the data lines on the Z80 microprocessor and the down stream functions they are wired to. This document is not a full schematic for the system, ******************************************************************************************************************************* --------------- |Setup outputs| --------------- Each cycle state is listed in this section The CPU will load the binary light control outputs to a memory location These memory locations are in Little Endian format, so the desired loactions are commented for ease of reading Here are all the cycle states, their memory locations, little endian memory locations, binary output values, hex output values Description |Binary |Hex |Location |Little Endian ;NS GREEN - EW RED |001100 |Ch |0x0100 |0001h ;NS YELLA - EW RED |001010 |Ah |0x0101 |0101h ;NS RED - EW RED |001001 |9h |0x0102 |0201h ;NS RED - EW GREEN |100001 |21h |0x0103 |0301h ;NS RED - EW YELLA |010001 |11h |0x0104 |0401h These values can later be loaded and sent to the output to control the lights. ******************************************************************************************************************** -------------- |Timing loops| -------------- Within stoplight.asm there are 3 loops dedicated to timing MILLISEC - Halts the machine for one milisecond, \INT pin wired to a N555 timer set to 1KHz SETUP_ONE_SEC - Loads decimal 1000 (0x3E8) into the BC register pair ONE_SEC - Calls MILLISEC loop and decriments the BC register pair, if Z flag is set, execution will return to previous loop SET_TIMER_5 - Loads decimal 5 (0x5) into the D register TIMER_5 - Calls SETUP_ONE_SEC, then ONE_SEC and decriments the D register, if Z flag is set, execution will return to previous loop SET_TIMER_25 - Loads decimal 25 (0x19) into the D register TIMER_25 - Calls SETUP_ONE_SEC, then ONE_SEC and decrements the D register, if Z flag is set, execution will return to previous loop Each timing loop stores the count down in either the D register or the BC register pair. For the D register count downs, the accumulator is XORed, the D register is decrimented, and added to the accumulator This will ensure the CPU has a mathematical operation that is capable to set the zero flag. This will allow execution to escape the loop when the count reaches zero Similarly. The 16 bit register pair BC has to undergo this process as well This pair is simply split up in to the 8 bit B and C registers and the same comparison with the accumulator is made on each register seperately ******************************************************************************************************************** -------------------------- |Holding the light states| -------------------------- Kind of a side plot here, but the Z80 won't hold the outputs during a halt That being said we need to catch the output so that we can still use the z80 for timing We could add up all the T-states in the manual and come up with a close representation of 1 sec, 5 sec, 25 sec etc. Or we can store the outputs to a chip In our case a 74HC374 D Flip-Flop should hold all 8 bits nicely, and will work great with the Z80 \WR \IORQ Simply wire the data bus to the 74HC374 data bus Wire the Z80 \WR to the 74HC374 \CLK And that should be able to let the Data bus stabilize by the time our \WR goes high to trigger a rising edge on the 74HC374 \CLK This chip will contiuously output the stored values, so no futher contol is needed on the 74HC374. The OE is for special cases only ************************************************************************************************************************************** --------------------- |Outputting anything| --------------------- Due to the output function of the Z80, we need to assign address to the devices wired in to the circuit 5 or binary 101 will be our 74HC374 For this device to listen on the address bus for its ID we need another chip the 74HC138 is capable of listening for our 101 call over the address bus and allowing the output to flow to the 74HC374 and only the output to only the 74HC374 ************************************************************************************************************************************** ----------- |The cycle| ----------- To start with, we'll need to go through each available light in the cycle so we SETUP_OUTPUTS, to load the values to memory Then we set a 25 second timer to load the timer with 25 seconds Using the values we loaded in memory, we'll set the first light cycle with CALL NS-G_EW-R This is North & South green, East & West red. CALL TIMER_25 to start the hardware timer This is similar for each cycle with a Green and Red Next is a Yello & Red cycle Call SET_TIMER_5 to load the timer with 5 seconds Call NS-Y_EW-R to set the lights Call TIMER_5 to start the timer This is similar for each Yello and red cycle Next is an all-way red Call SET_TIMER_5 to load the timer with 5 seconds Call NS-R_EW-R to set the lights Call TIMER_5 to start the timer This is exactly the same for each all-way red cycle Then we simply jump back to the start of FULL_CYCLE to keep the loop going To help track and debug the entire cycle, the H register hold the current Process ID [PID] This is incremented after the completion of each part of the code.