Please consult with your Rabbi if you have any concerns in
this regard.)
I actually developed two helper routines for the
button input. The first simply debounces a specified input
pin for a number of milliseconds; if the button is pressed
through the entire cycle, then it is considered good. Here's
that bit of code:
pub getbutton(pin, dbtime) | db, t
dira[pin] := 0
db := 0
t := cnt
repeat dbtime
waitcnt(t += MS_001)
if (BTN_MODE == ACTIVE_HIGH)
db += ina[pin]
else
db += !ina[pin] & %1
return (db == dbtime)
We start by forcing the desired pin to an input state
and clearing a variable that will count the number of
active cycles through the loop; if the active cycles match
the specified debounce time, then the button is
considered pressed.
Within the loop, we wait one millisecond
(synchronized, so as not to add too much overhead for
long debounce periods) and then add the state of the
input to the counter. Note that the code can
accommodate active-high and active-low inputs. In my
experience, the buttons on a given project tend to use the
same active state so I set that state (BTN_MODE) in the
constants section.
At the end of the loop, we return true or false
depending on whether or not the button remained
pressed through the entire cycle. This code is very
modular and provides a fixed delay that we will use in the
following method:
pub getcount(pin, cmax) | count, idle
count := 0
idle := 0
repeat
if (getbutton(pin, 50) == true)
repeat
until (getbutton(pin, 50) == false)
count += 1
idle := 0
else
idle += 50
if (count == cmax)
quit
if (count > 0) and (idle => 1000)
quit
return count
Again, the purpose of this method is to count the
number of presses on the target input pin, up to a
specified maximum. It uses the getbutton() method to
scan the pin and create internal timing.
16 November 2010
At the top, we clear the button count and idle timer
variables. When a button press is detected, the code waits
for it to be released, increments the count, and then resets
the idle timer. If there is no button press, then the idle
timer is incremented by 50 since that is the timing used
with getbutton().
There are two ways to return from this method: 1) The
maximum button count is reached, or 2) There is a nonzero count and the button has been left idle for at least
one second (1,000 ms). I considered passing the
maximum idle time as a parameter, but it really didn't
seem to be worth doing. I spent a lot of time playing with
this method and it works quite well. That said, you may
need to fine-tune it for different buttons as some are
easier to press than others.
Now we can create the working Menorah code:
pub main | day, level
leds.init(360)
bytefill(@wicks, 0, 12)
cognew(flicker(9), @stack)
At the top, we initialize an object called leds — this is
a 12-channel BAM driver that is set up especially for the
Power 12 PCB, so the only thing we have to specify is the
desired modulation frequency. The next step clears the
array called wicks that will hold our candle brightness
values. Finally, we launch the candle flicker generator into
its own cog using cognew (this is discussed in detail in the
October ‘ 10 issue).
The next step is to get the day number from the user
and then light the Shamash ("helper") candle:
day := getcount(TRIG, 8)
repeat level from 0 to 255
wicks[8] := level
pause(6)
The current day in entered with the getcount()
method which — for a Menorah — is limited to eight. After
returning from getcount(), we light the Shamash candle
which is on channel nine (P8) of the Power 12 board. A
six millisecond delay between each brightness level causes
the "candle" to be fully lit in about a second and a half.
The next step is to light each candle in order, starting
with the current day. A button press is required for each
candle so that there is time for the recitation of blessings
between each:
repeat
pause(1000)
repeat
until (getbutton(TRIG, 50) == true)
repeat level from 0 to 255
wicks[day-1] := level
pause(6)
if (--day == 0)
quit
Within the loop, we allow the last candle to "burn" at
least one second before scanning the button for a new
press. When this is detected, the candle for the day is "lit"