■ FIGURE 4.
to create a generic interface: Up, Down, Left, Right, OK,
and Escape. Using the SX's internal pull-ups adding the
interface is simple (see Figure 4).
We all know that we should debounce digital inputs;
we also know that this takes time. After some thought, I
decided to put the debouncing code inside the interrupt.
By doing this, a set of flags can be used to indicate that an
input is valid. Here's the code for that:
CJNE tmr1ms, #80, DB_Exit
CJB tmrScan, #50, DB_Port_Scan
MOV btnFlags, btnTemp
MOV btnTemp, #%1111_1111
MOV W, /UserIn
AND W, btnTemp
MOV btnTemp, W
This code use two timers: one that counts the
number of ISR cycles in one millisecond ( 80), and a
second that sets the debounce timing. In this case, I'm
using 50 milliseconds.
At the beginning of each 50 millisecond debounce
period, a temporary variable (btn Temp) is set to
%1111_1111. We start the debounce scan assuming a
button is pressed (1 is pressed, 0 is not pressed). On each
millisecond tick through the cycle, the temporary variable
is ANDed with the button port — any pin that is active will
remain 1 in the temporary variable.
Note that as we're using active-low inputs, we have to
invert the port value during the scan.
At the end of the debounce period, the temporary
variable is moved to a global variable called btnFlags for
use by the foreground program. This cycle runs constantly
so the btnFlags variable is updated every 50 milliseconds.
In the foreground, we don't have to do anything except
check the bits in btnFlags to see if any inputs are active.
I use a toggle switch for the mode selector as my time
spent developing sprinkler timers for Toro taught me that
users generally don't like navigating menus for operational
modes — just settings. When this switch is in the middle
position, we're in setup mode that allows us to adjust the
interval timing for run mode. The program will allow any
interval — with one-second resolution — from one second
to 24 hours. Time will be displayed on the LCD as
00:00:00 to 24:00:00.
In setup mode, the LCD will appear as in Figure 5
(top). An underline cursor will denote the field that can be
updated: seconds, minutes, or hours. These values are
stored in an array and use a BCD format like common
RTCs (DS1302, etc.).
Having a single menu item with three fields meant
that the code to update the interval was actually quite
manageable, and using the Up, Down, Left, Right, OK,
and Escape buttons makes it intuitive:
iChanged = No
PUT cntDn, iTime(0) TO iTime(2)
cmdChar = LcdLine1 + 7
IF iChanged THEN
LCD_OUT " "
At the start, we clear the screen and display the
current interval setting. The interval has been moved
into a temporary array called cntDn; we'll manipulate this
array instead of the present user setting.
By using a temporary array for the interval, we actually
have a method to "undo" any changes. You'll notice that
right before the time elements are written to the LCD, a