; Slow LED Blink
; http://www.pjrc.com/teensy/loader.html

; compile with:
;   tavrasm blink_slow.asm


.equ    DDRD    = 0x0A
.equ    PORTD   = 0x0B
.equ    CLKPR   = 0x61

.cseg
.org	0

begin:
	;Use clock prescaler to reduce power.  If someone leaves this
	;plugged into their laptop, which continues providing USB power
	;in sleep mode, it's nice to conserve their battery.
	;
	;You can easily try different speeds by just uncommenting a
	;different line, instead of having to edit the delay code below.
	;
	ldi	r16, 0x80	;CPU Clock	LED Off		LED On
	;ldi	r17, 0x00	;16 MHz		11.07 mA	13.97 mA
	;ldi	r17, 0x01	;8 MHz		6.71 mA		9.65 mA
	;ldi	r17, 0x02	;4 MHz		4.67 mA		7.61 mA
	;ldi	r17, 0x03	;2 MHz		2.98 mA		5.93 mA
	;ldi	r17, 0x04	;1 MHz		2.18 mA		5.14 mA
	ldi	r17, 0x05	;500 kHz	1.70 mA		4.66 mA
	;ldi	r17, 0x06	;250 kHz	1.46 mA		4.43 mA
	;ldi	r17, 0x07	;125 kHz	1.34 mA		4.30 mA
	;ldi	r17, 0x08	;62.5 kHz	1.28 mA		4.25 mA
	sts	CLKPR, r16
	sts	CLKPR, r17
	;
	;These current measurements were made with a computer providing
	;4.87 volts, which is typical of USB without a hub.
	;
	;The USB specification requires compliant devices to consume
	;no more than 0.5 mA when the USB bus is suspended.  Even the
	;slowest clock can not need that requirement.  Power down mode and
	;USB wakeup interrupts are required to meet the USB power spec!
	;(HalfKay uses those to achieve 0.2 mA in USB suspend state)
	;
	;Fortunately, there is little harm other than draining batteries
	;slightly and not being permitted to use the USB compliant logo.
	;
	;The current measurements above are with the USB peripheral
	;disabled and the PLL off.  With those active and the CPU running
	;at 16 MHz, current is typically between 20 to 25 mA.  USB allows
	;100 mA current, and up to 500 mA in some cases.

	;configure LED pin
	cbi	DDRD, 6
	cbi	PORTD, 6	;write a 0, so pin is low when output

main_loop:
	sbi	DDRD, 6		;LED on (pin becomes output)
	rcall	delay_1000ms
	cbi	DDRD, 6		;LED off (pin becomes input)
	rcall	delay_1000ms
	rjmp	main_loop


	;this "busy loop" is simple, but a low power delay would use
	;timer1 and put the CPU into idle mode, or the watchdog timer
	;with the cpu in power down mode
delay_1000ms:
	ldi	r17, 200
delay_loop1:
	ldi	r16, 250
delay_loop2:
	nop			;10 cycles per loop, r16 * r17 times
	nop
	nop
	nop
	nop
	nop
	nop
	dec	r16
	brne	delay_loop2
	dec	r17
	brne	delay_loop1
	ret

