;  No Copyright
;
;  The person who associated a work with this deed has dedicated the work to the
;  public domain by waiving all of his or her rights to the work worldwide under
;  copyright law, including all related and neighboring rights, to the extent
;  allowed by law.
;
;  You can copy, modify, distribute and perform the work, even for commercial
;  purposes, all without asking permission.
;
;  See https://creativecommons.org/share-your-work/public-domain/cc0/ for more
;  information on the license.


;  This file is part of the wake-up-bright led lamp project, made by
;  Maarten Tromp <maarten@geekabit.nl>, 2009 - 2014.
;
;  More info on the project: https://www.geekabit.nl/projects/wake-up-bright/


;  Version history:
;  2009-09-06  first version
;  2009-09-09  10 bits pwm
;  2010-11-22  fix for flashing led on powerup
;  2011-11-02  brighter led
;  2011-11-08  better exponential curve
;  2014-01-13  ported to tiny2313 for 16bit pwm


.include "tn2313def.inc"	; include register defenitions for this proc

; register defenitions
	.def zero		= r16	; always holds 0
	.def tmp		= r17	; general purposse temp register
	.def ps			= r18	; counter for prescaler delay
	.def brightH	= r19	; led brightness
	.def brightM	= r20	; 
	.def brightL	= r21	; 

; static values
	.cseg					; code segment
	.org 0					; code starts at address 0
	.equ led		= PB3
	.equ ps_max		= 35	; prescaler delay 35 -> ~15 min

; interrupt vectors
	rjmp reset				; reset
	reti					; external int0
	reti	 				; external int1
	reti					; timer1 capture
	reti					; timer1 compare match
	rjmp t1_of				; timer1 (16bit) overflow
	reti					; timer0 (8bit) overflow
	reti					; uart rx complete
	reti					; udr empty
	reti					; uart tx complete
	reti					; analog comparator
	reti					; pin change int
	reti					; timer 1 compare B
	reti					; timer 0 compare A
	reti					; timer 0 compare B
	reti					; USI start
	reti					; USI overflow
	reti					; EEPROM ready
	reti					; Watchdog ovf

reset:
	ldi tmp, RAMEND			; stackpointer
	out spl, tmp

	; init variables
	ldi zero, 0
	ldi brightH, 0			; initial brighness
	ldi brightM, $01
	ldi brightL, 0
	ldi ps, 0				; counter for prescaler delay

	; setup ports
	ldi tmp, 0	 			; set all pins (including led) to input
	out PORTB, tmp			; led will be set to output later
	out DDRB, tmp			; once pwm has settled
	
	; timer1 pwm
	ldi tmp, (1<<WGM11)+(1<<COM1A1)	; enable pwm mode 14, OC1 as pwm output
	out TCCR1A, tmp
	ldi tmp, (1<<WGM13)+(1<<WGM12)+(1<<CS10)	; timer1 clock input = system clock
	out TCCR1B, tmp			; clock frequency = 8 MHz
							; pwm frequency = 10 MHz / 2^16 = 122 Hz
	ldi tmp, $ff			; set PWM TOP
	out ICR1H, tmp
	out ICR1L, tmp
	out OCR1AH, brightH		; set initial brightness
	out OCR1AL, brightM

	; timer interrupt
	ldi tmp, (1<<TOIE1)		; enable timer1 overflow interrupt
	out TIMSK, tmp

	ldi tmp, (1<<SE)		; enable sleep
	out MCUCR, tmp

	sei						; global interrupt enable

main:
	sleep
	rjmp main

t1_of: 						; timer1 overflow interrupt
	; This point is reached at 122 Hz.

	cpi brightH, $ff		; return when max brightness is reached
	breq t1_of_done

	; prescaler delay
	inc ps
	cpi ps, ps_max			; return when prescaler value is not yet reached
	brlo t1_of_done
	clr ps

	; This point is reached at 122 Hz / 36 = 3.4 Hz.

	out OCR1AH, brightH		; update pwm value
	out OCR1AL, brightM		; write order: H, L

	ldi tmp, (1<<led) 		; set led (PB3, OC1) as output
	out DDRB, tmp			; now that pwm is stable

	add brightL, brightM	; increase brightness
	adc brightM, brightH	; by multipling with 1 1/256
	adc brightH, zero		; don't foget to add carry
t1_of_done:
	reti


; end of file
