ELEC270 Design Project
Summary of Modules
The supporting website for this project is found at http://geoffknagge.com/uni/elec270/.
Alarms Module
This module is responsible for determining which zones, doors and windows are secure, and handling any security violations which occur. Zones are secure if all doors connecting to that zone are either secure, or have a secure zone on the other side of them. Doors become secure if they are shut when either they are locked, or have a secure zone on both sides. Windows become secure if they are shut when either in a secure zone, or in a zone that is locked (but not secure) if that zone has the "maximum window security" option set.
When an alarm is triggered, a corresponding bit in the data bytes tq, tq1...tq4 is set (Smoke, panic, windows, internal doors, external doors). Then "topalarm" is called to locate the alarm which has top priority. If that alarm is not already active, then it is set off by the system. After all alarms are cleared, the system returns to the state that it was in before the alarm occurred.
The auto arming feature is also implemented here. When the clock module clicks over to a new minute, a flag is set to indicate that the auto arming needs to be checked on the next pass through the main program loop.
Clock Module
This module controls the real time clock, audio signals, and the indicator lamp. C_update is called every millisecond via an interrupt, and controls the real time clock, the menu timer "menutime", and the password timeout "PW_timer". If PW_timer is either 0 or FF, it is not decremented.
The audio and visual indicator handlers are very similar to each other. There are a number of different modes defined in an array for each. Each mode consists of eight different codes corresponding to an audio frequency or light on/off state, and the sequence to change to when the current sequence is completed. Every 0.25 seconds the driver is called via the timer and the next sound or light code in the sequence is activated.
Interrupt Handler
This module is the interface between interrupt request, and procedures which rely on the interrupts for timing. There are interrupts for the real time clock and timeout counters, the lcd module, and the UART driver.
IO Module
This module is handles the i/o ports. Since port 1C is shared by the indicator and LCD control lines, we implement a "bit set" feature via software.
The Jump Table
For each of the modes described in the mode handler, there is a corresponding routine which performs the action required of that mode. The routines locations are kept in the following jump table, indexed by the mode number.
Keypad Module
This module is responsible for detecting and reporting valid keypresses. The interrupt does most of the hard stuff and all the program needs to do is to call KeyGet when it needs to know what key was pressed, if any.
The keys are detected in KeyChk, by scanning each row individually via KeyRow. This tallies up the number of detected keys, and if exactly one was pressed, the scan code of that key is returned. If none, or more than one, is pressed then the routine indicates that nothing has been pressed. The interrupt continually checks for keys every milisecond, and if one is held down for longer than 10ms then it is saved in the buffer upon being released.
LCD Interface module
Below is the latest version of our LCD 3interface. Messages are passed by indexing the screen array with register C, and passing it to LCD_setmsg. The interrupt is called every 40 microseconds to update any changes that have been made to the desired output, and a counter is used to determine the time to wait before scrolling the screen.
This module relies on the presence of the data module somewhere in the program. Port initialisation is assumed.
Menu Definitions
The menus are defined in this module, in an array of 15 byte entries... The comments indicate which codes are for what.
;/////////////////// Menu 00
.Byte SC_main ; screen code
.byte ST_SZ1 ; key 1 mode
.byte ST_SZ4 ; key 4 mode
.byte ST_SZ7 ; key 7 mode
.byte ST_CONFIG ; key * mode
.byte ST_SZ2 ; key 2 mode
.byte ST_SZ5 ; key 5 mode
.byte ST_SZ8 ; key 8 mode
.byte 00 ; key 0 mode
.byte ST_SZ3 ; key 3 mode
.byte ST_SZ6 ; key 6 mode
.byte 00 ; key 9 mode
.byte 0DE ; key # mode
.byte 10 ; timeout
.byte 0DE ; mode to go to in timeout
The Screen Lines
Each line that ever needs to be displayed is stored here... somewhere. The line number is the code used in the screen definitions to determine what to display on which parts of the LCD module.
Mode Handler
These routines are the core of the user interface. At all times the program is set to be in a particular mode. Examples of modes include waiting for a keypress at a menu, reading in a password, or setting up the data for use by another mode. On every pass through the main loop, a short routine is called by looking up the mode number in the jump table. Once a mode's task has been completed or otherwise terminated, it will then change the mode to suit the next required operation.
Password Modules
Password handling is done in two modules. The input module is what handles the input from the keypad and output to the LCD, but does not do any validity checking. The module initialisation procedure is passed a pointer to a table of the following form, the address of which is stored in PW_table by the module.
1 byte: Mode to switch to when enter pressed
1 byte: Mode to switch to when cancelled
1 byte: Mode to switch to when timeout occurs
1 byte: Amount of seconds before a timeout
1 byte: screen line #1 to be displayed
1 byte: screen line #2 to be displayed
The checking module is what is called by the program when we seek a password. Passwords are stored in an array, so we only need to tell the module which one we're asking for, what prompts to display on the top half of the screen, and which modes to change to under various circumstances. This is done by passing the setup procedure a pointer to a table of the following form :
1 byte : password number that we're aiming for
2 bytes: lines 1,2 of display
1 byte : mode to change to if password accepted
1 byte : mode to change to if cancelled
1 byte : mode to change to if timed out
1 byte : mode to change to if wrong 3 times
1 byte : timeout in seconds
Screen Definitions
Each "screen" that is used is defined as follows
- 4 bytes corresponding to one of the screen lines. A zero indicates that this line is used for the scrolling part of the message.
- 1 byte indicating how many lines are to be rotated through the scrolling section. Must be non-zero, even if none of the lines are defined as scrolling.
- The lines, in order, that are to be rotated through the scrolling section.
ScrnTable is a list of 2 byte pointers to the memory location of each of the above screen definitions. You specify a screen by specifying the entry number in this table.
The Security Module
The module that calculates which doors and windows should be considered secured and/or locked, and handles zone locking and settings. The conditions for things becoming secure is described in the alarms module.
The recalculate procedure initially tries to secure all zones, doors, and windows. Any unlocked door which connects to the outside is not able to be secured. The procedure then checks all doors, and if a door is in its insecure state, and one of zones on either side of it is secure, then that zone becomes insecure. Consequently, all unlocked doors and windows in that zone also become insecure. This is repeated until all doors are checked without any changes being made.
Timers Module
This module controls the hardware timing devices, used for driving the speaker and interrupt line.
UART Module
The UART is used to simulate a telephone link to the outside world. When an alarm is triggered with the "send phone message" option enabled, a bit is set in one of the corresponding status bytes. The job of determining the highest priority message is done by U_next, which updates the pointer u_message. U_message points to the next byte to be sent, and is incremented by the interrupt after each send. The interrupt is triggered by the TxEmpty pin on the Uart, and so is called after each character is sent.
However, most of the time there is nothing to be sent, and so the interrupt will not do anything. This means that the TxEmpty pin does not make a high/low change (because nothing was sent so it stayed in the empty state), and so the interrupt stops being called. Therefore the kickstart procedure is required to force a call of the interrupt. The flag U_active determines whether or not a message is currently being sent, and hence whether the interrupt needs a forced call to begin retransmitting.
|