+#if AO_BUTTON_COUNT > 11
+ case 11: return ao_button_value(11);
+#endif
+#if AO_BUTTON_COUNT > 12
+ case 12: return ao_button_value(12);
+#endif
+#if AO_BUTTON_COUNT > 13
+ case 13: return ao_button_value(13);
+#endif
+#if AO_BUTTON_COUNT > 14
+ case 14: return ao_button_value(14);
+#endif
+#if AO_BUTTON_COUNT > 15
+ case 15: return ao_button_value(15);
+#endif
+ }
+ return 0;
+}
+
+static void
+_ao_button_check(uint8_t b)
+{
+ uint8_t value = _ao_button_get(b);
+
+ if (value != ao_button_state[b].value) {
+ AO_TICK_TYPE now = ao_time();
+
+ if ((now - ao_button_state[b].time) >= AO_BUTTON_DEBOUNCE_INTERVAL) {
+ ao_button_state[b].value = value;
+ ao_button_queue(b, value);
+ }
+ ao_button_state[b].time = now;
+ }
+}
+
+static void
+_ao_button_init(uint8_t b)
+{
+ uint8_t m = ao_arch_irqsave();
+ uint8_t value = _ao_button_get(b);
+ ao_button_state[b].value = value;
+ ao_button_state[b].time = ao_time();
+ ao_button_queue(b, value);
+ ao_arch_irqrestore(m);
+
+}
+
+uint8_t
+ao_button_get(uint8_t b)
+{
+ return ao_button_state[b].value;
+}
+
+static void
+ao_button_isr(void)
+{
+ uint8_t b;
+
+ for (b = 0; b < AO_BUTTON_COUNT; b++)
+ _ao_button_check(b);