![]() |
AVR-Anwendungen Zufallszahlen mit ATtiny13 Software für Zufallszahlen in Assembler |
;
; ***********************************
; * Random color generator *
; * ATtiny13(A) and one RGB-LED, V1 *
; * (C)2019 by Gerhard Schmidt *
; ***********************************
;
.nolist
.include "tn13adef.inc" ; Define device ATtiny13A
.list
;
; **********************************
; S W I T C H E S
; **********************************
;
; Mode 1: Display calculated randoms only
.equ swCalcOnly = 0
;
; Mode 2: Display noise generator randoms only
.equ swNoiseOnly = 0
;
; Mode 3: Display calculated and noise randoms mixed
.equ swMixed = 1
;
; Always only one PWM cycle
.equ sw1Pwm = 0 ; No matter what the poti says
;
; Check modes
.if (swCalcOnly==1)&&(swNoiseOnly==1)
.error "Mode can not be 1 and 2!"
.endif
.if (swCalcOnly==1)&&(swMixed==1)
.error "Mode can not be 1 and 3!"
.endif
.if (swNoiseOnly==1)&&(swMixed==1)
.error "Mode can not be 2 and 3!"
.endif
.if (swCalcOnly==0)&&(swNoiseOnly==0)&&(swMixed==0)
.error "Mode either 1, 2 or 3!"
.endif
;
; **********************************
; S I M U L A T I O N S W I T C H
; **********************************
;
; Generate only random numbers
.equ swRandomOnly = 0 ; Simulate number generation only
;
; Simulate the multiplication
.equ swSimMult = 0 ; Simulate multiplication
.equ swSimMultAdc = 1023 ; ADC result to simulate
;
; **********************************
; H A R D W A R E
; **********************************
;
;
; Device: ATtiny13(A), Package: 8-pin-PDIP_SOIC
;
; _________
; 1 / |8
; Reseto--|RESET VCC|--o +5V
; Speedo--|PB3 PB2|--o LED Blue
; Noiseo--|PB4 PB1|--o LED Green
; 0V o--|GND PB0|--o LED Red
; 4 |__________|5
;
; **********************************
; P O R T S A N D P I N S
; **********************************
;
.equ bBlue = DDB2 ; Blue LED on pin PB2
.equ bGreen = DDB1 ; Green LED on pin PB1
.equ bRed = DDB0 ; Red LED on pin PB0
;
; **********************************
; A D J U S T A B L E C O N S T
; **********************************
;
.equ clock=1200000 ; Define the clock frequency
.equ PwmFreq = 73 ; PWM frequency in Hz
;
; Longest delay per color, max 894.7 seconds
.equ cLedLong = 100 ; Longest delay in tens of ms
;
; Init values of the random generator
.equ cN1Start = 0xA8 ; The highest homogenity values
.equ cN2Start = 0x02 ; derived from 100k calculations
;
; Input voltage of the random noise input
.equ cNoiseHigh = 0 ; 1:0..5V, 0:0..1.1V
;
; In mixed mode: restart seeds after n calculations
.equ cRndCount = 15 ; Calculate 15 random numbers
;
; **********************************
; F I X & D E R I V. C O N S T
; **********************************
;
; cCtcDiv determines the PWM speed
.equ cCtcCmpA=((clock+128)/256+PwmFreq/2)/PwmFreq - 1 ; Compare A
.if cCtcCmpA<=31
.error "PWM frequency is too high! Reduce it!"
.endif
;
; Delay multiplication, ADC-Multiplier
; The value that (1024-Nadc) has to be muliplied with to
; get the precise scaling of the speed potentiometer
.equ cMultiplier = (((cLedLong*clock/(cCtcCmpA+1))+512)/1024)/100
.if (4*cMultiplier)>65535
.error "Time too long!"
.endif
;
.if cNoiseHigh==1
.equ cRef=0 ; Reference voltage is 5 V
.else
.equ cRef=1<<REFS0 ; Reference voltage is 1.1V
.endif
;
; **********************************
; R E G I S T E R S
; **********************************
;
; Used: R0 to R3 for multiplication of 16-bit by 10-bit (1024-ADC)
.def rRnd1 = R4 ; Random number from external noise, HSB
.def rRnd2 = R5 ; dto., MSB
.def rRnd3 = R6 ; dto., LSB
.def rSpeedL = R7 ; Speed setting, LSB
.def rSpeedH = R8 ; dto., MSB
.def rRed = R9 ; RGB compare value, red
.def rGreen = R10 ; dto., green
.def rBlue = R11 ; dto., blue
.def rPwm = R12 ; PWM phase counter
.def rN1 = R13 ; Random number 1
.def rN2 = R14 ; Random number 2
.def rSreg = R15 ; Save/Restore status port
.def rmp = R16 ; Define multipurpose register
.def rimp = R17 ; Multipurpose inside ISRs
.def rFlag = R18 ; Flag register
.equ bAdc = 0 ; ADC complete, convert
.def rStart = R19 ; Start value for PWM
.def rWork = R20 ; Work register for PWM
.def rRndC = R21 ; Counter for mixed operation only
; free: R22 to R23
.def rCntL = R24 ; 16-Bit duration counter, LSB
.def rCntH = R25 ; dto., MSB
; Used: R27:R26 = X for 10-bit-by-16-bit multiplication
; Used: R29:R28 = Y for multiplication
; used: R31:R30 = Z for ADC result and multiplication
;
; **********************************
; S R A M
; **********************************
;
.dseg
.org SRAM_START
; (No SRAM used, only for stack operations)
;
; **********************************
; C O D E
; **********************************
;
.cseg
.org 000000
;
; **********************************
; R E S E T & I N T - V E C T O R S
; **********************************
rjmp Main ; Reset vector
reti ; INT0 External Interrupt Request 0
reti ; PCINT0 Pin Change Interrupt Request 0
reti ; TIM0_OVF Timer/Counter Overflow
reti ; EE_RDY EEPROM Ready
reti ; ANA_COMP Analog Comparator
rjmp Tc0Isr ; TIM0_COMPA Timer/Counter Compare Match A
reti ; TIM0_COMPB Timer/Counter Compare Match B
reti ; WDT Watchdog Time-out
rjmp AdcIsr ; ADC Conversion Complete
;
; **********************************
; I N T - S E R V I C E R O U T .
; **********************************
;
; TC0 Compare match interrupt service routine
Tc0Isr: ; 7 clock cycles for int and vector jump
in rSreg,SREG ; Save SREG, +1 = 8
out DDRB,rWork ; Write rWork to LEDs, +1 = 9
inc rPwm ; Next PWM phase, +1 = 10
breq Tc0IsrPwmRst ; +1/2 = 11/12
cp rRed,rPwm ; Compare red, +1 = 12
brne Tc0Isr1 ; Not equal, +1/2 = 13/14
cbr rWork,1<<bRed ; Red off, +1 = 14
Tc0Isr1: ; 14 clock cycles
cp rGreen,rPwm ; Compare green, +1 = 15
brne Tc0Isr2 ; Not equal, +1/2 = 16/17
cbr rWork,1<<bGreen ; Green off, +1 = 17
Tc0Isr2: ; 17 clock cycles
cp rBlue,rPwm ; Compare blue, +1 = 18
brne Tc0Isr3 ; Not equal, +1/2 = 19/20
cbr rWork,1<<bBlue ; Blue off, +1 = 20
Tc0Isr3: ; 20 clock cycles
out SREG,rSreg ; Restore SREG, +1 = 21
reti ; +4 = 25 clock cycles
Tc0IsrPwmRst: ; Restart PWM, 12 clock cycles
sbiw rCntL,1 ; Count down, +2 = 14
brne Tc0IsrPwmStart ; +1/2 = 15/16
mov rCntH,rSpeedH ; Reload counter, MSB, +1 = 16
mov rCntL,rSpeedL ; dto., LSB, +1 = 17
.if (swCalcOnly == 1)||(swMixed == 1)
; Executed if external random generator is off or mixed
eor rN1,rN2 ; Calc first random, +1 = 18
swap rN1 ; +1 = 19
add rN2,rN1 ; +1 = 20
mov rRed,rN1 ; +1 = 21
eor rN1,rN2 ; Calc second random, +1 = 22
swap rN1 ; +1 = 23
add rN2,rN1 ; +1 = 24
mov rGreen,rN1 ; +1 = 25
eor rN1,rN2 ; Calc second random, +1 = 26
swap rN1 ; +1 = 27
add rN2,rN1 ; +1 = 28
mov rBlue,rN1 ; +1 = 29
.if swMixed == 1
; Mixed operation, count mixed down
tst rRndC ; Counter already at zero?
breq Tc0IsrCnt
dec rRndC ; Count down
Tc0IsrCnt:
.endif
.else
; Executed if external random generator is only source
mov rRed,rRnd1 ; Get generated random, red, +1 = 18
mov rGreen,rRnd2 ; dto., green, +1 = 19
mov rBlue,rRnd3 ; dto., blue, +1 = 20
.endif
; 29/20 clock cycles
clr rStart ; Start with zero, +1 = 30/21
clr rimp ; Compare value zero, +1 = 31/22
cpse rRed,rimp ; Skip next if red zero, +1/2 = 32/23/33/24
sbr rStart,1<<bRed ; Red on, +1 = 33/24
; 33/24 clock cycles
cpse rGreen,rimp ; Skip next if green zero, +1/2 = 34/25/35/26
sbr rStart,1<<bGreen ; Green on, +1 = 35/26
; 35/26 clock cycles
cpse rBlue,rimp ; Skip next if blue zero, +1/2 = 36/27/37/28
sbr rStart,1<<bBlue ; Blue on, +1 = 37/28
Tc0IsrPwmStart: ; 16/37/28
mov rWork,rStart ; +1 = 17/38/29
out SREG,rSreg ; Restore SREG, +1 = 18/39/30
reti ; +4 = 22/43/34
; Maximum = 43 clock cycles if external random
; generator is not selected
;
; ADC complete interrupt service routine
AdcIsr:
in rSreg,SREG ; Save SREG
sbr rFlag,1<<bAdc ; Set ADC flag
out SREG,rSreg ; Restore SREG
reti
;
; **********************************
; M A I N P R O G R A M I N I T
; **********************************
;
Main:
ldi rmp,Low(RAMEND)
out SPL,rmp ; Init LSB stack pointer
;
; Simulation of multpication only
.if swSimMult == 1 ; Simulate multiplication
ldi ZH,High(swSimMultAdc) ; Simulate ADC result, MSB
ldi ZL,Low(swSimMultAdc) ; dto., LSB
rcall AdcCalc3 ; Multiply
Loop1:
rjmp Loop1
.endif
; Init the random generator
ldi R16,cN1Start
mov rN1,R16
ldi R16,cN2Start
mov rN2,R16
;
; Calculation of random numbers only?
.if swRandomOnly == 1
rjmp RandomOnly
.endif
;
; Init the colors
rcall Colors
;
; Init TC0 as PWM counter in CTC mode
ldi rmp,cCtcCmpA ; Set compare A
out OCR0A,rmp ; in Compare A port
ldi rmp,1<<WGM01 ; Set CTC mode
out TCCR0A,rmp ; in TC0 control port A
ldi rmp,1<<CS00 ; Prescaler=1
out TCCR0B,rmp ; in TC0 control port B
ldi rmp,1<<OCIE0A ; Set TC0 interrupt mask compare A
out TIMSK0,rmp ; in TC0 int mask
; Init speed and PWM registers
ldi ZH,High(3*PwmFreq) ; Three seconds, MSB
ldi ZL,Low(3*PwmFreq) ; dto., LSB
mov rSpeedH,ZH ; Copy to speed register, MSB
mov rSpeedL,ZL ; dto., LSB
mov rCntH,ZH ; and to counter, MSB
mov rCntL,ZL ; dto., LSB
ldi rStart,0x00 ; All LEDs off
ldi rWork,0x00 ; All LEDs off
out DDRB,rWork ; And in port direction
; Init ADC for random generator and speed pot
ldi rmp,1<<ACD ; Disable analog comparator
out ACSR,rmp ; in analog comparator status port register
ldi rmp,(1<<ADC2D)|(1<<ADC3D) ; Disable digital inputs on ADC channels
out DIDR0,rmp ; in digital input disable port register
ldi rmp,(1<<MUX1)|(1<<MUX0)|cRef ; MUX to channel ADC3
out ADMUX,rmp ; and to ADMUX
ldi rmp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rmp ; Start first conversion
ldi rCntH,High(1)
ldi rCntL,Low(1)
; Sleep mode
ldi rmp,1<<SE ; Sleep idle mode
out MCUCR,rmp ; in master control port
sei ; Enable interrupts
;
; **********************************
; P R O G R A M L O O P
; **********************************
;
Loop:
sleep ; Go to bed
nop ; Dummy after wake-up
sbrc rFlag,bAdc ; ADC flag set?
rcall AdcCalc ; Handle ADC flag
rjmp loop
;
; Flag handling routines
AdcCalc: ; Handle ADC flag
cbr rFlag,1<<bAdc ; Clear ADC flag
in ZL,ADCL ; Read ADC result, LSB first
in ZH,ADCH ; dto., MSB next
in rmp,ADMUX ; Read current channel
cpi rmp,(1<<MUX1)|(1<<MUX0)|cRef ; Channel ADC3?
breq AdcCalc3 ; To channel ADC3: speed pot
ldi rmp,(1<<MUX1)|(1<<MUX0)|cRef ; MUX to channel ADC3
out ADMUX,rmp ; and to ADMUX
ldi rmp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rmp ; Start next conversion
mov rmp,ZL ; Check zero read
or rmp,ZH
breq AdcCalc2 ; Zero, skip
cpi ZL,0xFF ; Result = 0x3F?
brne AdcCalc1 ; No
cpi ZH,0x03 ; Check MSB
breq AdcCalc2 ; MSB = 0x03, skip
AdcCalc1:
lsr ZL ; Lowest bit to carry
rol rRnd1 ; and into LSB
rol rRnd2 ; and into MSB
rol rRnd3 ; and into HSB
.if swMixed == 1
tst rRndC ; Counter at zero?
brne AdcCalc2 ; No, continue
mov rN1,rRnd1 ; Restart random seed
mov rN2,rRnd2 ; dto.
ldi rRndC,cRndCount
.endif
AdcCalc2:
ret
AdcCalc3: ; Channel ADC3 measured
ldi rmp,(1<<MUX1)|cRef ; MUX to channel ADC2
out ADMUX,rmp ; and to ADMUX
ldi rmp,(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)
out ADCSRA,rmp ; Start next conversion
ldi rmp,255
mov rRed,rmp
clr R0 ; Subtract 0x0400 from ADC result
ldi rmp,0x04
mov R1,rmp
sub R0,ZL ; Subtract LSB
sbc R1,ZH ; and MSB
clr R2
clr R3
ldi XH,High(cMultiplier) ; X is multiplier
ldi XL,Low(cMultiplier)
clr YL ; Result = 0
clr YH
clr ZL
clr ZH
AdcCalc4:
lsr XH ; Shift multiplier, MSB
ror XL ; dto., LSB
brcc AdcCalc5
add YL,R0 ; Add ADC result, Byte1
adc YH,R1 ; dto., Byte2
adc ZL,R2 ; dto., Byte3
adc ZH,R3 ; dto., Byte4
AdcCalc5:
tst XH ; Check end of multiplication, MSB
brne AdcCalc6
tst XL ; dto., LSB
breq AdcCalc7 ; End of multiplication
AdcCalc6:
lsl R0 ; Shift multiplicator left, Byte1
rol R1 ; dto., Byte2
rol R2 ; dto., Byte3
rol R3 ; dto., Byte4
rjmp AdcCalc4 ; Continue multiplication
AdcCalc7:
ldi rmp,0x80 ; Round up
add rmp,YL
ldi rmp,1 ; Add 1
adc YH,rmp ; Add to LSB
ldi rmp,0
adc ZL,rmp ; dto., to MSB
adc ZH,rmp ; dto., to HSB
tst ZH ; Overflow to HSB?
breq AdcCalc8
ldi ZL,0xFF ; To max, MSB
ldi YH,0xFF ; To max, LSB
AdcCalc8:
.if sw1Pwm==1
ldi YH,1
ldi ZL,0
.endif
mov rSpeedH,ZL ; Copy result to speed value, MSB
mov rSpeedL,YH ; dto., LSB
AdcCalc9:
ret
;
; Calculate next three random colors
Colors:
eor rN1,rN2
swap rN1
add rN2,rN1
mov rRed,rN1
eor rN1,rN2
swap rN1
add rN2,rN1
mov rGreen,rN1
eor rN1,rN2
swap rN1
add rN2,rN1
mov rBlue,rN1
ret
;
; Calculate random numbers only
RandomOnly:
eor rN1,rN2
swap rN1
add rN2,rN1
rjmp RandomOnly
;
; End of source code
;
; Time stamp
.ifdef ATtiny13A
.db "Assembled:"
.db NOW_Y,'-',NOW_M,'-',NOW_D,'='
.dw NOW_I
.endif
;
; Copyright information
.db "(C)2019 by Gerhard Schmidt " ; Source code readable
.db "C(2)10 9ybG reahdrS hcimtd " ; Machine code format
;
Seitenanfang | Berechnung | Anzeigen | Rauschgenerator | Analyse |
---|