For my friends at House of Restless Spirits (http://houseofrestlessspirits.com) in Santa Monica I hacked one of their old FC-4s to created a lamp flicker.
Tip: Code can be pretty simple when using incandescent lamps because the thermal inertia of the filament smooths things out -- in many cases there is no need for complicated ramping.
This particular prop is controlled by a video player. A control tone on the video tells the lamp to flicker; when the tone drops out, so does the light. We used a TD-1 connected to the SERIAL port on the FC-4.
Here's the code (built on the code base of the original FC-4, so it could flicker up to four channels). Of course, you'll need an SX-Key or SX-Blitz to reprogram the FC-4; sadly, those devices went extinct a couple years ago.
' =========================================================================
'
' File...... HORS_Lantern.SXB
' Purpose...
' Author.... JonnyMac
' E-mail....
' Started...
' Updated... 27 OCT 2013
'
' =========================================================================
' -------------------------------------------------------------------------
' Program Description
' -------------------------------------------------------------------------
' -------------------------------------------------------------------------
' Conditional Compilation Symbols
' -------------------------------------------------------------------------
' -------------------------------------------------------------------------
' Device Settings
' -------------------------------------------------------------------------
DEVICE SX20, OSCHS2, TURBO, STACKX, OPTIONX, BOR42
FREQ 50_000_000
ID "Lantern"
' -------------------------------------------------------------------------
' IO Pins
' -------------------------------------------------------------------------
Sio PIN RA.3 INPUT ' serial I/O to host
BaudRate PIN RA.2 INPUT PULLUP ' B/R select input
A1 PIN RA.1 INPUT PULLUP ' address jumpers (%00-%11)
A0 PIN RA.0 INPUT PULLUP
Lamps PIN RB
UnusedRB7 PIN RB.7 INPUT PULLUP
UnusedRB6 PIN RB.6 INPUT PULLUP
UnusedRB5 PIN RB.5 INPUT PULLUP
ZCross PIN RB.4 INPUT
Lamp4 PIN RB.3 OUTPUT
Lamp3 PIN RB.2 OUTPUT
Lamp2 PIN RB.1 OUTPUT
Lamp1 PIN RB.0 OUTPUT
' -------------------------------------------------------------------------
' Constants
' -------------------------------------------------------------------------
YES CON 1
NO CON 0
IS_ON CON 1
IF_OFF CON 0
NO_TONE CON 1
HAS_TONE CON 0
' -------------------------------------------------------------------------
' Variables
' -------------------------------------------------------------------------
flags VAR Byte
isrFlag VAR flags.0
idx VAR Byte
lottery VAR Byte
tmpB1 VAR Byte ' sub/func work vars
tmpB2 VAR Byte
tmpB3 VAR Byte
tmpW1 VAR Word
dimmer VAR Byte (9) ' bank for dimmer vars
chan1 VAR dimmer(0) ' channel brightness
chan2 VAR dimmer(1)
chan3 VAR dimmer(2)
chan4 VAR dimmer(3)
acc1 VAR dimmer(4) ' channel brightness timer
acc2 VAR dimmer(5)
acc3 VAR dimmer(6)
acc4 VAR dimmer(7)
dimmerTix VAR dimmer(8) ' ISR divider
target VAR Byte (4)
speed VAR Byte (4)
tix VAR Byte (4)
' =========================================================================
INTERRUPT NOCODE 153_600 ' every 6.51 uS
' =========================================================================
Mark_ISR:
ASM
BANK $00 ' (1)
SETB isrFlag ' (1)
ENDASM
' -----------------
' Dimmer processing
' -----------------
Check_Dimmer_Tix:
ASM
BANK dimmer ' (1)
INC dimmerTix ' (1) update dimmer divider
CJB dimmerTix, #5, Dimmer_Done ' (4/6) ready for service?
CLR dimmerTix ' (1) yes, reset and go
' Dimmer service runs every 32.55 uS (256 levels x 120 Hz)
' -- inspired by code from Phil Short
'
Dimmer_Service:
JNB ZCross, Update_Triacs ' (2/4) skip if not at ZC
Zero_Cross:
CLR Lamps ' (1) all triacs off
MOV acc1, chan1 ' (2) reset dimming timers
MOV acc2, chan2 ' (2)
MOV acc3, chan3 ' (2)
MOV acc4, chan4 ' (2)
Update_Triacs:
INC acc1 ' (1) increment accumulator
SNZ ' (1/2) skip if no roll-over
SETB Lamp1 ' (1) otherwise triac on
INC acc2 ' (1)
SNZ ' (1/2)
SETB Lamp2 ' (1)
INC acc3 ' (1)
SNZ ' (1/2)
SETB Lamp3 ' (1)
INC acc4 ' (1)
SNZ ' (1/2)
SETB Lamp4 ' (1)
Dimmer_Done:
BANK $00
ENDASM
RETURNINT
' -------------------------------------------------------------------------
' Subroutine Declarations
' -------------------------------------------------------------------------
DELAY_MS SUB 1, 2 ' delay in milliseconds
RANDOMIZE FUNC 2, 1, 2 ' 8/16-bit random
' =========================================================================
PROGRAM Start
' =========================================================================
Start:
dimmer(1) = 0
dimmer(2) = 0
dimmer(3) = 0
lottery = 31
Main:
IF Sio = NO_TONE THEN Lamp_Off
Lamp_On:
lottery = RANDOMIZE lottery
tmpB1 = lottery // 85
dimmer(0) = 255 - tmpB1
lottery = RANDOMIZE lottery
tmpB1 = lottery >> 2
speed(0) = tmpB1 + 75
Dim_Hold:
IF Sio = NO_TONE THEN Lamp_Off
IF speed(0) = 0 THEN Main
DELAY_MS 1
DEC speed(0)
GOTO Dim_Hold
Lamp_Off:
dimmer(0) = 0
DELAY_MS 1
IF Sio = NO_TONE THEN Lamp_Off
GOTO Lamp_On
' -------------------------------------------------------------------------
' Subroutine Code
' -------------------------------------------------------------------------
' Use: DELAY_MS ms
' -- delay in ~milliseconds; uses ISR
' -- ideal ISR count is 153.6
SUB DELAY_MS
mSecs VAR __WPARAM12
msTix VAR __PARAM3
\ SB __PARAMCNT.1
\ CLR mSecs_MSB
DO WHILE mSecs > 0 ' time left?
msTix = 153 + mSecs.0 ' (re)load 1 ms timer
DO WHILE msTix > 0
\ CLRB isrFlag ' clear ISR flag
\ JNB isrFlag, $ ' wait for next flag
\ DEC msTix ' update 1 ms timer
LOOP
DEC mSecs ' update delay timer
LOOP
ENDSUB
' -------------------------------------------------------------------------
FUNC RANDOMIZE
IF __PARAMCNT = 1 THEN ' byte parameter?
tmpW1_LSB = __PARAM1
RANDOM tmpW1_LSB
tmpW1_MSB = 0
ELSE
tmpW1 = __WPARAM12
RANDOM tmpW1
ENDIF
RETURN tmpW1
ENDFUNC