;***************************************************************************
; Application:  random light blinker.
; Author:       Dan Williams
; Date:         dec 2004
; Assembler:    
; Target:       Atmel ATtiny13.
;***************************************************************************
;
; notes:
;
;****************************************************************************

.device ATtiny13 

; ------------- Memory locations ---------------
;
;  .def bar =r01 ; one byte ram location
;
; ----------------------------------------------

; R 0 ->15 are gen. purp.

.def A          = r16    
.def B          = r17   ;
.def C          = r18
.def D          = r19

.def rnd1       = r20   ; the random number.
.def rnd2       = r21
.def rnd3       = r22
.def rnd4       = r23
.def temp1      = r24
.def count1     = r25
.def count2     = r26
.def count3     = r27
.def kick1      = r28 ; timeout
.def _Y         = r29
.def _Z         = r30


;cant use r25 -> r31

; ------------- Equates ------------------

.equ INPUT   = 0
.equ OUTPUT  = 1

; --- Port Directions ---
.equ PB0DIR  = INPUT ; !!!???!!! changeme
.equ PB1DIR  = OUTPUT
.equ PB2DIR  = INPUT
.equ PB3DIR  = INPUT
.equ PB4DIR  = INPUT
.equ PB5DIR  = INPUT

; --- Initial port state ---
.equ INPB0   = 0  ; !!!???!!! changeme
.equ INPB1   = 0
.equ INPB2   = 0
.equ INPB3   = 0
.equ INPB4   = 0
.equ INPB5   = 0

; --- Port Names ---
.equ PORT1    = 0  ;
.equ PORT2    = 1  ; !!!???!!! changeme's
.equ PORT3    = 2  ; 
.equ PORT4    = 3  ;
.equ PORT5    = 4  ;
.equ PORT6    = 5  ;

; --- amalgimate ---

.equ INITDIR   = ((PB5DIR<<DDB5)|(PB4DIR<<DDB4)|(PB3DIR<<DDB3)|(PB2DIR<<DDB2)|(PB1DIR<<DDB1)|(PB0DIR<<DDB0))
.equ INITSTATE = ((INPB5<<PORTB5)|(INPB4<<PORTB4)|(INPB3<<PORTB3)|(INPB2<<PORTB2)|(INPB1<<PORTB1)|(INPB0<<PORTB0))

.equ CH1  = 1
.equ CH2  = 0  ; not used
.equ CH3  = 2  ; not used

;========================| SYSTEM VECTORS |===========================
;
.cseg                                   ;CODE segment
.org 0x0000
    rjmp    init   ; RESET 
    reti           ; EXT_INT0  
    reti           ; PCINT0   (pin change)
    reti           ; TIM0_OVF  
    reti           ; EE_RDY  
    reti           ; ANA_COMP  
    reti           ; TIM0_COMPA  
    reti           ; TIM0_COMPB  
    reti           ; WATCHDOG  
    reti           ; ADC  

;=============================| MAIN |================================
;


.org 0x000A
init:   
        ; Set up stack
        ldi     A,   low(RAMEND)        ; load low address of ram to R16...
        out     SPL, A               ; Set Stack Pointer to top of RAM

        ; Disable interrupts
        cli        

        ; Set up io ports
        ldi   A,    INITSTATE
        out   PORTB, A
        ldi   A,    INITDIR
        out   DDRB,  A      


   ldi rnd1, 0xDA   ; random seed

   rcall adc_init
 ;  rcall pwm_init
   
 

MainLoup:
     
        rcall random
        cpi   rnd1, 110
        
        brlo  skip
          sbic PORTB, CH1
          rjmp on
            ; kick it back on if off for <3
          ;  inc kick1
          ;  cpi kick1, 0x02
          ;  brge on
            ; kick            
            sbi  PORTB, CH1
            rjmp skip 
            
on:        
          clr kick1
          cbi PORTB, CH1
 
skip:
        
        rcall wait  
        
        
     ;   IN  A, ADCH
     ;   OUT OCR0A, A      
     
        rjmp    MainLoup                ; go back and do it all over again


;========================| SUBROUTINES |==============================
;

random:    
    mov   A,rnd4      ; BIT 25 TO CARRY
    ror   A    
    mov   rnd4,rnd3    
    mov   rnd3,rnd2    
    mov   rnd2,rnd1   ; SHIFT ALL BYTES LEFT
    
    mov   A,rnd4      ; WAS rnd3
    ror   A           ; GET BIT 25 (IN CARRY) INTO OLD rnd3
    mov   temp1,A     ; SAVE IT FOR LATER
    
    mov   A,rnd1    
    rol   A           ; BIT 1 TO 7 IN POSITION
    mov   rnd1,A      ; PUT BACK
    
    mov   A,temp1     ; RESTORE A
    eor   A,rnd1      ; MOD 2 SUM OF ALL BITS IN rnd1 AND THE CARRY BIT (exclusive or)
    mov   temp1,A     ; SAVE IT
    
    mov   A,rnd4    
    ror   A    
    mov   rnd4,A      ; ROTATE rnd4
    
    mov   A,rnd3    
    ror   A    
    mov   rnd3,A      ; ROTATE rnd3
    
    mov   A,rnd2    
    ror   A    
    mov   rnd2,A      ; ROTATE rnd2
    
    mov   A,temp1     ; RESTORE A
    rol   A    
    mov   rnd1,A      ; xor OVER-WRITES ALL 8 BITS, BUT DOESN'T MATTER
  ret    


; ----------------------------
; wait subroutine 
; ----------------------------
wait:  
      IN      count2, ADCH  
    ;  mov     count2, A              ; load count2 with decimal 200

d2:
	      ldi	count3,50

d3:
	      dec	count3
	      brne	d3
      dec     count2                  ; decrement count2
      brne    d2                      ; loop if not zero              
  ret
    


adc_init:
  ; set up adc1 as analog input
  ldi A, 0x04
  out DIDR0, A
  ; auto trigger to free running
  ldi A, 0x00
  out ADCSRB, A
  ; set mux channel
  ldi A, 0x23
  out ADMUX, A
  ; turn system on
  ldi A, 0xEE
  out ADCSRA, A
 ret



pwm_init:
  ; clear pwm levels
  ldi  A, 0x3F
  out  OCR0A, A 
  ldi  A, 0xBF
  out  OCR0B, A
  ; set up TCCR0A
  ldi  A, 0xA3
  out  TCCR0A, A
  ; set up TCCROB
  ldi  A, 0x02
  out  TCCR0B, A
 ret









