;********************************************* ;* * ;* Low Power Lamp Flicker Generator * ;* Independent Pulse-Width Modulation * ;* on Five Output Port Pins * ;* * ;* Author: Tim Doggett * ;* Start Date: 31Oct03 * ;* Latest Revision Date: 12Jun04 * ;* Latest Revision Number: 0.03 * ;* * ;* Language: AVR Assembly * ;* Device: AVR ATTiny12V * ;* * ;********************************************* ;***** Revision History ***** ; 0.01 Initial Coding ; 0.03 Modify for ATTiny12 ;.DEVICE ATTiny12 ;Use AVR Flash ATTiny12V .INCLUDE "C:\Program Files\Atmel\AVR Tools\AvrAssembler\Appnotes\tn12DEF.inc" ;Constants .EQU bm0 =1<<0 ; Bit0 Mask .EQU bm1 =1<<1 ; Bit1 Mask .EQU bm2 =1<<2 ; Bit2 Mask .EQU bm3 =1<<3 ; Bit3 Mask .EQU bm4 =1<<4 ; Bit4 Mask .EQU bm5 =1<<5 ; Bit5 Mask .EQU bm6 =1<<6 ; Bit6 Mask .EQU bm7 =1<<7 ; Bit7 Mask .EQU kTIMESCALE =0x2 ; timer prescaler to CK/8 .EQU kPWMLEVMIN =0x80 ;lowest value .EQU kPWMLEVMAX =0xFF ;highest .EQU kPWMLEVNOM =0xBF ;nominal bias .EQU kPWMSTPMAX =0x7 ;maximum difference between current PWM and next .EQU kINTERVAL =0x30 ;time delay between changes ;Register aliases .DEF rSTKREG =R0 ;SREG save register .DEF rPWMLEVNOM =R1 ;Reference PWM time .DEF rPWMLEVMAX =R2 ;Maximum PWM time value .DEF rPWMLEVMIN =R3 ;Minimum PWM time value low byte .DEF rPWMSTPMAX =R4 ;Maximum PWM step value low byte .DEF rONBYTE =R10 ;PWM On output constant .DEF rRKl =R14 ;random constant low byte .DEF rRKh =R15 ;random constant high byte .DEF rTEMP1 =R16 .DEF rTEMP2 =R17 .DEF rTEMP3 =R18 .DEF rTEMP4 =R19 .DEF rONTM0 =R20 ;PWM On time 0 .DEF rONTM1 =R21 ;PWM On time 1 .DEF rONTM2 =R22 ;PWM On time 2 .DEF rONTM3 =R23 ;PWM On time 3 .DEF rONTM4 =R24 ;PWM On time 4 .DEF rPWMCOUNT =R25 ;PWM Counter .DEF rRNDl =R26 ;random seed low byte .DEF rRNDh =R27 ;rnd byte .DEF rSTATE =R28 ;output state byte .DEF rDELAYl =R29 ;time counter low byte .CSEG .ORG $00 ;Vector Table Reset: rjmp Init ;Reset handler ExtInt0: reti ;IRQ0 handler PCInt: reti ;Pin change handler TimerInt: rcall TimeTick ;Timer0 overflow handler ERDYInt: reti ;EEPROM Ready handler AnaCompInt: reti ;Analog Comparator handler ;Interrupt Handlers TimeTick: in rSTKREG,SREG ;save status flags subi rDELAYl,1 ;decrement delay counter out SREG,rSTKREG ;restore status flags reti ;continue execution ;Initialization Init: ldi rTEMP1, 0x67 ;init random constant low byte mov rRKl, rTEMP1 ;init random constant low byte ldi rTEMP1, 0x1 ;init random constant high byte mov rRKh,rTEMP1 ;init random constant high byte ; clr rRNDh ;Clear Random seed high byte ; clr rRNDl ;Clear Random seed low byte ldi rTEMP1,kPWMLEVMAX mov rPWMLEVMAX,rTEMP1 ;Minimum PWM time value ldi rTEMP1,kPWMLEVMIN mov rPWMLEVMIN,rTEMP1 ;Maximum PWM time value ldi rTEMP1,kPWMLEVNOM mov rPWMLEVNOM,rTEMP1 ;Nominal PWM time value ldi rTEMP1,kPWMSTPMAX mov rPWMSTPMAX,rTEMP1 ;Maximum PWM value change ; ldi rTEMP1,0xE0 ; mov rONBYTE,rTEMP1 clr rONBYTE ldi rONTM0,kPWMLEVNOM ;Set initial levels ldi rONTM1,kPWMLEVNOM ldi rONTM2,kPWMLEVNOM ldi rONTM3,kPWMLEVNOM ldi rONTM4,kPWMLEVNOM ser rTEMP1 ;TEMP1 to $FF out DDRB,rTEMP1 ;set PORTB as outputs ldi rTEMP1, 0x0 out TCCR0, rTEMP1 ;stop timer ldi rTEMP1, 1<>>>>>>>>>>>>>>> Main program loop <<<<<<<<<<<<<<<<<<<<< Main: SetPWM0:rcall Rand ;Generate random byte mov rTEMP2,rRNDh ;Save random byte for modification mov rTEMP1,rONTM0 ;Save current level value andi rTEMP2,0x1F ;Reduce random number to range 0 to 31 (5 bits) subi rTEMP2,16 ;Change random number to range -16 to 15 add rTEMP1,rTEMP2 ;Add value to current value for output 0 cp rTEMP1,rPWMLEVMIN ;Check for new value below minimum brlo SetPWM1 ;If too low then keep old value cp rPWMLEVMAX,rTEMP1 ;Check for new value above maximum brlo SetPWM1 ;If too high then keep old value mov rONTM0,rTEMP1 ;If within range save new value for output 0 SetPWM1:rcall Rand ;Generate random byte mov rTEMP2,rRNDh ;Save random byte for modification mov rTEMP1,rONTM1 ;Save current level value andi rTEMP2,0x1F ;Reduce random number to range 0 to 31 (5 bits) subi rTEMP2,16 ;Change random number to range -16 to 15 add rTEMP1,rTEMP2 ;Add value to current value for output 1 cp rTEMP1,rPWMLEVMIN ;Check for new value below minimum brlo SetPWM2 ;If too low then keep old value cp rPWMLEVMAX,rTEMP1 ;Check for new value above maximum brlo SetPWM2 ;If too high then keep old value mov rONTM1,rTEMP1 ;If within range save new value for output 1 SetPWM2:rcall Rand ;Generate random byte mov rTEMP2,rRNDh ;Save random byte for modification mov rTEMP1,rONTM2 ;Save current level value andi rTEMP2,0x1F ;Reduce random number to range 0 to 31 (5 bits) subi rTEMP2,16 ;Change random number to range -16 to 15 add rTEMP1,rTEMP2 ;Add value to current value for output 2 cp rTEMP1,rPWMLEVMIN ;Check for new value below minimum brlo SetPWM3 ;If too low then keep old value cp rPWMLEVMAX,rTEMP1 ;Check for new value above maximum brlo SetPWM3 ;If too high then keep old value mov rONTM2,rTEMP1 ;If within range save new value for output 2 SetPWM3:rcall Rand ;Generate random byte mov rTEMP2,rRNDh ;Save random byte for modification mov rTEMP1,rONTM3 ;Save current level value andi rTEMP2,0x1F ;Reduce random number to range 0 to 31 (5 bits) subi rTEMP2,16 ;Change random number to range -16 to 15 add rTEMP1,rTEMP2 ;Add value to current value for output 3 cp rTEMP1,rPWMLEVMIN ;Check for new value below minimum brlo SetPWM4 ;If too low then keep old value cp rPWMLEVMAX,rTEMP1 ;Check for new value above maximum brlo SetPWM4 ;If too high then keep old value mov rONTM3,rTEMP1 ;If within range save new value for output 3 SetPWM4:rcall Rand ;Generate random byte mov rTEMP2,rRNDh ;Save random byte for modification mov rTEMP1,rONTM4 ;Save current level value andi rTEMP2,0x1F ;Reduce random number to range 0 to 31 (5 bits) subi rTEMP2,16 ;Change random number to range -16 to 15 add rTEMP1,rTEMP2 ;Add value to current value for output 4 cp rTEMP1,rPWMLEVMIN ;Check for new value below minimum brlo SetDelayTime ;If too low then keep old value cp rPWMLEVMAX,rTEMP1 ;Check for new value above maximum brlo SetDelayTime ;If too high then keep old value mov rONTM4,rTEMP1 ;If within range save new value for output 4 SetDelayTime: ldi rDELAYl,kINTERVAL ;Reset time until next value change T0: cp rPWMCOUNT,rONTM0 ;Compare counter to value for output 0 brlo T1 ;If count is less than value then continue ori rSTATE,bm0 ;otherwise, prepare to turn output 0 off T1: cp rPWMCOUNT,rONTM1 ;Compare counter to value for output 1 brlo T2 ;If count is less than value then continue ori rSTATE,bm1 ;otherwise, prepare to turn output 1 off T2: cp rPWMCOUNT,rONTM2 ;Compare counter to value for output 2 brlo T3 ;If count is less than value then continue ori rSTATE,bm2 ;otherwise, prepare to turn output 2 off T3: cp rPWMCOUNT,rONTM3 ;Compare counter to value for output 3 brlo T4 ;If count is less than value then continue ori rSTATE,bm3 ;otherwise, prepare to turn output 3 off T4: cp rPWMCOUNT,rONTM4 ;Compare counter to value for output 4 brlo PWMCnt ;If count is less than value then continue ori rSTATE,bm4 ;otherwise, prepare to turn output 4 off PWMCnt: mov rTEMP1,rSTATE ;Copy output bit states com rTEMP1 ;Invert output bits value out PORTB,rTEMP1 ;Set outputs inc rPWMCOUNT ;Increment counter brne Del1 ;If count rolls over (reaches 256 = 0) mov rSTATE,rONBYTE ;then set bits to turn on Del1: tst rDELAYl ;Check for timeout of current values brne T0 ;If not, then repeat with current values rjmp Main ;If so, then pick new values ;**************************** Subroutines ****************************** ;>>>>>>>>> pseudo-random byte generator <<<<<<<<<<<<<<<<<<< Rand: mov rTEMP3, rRNDl ;save seed l mov rTEMP4, rRNDh ;save seed h ;multiply seed by 181 mul181: lsl rRNDl ;mul * 4 rol rRNDh ; lsl rRNDl ; rol rRNDh ;end mul add rRNDl, rTEMP3 ;add seed l adc rRNDh, rTEMP4 ;add seed h lsl rRNDl ;mul * 2 rol rRNDh ;end mul add rRNDl, rTEMP3 ;add seed l adc rRNDh, rTEMP4 ;add seed h lsl rRNDl ;mul * 4 rol rRNDh ; lsl rRNDl ; rol rRNDh ;end mul add rRNDl, rTEMP3 ;add seed l adc rRNDh, rTEMP4 ;add seed h lsl rRNDl ;mul * 4 rol rRNDh ; lsl rRNDl ; rol rRNDh ;end mul add rRNDl, rTEMP3 ;add seed l adc rRNDh, rTEMP4 ;add seed h ;add 359 to result add359: add rRNDl, rRKl adc rRNDh, rRKh ;return from call ret