summaryrefslogtreecommitdiffstats
path: root/libleds_asm.S
blob: fd7e67c22a1f6e666339c8fbe354df468f498442 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
.include "m16def.inc"

#ifndef F_CPU
# error The LEDs are timing sensitive. F_CPU required.
#elif F_CPU < 4000000
# error The LEDs are timing sensitive. CPU Frequency must be at least 4MHz
#elif F_CPU == 4000000

// 4MHz
#define nop_short
#define nop_long nop $ nop

#elif F_CPU == 8000000

// 8MHz
#define nop_short nop
#define nop_long nop $ nop $ nop $ nop $ nop

#elif F_CPU == 16000000

// 16MHz
#define nop_short nop $ nop $ nop
#define nop_long nop $ nop $ nop $ nop $ nop $ nop $ nop $ nop $ nop $ nop $ nop

#else
# error Missing nop definitions for your CPU frequency.
#endif


.global led_write_rgb
	.type led_write_rgb, @function
; void (uint16_t port, char pins, char r, char g, char b);
;
; Args:
;	port:	r25, r24
;	pins:	r22
;	b:	r20
;	g:	r19
;	r:	r18
;
; destroys: r19
;
; The leds expect the data in G-R-B order
led_write_rgb:
	clr r0
	dec r0

	call L_led_write_byte
	mov r19, r18
	call L_led_write_byte
	mov r19, r20
	call L_led_write_byte
	ret

; Args:
;	port:	X -- curently ignored, hadcoded to PORTD
;	pins:	r22  -- currently ignored, hardcoded to 0xFF
;	byte:	r19 (!)
;
; Prerequisites:
; r0 must be 0xFF
;
; destroys: r21 -- will be 0 afterwards
; destroys: r19 -- call rol on it once to restore
L_led_write_byte:

	ldi r21, 8

L_led_write_byte__loop_head:
	rol r19
	brcc L_led_write_byte__zero

L_led_write_byte__one:
	out PORTD, r0
	nop_long
	out PORTD, r1
	nop_short
	rjmp L_led_write_byte__loop_ctrl

L_led_write_byte__zero:
	out PORTD, r0
	nop_short
	out PORTD, r1
	nop_long

L_led_write_byte__loop_ctrl:
	; loop ctrl
	dec r21
	brne L_led_write_byte__loop_head

L_led_write_byte__out:
	ret