summaryrefslogtreecommitdiffstats
path: root/libleds_asm.S
diff options
context:
space:
mode:
Diffstat (limited to 'libleds_asm.S')
-rw-r--r--libleds_asm.S92
1 files changed, 92 insertions, 0 deletions
diff --git a/libleds_asm.S b/libleds_asm.S
new file mode 100644
index 0000000..fd7e67c
--- /dev/null
+++ b/libleds_asm.S
@@ -0,0 +1,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