Path: Home => AVR-EN => Applications => Random ATtiny13 => Source code   Diese Seite in Deutsch: Flag DE Logo
Random colors 250*250 AVR applications

Random number generation with ATtiny13
Source code for displaying random numbers on a RGB LED

Assembler source code for displaying randoms with an ATtiny13

The assembler source code in asm format is here.

;
; ***********************************
; * 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
;



Page top Main page Calculation Display Noise generation Analysis sine wave


Praise, error reports, scolding and spam please via the comment page to me.

©2020 by http://www.avr-asm-tutorial.net