summaryrefslogtreecommitdiff
path: root/protocol
diff options
context:
space:
mode:
Diffstat (limited to 'protocol')
-rw-r--r--protocol/bluefruit.mk27
-rw-r--r--protocol/bluefruit/bluefruit.c202
-rw-r--r--protocol/bluefruit/bluefruit.h28
-rw-r--r--protocol/bluefruit/main.c116
-rw-r--r--protocol/lufa/lufa.c4
-rw-r--r--protocol/pjrc/usb.c3
-rw-r--r--protocol/ps2.h146
-rw-r--r--protocol/ps2_busywait.c185
-rw-r--r--protocol/ps2_interrupt.c (renamed from protocol/ps2.c)334
-rw-r--r--protocol/ps2_usart.c174
10 files changed, 804 insertions, 415 deletions
diff --git a/protocol/bluefruit.mk b/protocol/bluefruit.mk
new file mode 100644
index 0000000000..7e6328f6cb
--- /dev/null
+++ b/protocol/bluefruit.mk
@@ -0,0 +1,27 @@
+BLUEFRUIT_DIR = protocol/bluefruit
+PJRC_DIR = protocol/pjrc
+
+SRC += $(BLUEFRUIT_DIR)/main.c \
+ $(BLUEFRUIT_DIR)/bluefruit.c \
+ serial_uart.c \
+ $(PJRC_DIR)/pjrc.c \
+ $(PJRC_DIR)/usb_keyboard.c \
+ $(PJRC_DIR)/usb_debug.c \
+ $(PJRC_DIR)/usb.c
+
+# Option modules
+ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE)
+ SRC += $(PJRC_DIR)/usb_mouse.c
+endif
+
+ifdef EXTRAKEY_ENABLE
+ SRC += $(PJRC_DIR)/usb_extra.c
+endif
+
+# Search Path
+VPATH += $(TOP_DIR)/$(BLUEFRUIT_DIR)
+#VPATH += $(TOP_DIR)/$(BLUEFRUIT_DIR)/usb_debug_only
+VPATH += $(TOP_DIR)/$(PJRC_DIR)
+
+OPT_DEFS += -DPROTOCOL_BLUEFRUIT
+OPT_DEFS += -DPROTOCOL_PJRC
diff --git a/protocol/bluefruit/bluefruit.c b/protocol/bluefruit/bluefruit.c
new file mode 100644
index 0000000000..f991e4d04e
--- /dev/null
+++ b/protocol/bluefruit/bluefruit.c
@@ -0,0 +1,202 @@
+/*
+Bluefruit Protocol for TMK firmware
+Author: Benjamin Gould, 2013
+Based on code Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <stdint.h>
+#include "host.h"
+#include "report.h"
+#include "print.h"
+#include "debug.h"
+#include "host_driver.h"
+#include "serial.h"
+#include "bluefruit.h"
+
+#define BLUEFRUIT_TRACE_SERIAL 1
+
+static uint8_t bluefruit_keyboard_leds = 0;
+
+static void bluefruit_serial_send(uint8_t);
+
+void bluefruit_keyboard_print_report(report_keyboard_t *report)
+{
+ if (!debug_keyboard) return;
+ dprintf("keys: "); for (int i = 0; i < REPORT_KEYS; i++) { debug_hex8(report->keys[i]); dprintf(" "); }
+ dprintf(" mods: "); debug_hex8(report->mods);
+ dprintf(" reserved: "); debug_hex8(report->reserved);
+ dprintf("\n");
+}
+
+#ifdef BLUEFRUIT_TRACE_SERIAL
+static void bluefruit_trace_header()
+{
+ dprintf("+------------------------------------+\n");
+ dprintf("| HID report to Bluefruit via serial |\n");
+ dprintf("+------------------------------------+\n|");
+}
+
+static void bluefruit_trace_footer()
+{
+ dprintf("|\n+------------------------------------+\n\n");
+}
+#endif
+
+static void bluefruit_serial_send(uint8_t data)
+{
+#ifdef BLUEFRUIT_TRACE_SERIAL
+ dprintf(" ");
+ debug_hex8(data);
+ dprintf(" ");
+#endif
+ serial_send(data);
+}
+
+/*------------------------------------------------------------------*
+ * Host driver
+ *------------------------------------------------------------------*/
+
+static uint8_t keyboard_leds(void);
+static void send_keyboard(report_keyboard_t *report);
+static void send_mouse(report_mouse_t *report);
+static void send_system(uint16_t data);
+static void send_consumer(uint16_t data);
+
+static host_driver_t driver = {
+ keyboard_leds,
+ send_keyboard,
+ send_mouse,
+ send_system,
+ send_consumer
+};
+
+host_driver_t *bluefruit_driver(void)
+{
+ return &driver;
+}
+
+static uint8_t keyboard_leds(void) {
+ return bluefruit_keyboard_leds;
+}
+
+static void send_keyboard(report_keyboard_t *report)
+{
+#ifdef BLUEFRUIT_TRACE_SERIAL
+ bluefruit_trace_header();
+#endif
+ bluefruit_serial_send(0xFD);
+ for (uint8_t i = 0; i < REPORT_SIZE; i++) {
+ bluefruit_serial_send(report->raw[i]);
+ }
+#ifdef BLUEFRUIT_TRACE_SERIAL
+ bluefruit_trace_footer();
+#endif
+}
+
+static void send_mouse(report_mouse_t *report)
+{
+#ifdef BLUEFRUIT_TRACE_SERIAL
+ bluefruit_trace_header();
+#endif
+ bluefruit_serial_send(0xFD);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x03);
+ bluefruit_serial_send(report->buttons);
+ bluefruit_serial_send(report->x);
+ bluefruit_serial_send(report->y);
+ bluefruit_serial_send(report->v); // should try sending the wheel v here
+ bluefruit_serial_send(report->h); // should try sending the wheel h here
+ bluefruit_serial_send(0x00);
+#ifdef BLUEFRUIT_TRACE_SERIAL
+ bluefruit_trace_footer();
+#endif
+}
+
+static void send_system(uint16_t data)
+{
+}
+
+/*
++-----------------+-------------------+-------+
+| Consumer Key | Bit Map | Hex |
++-----------------+-------------------+-------+
+| Home | 00000001 00000000 | 01 00 |
+| KeyboardLayout | 00000010 00000000 | 02 00 |
+| Search | 00000100 00000000 | 04 00 |
+| Snapshot | 00001000 00000000 | 08 00 |
+| VolumeUp | 00010000 00000000 | 10 00 |
+| VolumeDown | 00100000 00000000 | 20 00 |
+| Play/Pause | 01000000 00000000 | 40 00 |
+| Fast Forward | 10000000 00000000 | 80 00 |
+| Rewind | 00000000 00000001 | 00 01 |
+| Scan Next Track | 00000000 00000010 | 00 02 |
+| Scan Prev Track | 00000000 00000100 | 00 04 |
+| Random Play | 00000000 00001000 | 00 08 |
+| Stop | 00000000 00010000 | 00 10 |
++-------------------------------------+-------+
+*/
+#define CONSUMER2BLUEFRUIT(usage) \
+ (usage == AUDIO_MUTE ? 0x0000 : \
+ (usage == AUDIO_VOL_UP ? 0x1000 : \
+ (usage == AUDIO_VOL_DOWN ? 0x2000 : \
+ (usage == TRANSPORT_NEXT_TRACK ? 0x0002 : \
+ (usage == TRANSPORT_PREV_TRACK ? 0x0004 : \
+ (usage == TRANSPORT_STOP ? 0x0010 : \
+ (usage == TRANSPORT_STOP_EJECT ? 0x0000 : \
+ (usage == TRANSPORT_PLAY_PAUSE ? 0x4000 : \
+ (usage == AL_CC_CONFIG ? 0x0000 : \
+ (usage == AL_EMAIL ? 0x0000 : \
+ (usage == AL_CALCULATOR ? 0x0000 : \
+ (usage == AL_LOCAL_BROWSER ? 0x0000 : \
+ (usage == AC_SEARCH ? 0x0400 : \
+ (usage == AC_HOME ? 0x0100 : \
+ (usage == AC_BACK ? 0x0000 : \
+ (usage == AC_FORWARD ? 0x0000 : \
+ (usage == AC_STOP ? 0x0000 : \
+ (usage == AC_REFRESH ? 0x0000 : \
+ (usage == AC_BOOKMARKS ? 0x0000 : 0)))))))))))))))))))
+
+static void send_consumer(uint16_t data)
+{
+ static uint16_t last_data = 0;
+ if (data == last_data) return;
+ last_data = data;
+
+ uint16_t bitmap = CONSUMER2BLUEFRUIT(data);
+
+#ifdef BLUEFRUIT_TRACE_SERIAL
+ dprintf("\nData: ");
+ debug_hex16(data);
+ dprintf("; bitmap: ");
+ debug_hex16(bitmap);
+ dprintf("\n");
+ bluefruit_trace_header();
+#endif
+ bluefruit_serial_send(0xFD);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x02);
+ bluefruit_serial_send((bitmap>>8)&0xFF);
+ bluefruit_serial_send(bitmap&0xFF);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x00);
+#ifdef BLUEFRUIT_TRACE_SERIAL
+ bluefruit_trace_footer();
+#endif
+}
+
diff --git a/protocol/bluefruit/bluefruit.h b/protocol/bluefruit/bluefruit.h
new file mode 100644
index 0000000000..4f9b58836d
--- /dev/null
+++ b/protocol/bluefruit/bluefruit.h
@@ -0,0 +1,28 @@
+/*
+Bluefruit Protocol for TMK firmware
+Author: Benjamin Gould, 2013
+Based on code Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef VUSB_H
+#define VUSB_H
+
+#include "host_driver.h"
+
+
+host_driver_t *bluefruit_driver(void);
+
+#endif
diff --git a/protocol/bluefruit/main.c b/protocol/bluefruit/main.c
new file mode 100644
index 0000000000..871062ab11
--- /dev/null
+++ b/protocol/bluefruit/main.c
@@ -0,0 +1,116 @@
+/*
+Bluefruit Protocol for TMK firmware
+Author: Benjamin Gould, 2013
+Based on code Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include <avr/interrupt.h>
+#include <avr/wdt.h>
+#include <avr/sleep.h>
+#include <util/delay.h>
+#include "serial.h"
+#include "keyboard.h"
+#include "usb.h"
+#include "host.h"
+#include "timer.h"
+#include "print.h"
+#include "debug.h"
+#include "sendchar.h"
+#include "suspend.h"
+#include "bluefruit.h"
+#include "pjrc.h"
+
+#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
+
+#define HOST_DRIVER_NOT_SET 0
+#define BLUEFRUIT_HOST_DRIVER 1
+#define PJRC_HOST_DRIVER 2
+
+int main(void)
+{
+
+ CPU_PRESCALE(0);
+
+ DDRD = _BV(PD5);
+ DDRB = _BV(PB0);
+
+ PORTD = _BV(PD5);
+ PORTB = _BV(PB0);
+
+ print_set_sendchar(sendchar);
+
+ usb_init();
+ _delay_ms(2000);
+ // while (!usb_configured()) /* wait */
+
+ dprintf("Initializing keyboard...\n");
+ keyboard_init();
+
+ // This implementation is pretty simplistic... if the USB connection
+ // is not configured, choose the Bluefruit, otherwise use USB
+ // Definitely would prefer to have this driven by an input pin and make
+ // it switch dynamically - BCG
+ if (!usb_configured()) {
+
+ // Send power to Bluefruit... Adafruit says it takes 27 mA, I think
+ // the pins should provide 40 mA, but just in case I switch the
+ // Bluefruit using a transistor - BCG
+ DDRB = _BV(PB6);
+ PORTB |= _BV(PB6);
+
+ dprintf("Setting host driver to bluefruit...\n");
+ host_set_driver(bluefruit_driver());
+
+ dprintf("Initializing serial...\n");
+ serial_init();
+
+ // wait an extra second for the PC's operating system
+ // to load drivers and do whatever it does to actually
+ // be ready for input
+ _delay_ms(1000);
+ PORTD = ~_BV(PD5);
+ dprintf("Starting main loop");
+ while (1) {
+ keyboard_task();
+ }
+
+ } else {
+
+ // I'm not smart enough to get this done with LUFA - BCG
+ dprintf("Setting host driver to PJRC...\n");
+ host_set_driver(pjrc_driver());
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_init();
+#endif
+ // wait an extra second for the PC's operating system
+ // to load drivers and do whatever it does to actually
+ // be ready for input
+ _delay_ms(1000);
+ PORTB = ~_BV(PB0);
+ dprintf("Starting main loop");
+ while (1) {
+ while (suspend) {
+ suspend_power_down();
+ if (remote_wakeup && suspend_wakeup_condition()) {
+ usb_remote_wakeup();
+ }
+ }
+ keyboard_task();
+ }
+ }
+
+}
diff --git a/protocol/lufa/lufa.c b/protocol/lufa/lufa.c
index 04e8e78f38..eca51c8784 100644
--- a/protocol/lufa/lufa.c
+++ b/protocol/lufa/lufa.c
@@ -148,7 +148,6 @@ static void Console_Task(void)
*/
void EVENT_USB_Device_Connect(void)
{
- led_set(0x1f); // all on
}
void EVENT_USB_Device_Disconnect(void)
@@ -172,8 +171,9 @@ void EVENT_USB_Device_WakeUp()
#ifdef SLEEP_LED_ENABLE
sleep_led_disable();
-#endif
+ // NOTE: converters may not accept this
led_set(host_keyboard_leds());
+#endif
}
void EVENT_USB_Device_StartOfFrame(void)
diff --git a/protocol/pjrc/usb.c b/protocol/pjrc/usb.c
index 84c99972f2..393b36f78e 100644
--- a/protocol/pjrc/usb.c
+++ b/protocol/pjrc/usb.c
@@ -662,8 +662,9 @@ ISR(USB_GEN_vect)
suspend_wakeup_init();
#ifdef SLEEP_LED_ENABLE
sleep_led_disable();
-#endif
+ // NOTE: converters may not accept this
led_set(host_keyboard_leds());
+#endif
UDIEN |= (1<<SUSPE);
UDIEN &= ~(1<<WAKEUPE);
diff --git a/protocol/ps2.h b/protocol/ps2.h
index 834165356c..483eea7209 100644
--- a/protocol/ps2.h
+++ b/protocol/ps2.h
@@ -1,5 +1,5 @@
/*
-Copyright 2010,2011 Jun WAKO <wakojun@gmail.com>
+Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
This software is licensed with a Modified BSD License.
All of this is supposed to be Free Software, Open Source, DFSG-free,
@@ -37,32 +37,46 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef PS2_H
#define PS2_H
+
+#include <stdbool.h>
+#include <util/delay.h>
+#include <avr/io.h>
+
/*
* Primitive PS/2 Library for AVR
+ *
+ * PS/2 Resources
+ * --------------
+ * [1] The PS/2 Mouse/Keyboard Protocol
+ * http://www.computer-engineering.org/ps2protocol/
+ * Concise and thorough primer of PS/2 protocol.
+ *
+ * [2] Keyboard and Auxiliary Device Controller
+ * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
+ * Signal Timing and Format
+ *
+ * [3] Keyboards(101- and 102-key)
+ * http://www.mcamafia.de/pdf/ibm_hitrc11.pdf
+ * Keyboard Layout, Scan Code Set, POR, and Commands.
+ *
+ * [4] PS/2 Reference Manuals
+ * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
+ * Collection of IBM Personal System/2 documents.
+ *
+ * [5] TrackPoint Engineering Specifications for version 3E
+ * https://web.archive.org/web/20100526161812/http://wwwcssrv.almaden.ibm.com/trackpoint/download.html
*/
-
-
-/* port settings for clock and data line */
-#if !(defined(PS2_CLOCK_PORT) && \
- defined(PS2_CLOCK_PIN) && \
- defined(PS2_CLOCK_DDR) && \
- defined(PS2_CLOCK_BIT))
-# error "PS/2 clock port setting is required in config.h"
-#endif
-
-#if !(defined(PS2_DATA_PORT) && \
- defined(PS2_DATA_PIN) && \
- defined(PS2_DATA_DDR) && \
- defined(PS2_DATA_BIT))
-# error "PS/2 data port setting is required in config.h"
-#endif
-
#define PS2_ACK 0xFA
#define PS2_RESEND 0xFE
#define PS2_SET_LED 0xED
-#define PS2_ERR_NONE 0
-#define PS2_ERR_PARITY 0x10
+// TODO: error numbers
+#define PS2_ERR_NONE 0
+#define PS2_ERR_STARTBIT1 1
+#define PS2_ERR_STARTBIT2 2
+#define PS2_ERR_STARTBIT3 3
+#define PS2_ERR_PARITY 0x10
+#define PS2_ERR_NODATA 0x20
#define PS2_LED_SCROLL_LOCK 0
#define PS2_LED_NUM_LOCK 1
@@ -71,13 +85,101 @@ POSSIBILITY OF SUCH DAMAGE.
extern uint8_t ps2_error;
-/* host role */
void ps2_host_init(void);
uint8_t ps2_host_send(uint8_t data);
uint8_t ps2_host_recv_response(void);
uint8_t ps2_host_recv(void);
void ps2_host_set_led(uint8_t usb_led);
-/* device role */
+
+/* Check port settings for clock and data line */
+#if !(defined(PS2_CLOCK_PORT) && \
+ defined(PS2_CLOCK_PIN) && \
+ defined(PS2_CLOCK_DDR) && \
+ defined(PS2_CLOCK_BIT))
+# error "PS/2 clock port setting is required in config.h"
+#endif
+
+#if !(defined(PS2_DATA_PORT) && \
+ defined(PS2_DATA_PIN) && \
+ defined(PS2_DATA_DDR) && \
+ defined(PS2_DATA_BIT))
+# error "PS/2 data port setting is required in config.h"
+#endif
+
+/*--------------------------------------------------------------------
+ * static functions
+ *------------------------------------------------------------------*/
+static inline void clock_lo(void)
+{
+ PS2_CLOCK_PORT &= ~(1<<PS2_CLOCK_BIT);
+ PS2_CLOCK_DDR |= (1<<PS2_CLOCK_BIT);
+}
+static inline void clock_hi(void)
+{
+ /* input with pull up */
+ PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT);
+ PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT);
+}
+static inline bool clock_in(void)
+{
+ PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT);
+ PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT);
+ _delay_us(1);
+ return PS2_CLOCK_PIN&(1<<PS2_CLOCK_BIT);
+}
+static inline void data_lo(void)
+{
+ PS2_DATA_PORT &= ~(1<<PS2_DATA_BIT);
+ PS2_DATA_DDR |= (1<<PS2_DATA_BIT);
+}
+static inline void data_hi(void)
+{
+ /* input with pull up */
+ PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT);
+ PS2_DATA_PORT |= (1<<PS2_DATA_BIT);
+}
+static inline bool data_in(void)
+{
+ PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT);
+ PS2_DATA_PORT |= (1<<PS2_DATA_BIT);
+ _delay_us(1);
+ return PS2_DATA_PIN&(1<<PS2_DATA_BIT);
+}
+
+static inline uint16_t wait_clock_lo(uint16_t us)
+{
+ while (clock_in() && us) { asm(""); _delay_us(1); us--; }
+ return us;
+}
+static inline uint16_t wait_clock_hi(uint16_t us)
+{
+ while (!clock_in() && us) { asm(""); _delay_us(1); us--; }
+ return us;
+}
+static inline uint16_t wait_data_lo(uint16_t us)
+{
+ while (data_in() && us) { asm(""); _delay_us(1); us--; }
+ return us;
+}
+static inline uint16_t wait_data_hi(uint16_t us)
+{
+ while (!data_in() && us) { asm(""); _delay_us(1); us--; }
+ return us;
+}
+
+/* idle state that device can send */
+static inline void idle(void)
+{
+ clock_hi();
+ data_hi();
+}
+
+/* inhibit device to send */
+static inline void inhibit(void)
+{
+ clock_lo();
+ data_hi();
+}
#endif
diff --git a/protocol/ps2_busywait.c b/protocol/ps2_busywait.c
new file mode 100644
index 0000000000..05dd7b27e6
--- /dev/null
+++ b/protocol/ps2_busywait.c
@@ -0,0 +1,185 @@
+/*
+Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+* Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * PS/2 protocol busywait version
+ */
+
+#include <stdbool.h>
+#include <util/delay.h>
+#include "ps2.h"
+#include "debug.h"
+
+
+#define WAIT(stat, us, err) do { \
+ if (!wait_##stat(us)) { \
+ ps2_error = err; \
+ goto ERROR; \
+ } \
+} while (0)
+
+
+uint8_t ps2_error = PS2_ERR_NONE;
+
+
+void ps2_host_init(void)
+{
+ // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
+ _delay_ms(2500);
+
+ inhibit();
+}
+
+uint8_t ps2_host_send(uint8_t data)
+{
+ bool parity = true;
+ ps2_error = PS2_ERR_NONE;
+
+ /* terminate a transmission if we have */
+ inhibit();
+ _delay_us(100); // 100us [4]p.13, [5]p.50
+
+ /* 'Request to Send' and Start bit */
+ data_lo();
+ clock_hi();
+ WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
+
+ /* Data bit */
+ for (uint8_t i = 0; i < 8; i++) {
+ _delay_us(15);
+ if (data&(1<<i)) {
+ parity = !parity;
+ data_hi();
+ } else {
+ data_lo();
+ }
+ WAIT(clock_hi, 50, 2);
+ WAIT(clock_lo, 50, 3);
+ }
+
+ /* Parity bit */
+ _delay_us(15);
+ if (parity) { data_hi(); } else { data_lo(); }
+ WAIT(clock_hi, 50, 4);
+ WAIT(clock_lo, 50, 5);
+
+ /* Stop bit */
+ _delay_us(15);
+ data_hi();
+
+ /* Ack */
+ WAIT(data_lo, 50, 6);
+ WAIT(clock_lo, 50, 7);
+
+ /* wait for idle state */
+ WAIT(clock_hi, 50, 8);
+ WAIT(data_hi, 50, 9);
+
+ inhibit();
+ return ps2_host_recv_response();
+ERROR:
+ inhibit();
+ return 0;
+}
+
+/* receive data when host want else inhibit communication */
+uint8_t ps2_host_recv_response(void)
+{
+ // Command may take 25ms/20ms at most([5]p.46, [3]p.21)
+ // 250 * 100us(wait for start bit in ps2_host_recv)
+ uint8_t data = 0;
+ uint8_t try = 250;
+ do {
+ data = ps2_host_recv();
+ } while (try-- && ps2_error);
+ return data;
+}
+
+/* called after start bit comes */
+uint8_t ps2_host_recv(void)
+{
+ uint8_t data = 0;
+ bool parity = true;
+ ps2_error = PS2_ERR_NONE;
+
+ /* release lines(idle state) */
+ idle();
+
+ /* start bit [1] */
+ WAIT(clock_lo, 100, 1); // TODO: this is enough?
+ WAIT(data_lo, 1, 2);
+ WAIT(clock_hi, 50, 3);
+
+ /* data [2-9] */
+ for (uint8_t i = 0; i < 8; i++) {
+ WAIT(clock_lo, 50, 4);
+ if (data_in()) {
+ parity = !parity;
+ data |= (1<<i);
+ }
+ WAIT(clock_hi, 50, 5);
+ }
+
+ /* parity [10] */
+ WAIT(clock_lo, 50, 6);
+ if (data_in() != parity) {
+ ps2_error = PS2_ERR_PARITY;
+ goto ERROR;
+ }
+ WAIT(clock_hi, 50, 7);
+
+ /* stop bit [11] */
+ WAIT(clock_lo, 50, 8);
+ WAIT(data_hi, 1, 9);
+ WAIT(clock_hi, 50, 10);
+
+ inhibit();
+ return data;
+ERROR:
+ if (ps2_error > PS2_ERR_STARTBIT3) {
+ xprintf("x%02X\n", ps2_error);
+ }
+ inhibit();
+ return 0;
+}
+
+/* send LED state to keyboard */
+void ps2_host_set_led(uint8_t led)
+{
+ ps2_host_send(0xED);
+ ps2_host_send(led);
+}
diff --git a/protocol/ps2.c b/protocol/ps2_interrupt.c
index e5873a9bfa..259d254007 100644
--- a/protocol/ps2.c
+++ b/protocol/ps2_interrupt.c
@@ -35,47 +35,15 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
+/*
+ * PS/2 protocol Pin interrupt version
+ */
+
#include <stdbool.h>
-#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "ps2.h"
-#include "debug.h"
-
-
-#ifndef PS2_USE_INT
-static uint8_t recv_data(void);
-#endif
-static inline void clock_lo(void);
-static inline void clock_hi(void);
-static inline bool clock_in(void);
-static inline void data_lo(void);
-static inline void data_hi(void);
-static inline bool data_in(void);
-static inline uint16_t wait_clock_lo(uint16_t us);
-static inline uint16_t wait_clock_hi(uint16_t us);
-static inline uint16_t wait_data_lo(uint16_t us);
-static inline uint16_t wait_data_hi(uint16_t us);
-static inline void idle(void);
-static inline void inhibit(void);
-
-
-/*
-Primitive PS/2 Library for AVR
-==============================
-Host side is only supported now.
-
-
-I/O control
------------
-High state is asserted by input with pull up.
-
-
-PS/2 References
----------------
-http://www.computer-engineering.org/ps2protocol/
-http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
-*/
+#include "print.h"
#define WAIT(stat, us, err) do { \
@@ -89,35 +57,38 @@ http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
uint8_t ps2_error = PS2_ERR_NONE;
+static inline uint8_t pbuf_dequeue(void);
+static inline void pbuf_enqueue(uint8_t data);
+static inline bool pbuf_has_data(void);
+static inline void pbuf_clear(void);
+
+
void ps2_host_init(void)
{
-#ifdef PS2_USE_INT
+ idle();
PS2_INT_INIT();
PS2_INT_ON();
- idle();
-#else
- inhibit();
-#endif
+ // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
+ //_delay_ms(2500);
}
-// TODO: send using interrupt if available
uint8_t ps2_host_send(uint8_t data)
{
- uint8_t res = 0;
bool parity = true;
ps2_error = PS2_ERR_NONE;
-#ifdef PS2_USE_INT
+
PS2_INT_OFF();
-#endif
+
/* terminate a transmission if we have */
inhibit();
- _delay_us(200); // at least 100us
+ _delay_us(100); // 100us [4]p.13, [5]p.50
- /* start bit [1] */
+ /* 'Request to Send' and Start bit */
data_lo();
clock_hi();
- WAIT(clock_lo, 20000, 10); // may take 15ms at most until device starts clocking
- /* data [2-9] */
+ WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
+
+ /* Data bit[2-9] */
for (uint8_t i = 0; i < 8; i++) {
_delay_us(15);
if (data&(1<<i)) {
@@ -129,15 +100,18 @@ uint8_t ps2_host_send(uint8_t data)
WAIT(clock_hi, 50, 2);
WAIT(clock_lo, 50, 3);
}
- /* parity [10] */
+
+ /* Parity bit */
_delay_us(15);
if (parity) { data_hi(); } else { data_lo(); }
WAIT(clock_hi, 50, 4);
WAIT(clock_lo, 50, 5);
- /* stop bit [11] */
+
+ /* Stop bit */
_delay_us(15);
data_hi();
- /* ack [12] */
+
+ /* Ack */
WAIT(data_lo, 50, 6);
WAIT(clock_lo, 50, 7);
@@ -145,116 +119,35 @@ uint8_t ps2_host_send(uint8_t data)
WAIT(clock_hi, 50, 8);
WAIT(data_hi, 50, 9);
-#ifdef PS2_USE_INT
+ idle();
PS2_INT_ON();
-#endif
- res = ps2_host_recv_response();
+ return ps2_host_recv_response();
ERROR:
-#ifdef PS2_USE_INT
- PS2_INT_ON();
idle();
-#else
- inhibit();
-#endif
- return res;
+ PS2_INT_ON();
+ return 0;
}
-#ifndef PS2_USE_INT
-/* receive data when host want else inhibit communication */
uint8_t ps2_host_recv_response(void)
{
- uint8_t data = 0;
-
-#ifdef PS2_USE_INT
- PS2_INT_OFF();
-#endif
- /* terminate a transmission if we have */
- inhibit();
- _delay_us(100);
-
- /* release lines(idle state) */
- idle();
-
- /* wait start bit */
- wait_clock_lo(25000); // command response may take 20 ms at most
- data = recv_data();
-
- inhibit();
- return data;
-}
-#endif
-
-#ifndef PS2_USE_INT
-uint8_t ps2_host_recv(void)
-{
- return ps2_host_recv_response();
-}
-#else
-/* ring buffer to store ps/2 key data */
-#define PBUF_SIZE 32
-static uint8_t pbuf[PBUF_SIZE];
-static uint8_t pbuf_head = 0;
-static uint8_t pbuf_tail = 0;
-static inline void pbuf_enqueue(uint8_t data)
-{
- uint8_t sreg = SREG;
- cli();
- uint8_t next = (pbuf_head + 1) % PBUF_SIZE;
- if (next != pbuf_tail) {
- pbuf[pbuf_head] = data;
- pbuf_head = next;
- } else {
- debug("pbuf: full\n");
- }
- SREG = sreg;
-}
-static inline uint8_t pbuf_dequeue(void)
-{
- uint8_t val = 0;
-
- uint8_t sreg = SREG;
- cli();
- if (pbuf_head != pbuf_tail) {
- val = pbuf[pbuf_tail];
- pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE;
+ // Command may take 25ms/20ms at most([5]p.46, [3]p.21)
+ uint8_t retry = 25;
+ while (retry-- && !pbuf_has_data()) {
+ _delay_ms(1);
}
- SREG = sreg;
-
- return val;
-}
-static inline bool pbuf_has_data(void)
-{
- uint8_t sreg = SREG;
- cli();
- bool has_data = (pbuf_head != pbuf_tail);
- SREG = sreg;
- return has_data;
-}
-static inline void pbuf_clear(void)
-{
- uint8_t sreg = SREG;
- cli();
- pbuf_head = pbuf_tail = 0;
- SREG = sreg;
+ return pbuf_dequeue();
}
/* get data received by interrupt */
uint8_t ps2_host_recv(void)
{
- if (ps2_error) {
- print("x");
- phex(ps2_error);
- ps2_host_send(0xFE); // request to resend
+ if (pbuf_has_data()) {
ps2_error = PS2_ERR_NONE;
+ return pbuf_dequeue();
+ } else {
+ ps2_error = PS2_ERR_NODATA;
+ return 0;
}
- idle();
- return pbuf_dequeue();
-}
-
-uint8_t ps2_host_recv_response(void)
-{
- while (!pbuf_has_data()) ;
- return pbuf_dequeue();
}
ISR(PS2_INT_VECT)
@@ -309,7 +202,6 @@ ISR(PS2_INT_VECT)
if (!data_in())
goto ERROR;
pbuf_enqueue(data);
-//phex(data);
goto DONE;
break;
default:
@@ -317,7 +209,6 @@ ISR(PS2_INT_VECT)
}
goto RETURN;
ERROR:
- inhibit();
ps2_error = state;
DONE:
state = INIT;
@@ -326,8 +217,6 @@ DONE:
RETURN:
return;
}
-#endif
-
/* send LED state to keyboard */
void ps2_host_set_led(uint8_t led)
@@ -337,116 +226,53 @@ void ps2_host_set_led(uint8_t led)
}
-#ifndef PS2_USE_INT
-/* called after start bit comes */
-static uint8_t recv_data(void)
+/*--------------------------------------------------------------------
+ * Ring buffer to store scan codes from keyboard
+ *------------------------------------------------------------------*/
+#define PBUF_SIZE 32
+static uint8_t pbuf[PBUF_SIZE];
+static uint8_t pbuf_head = 0;
+static uint8_t pbuf_tail = 0;
+static inline void pbuf_enqueue(uint8_t data)
{
- uint8_t data = 0;
- bool parity = true;
- ps2_error = PS2_ERR_NONE;
-
- /* start bit [1] */
- WAIT(clock_lo, 1, 1);
- WAIT(data_lo, 1, 2);
- WAIT(clock_hi, 50, 3);
-
- /* data [2-9] */
- for (uint8_t i = 0; i < 8; i++) {
- WAIT(clock_lo, 50, 4);
- if (data_in()) {
- parity = !parity;
- data |= (1<<i);
- }
- WAIT(clock_hi, 50, 5);
- }
-
- /* parity [10] */
- WAIT(clock_lo, 50, 6);
- if (data_in() != parity) {
- ps2_error = PS2_ERR_PARITY;
- goto ERROR;
+ uint8_t sreg = SREG;
+ cli();
+ uint8_t next = (pbuf_head + 1) % PBUF_SIZE;
+ if (next != pbuf_tail) {
+ pbuf[pbuf_head] = data;
+ pbuf_head = next;
+ } else {
+ print("pbuf: full\n");
}
- WAIT(clock_hi, 50, 7);
-
- /* stop bit [11] */
- WAIT(clock_lo, 50, 8);
- WAIT(data_hi, 1, 9);
- WAIT(clock_hi, 50, 10);
-
- return data;
-ERROR:
- return 0;
-}
-#endif
-
-static inline void clock_lo()
-{
- PS2_CLOCK_PORT &= ~(1<<PS2_CLOCK_BIT);
- PS2_CLOCK_DDR |= (1<<PS2_CLOCK_BIT);
-}
-static inline void clock_hi()
-{
- /* input with pull up */
- PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT);
- PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT);
-}
-static inline bool clock_in()
-{
- PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT);
- PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT);
- _delay_us(1);
- return PS2_CLOCK_PIN&(1<<PS2_CLOCK_BIT);
-}
-static inline void data_lo()
-{
- PS2_DATA_PORT &= ~(1<<PS2_DATA_BIT);
- PS2_DATA_DDR |= (1<<PS2_DATA_BIT);
-}
-static inline void data_hi()
-{
- /* input with pull up */
- PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT);
- PS2_DATA_PORT |= (1<<PS2_DATA_BIT);
+ SREG = sreg;
}
-static inline bool data_in()
+static inline uint8_t pbuf_dequeue(void)
{
- PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT);
- PS2_DATA_PORT |= (1<<PS2_DATA_BIT);
- _delay_us(1);
- return PS2_DATA_PIN&(1<<PS2_DATA_BIT);
-}
+ uint8_t val = 0;
-static inline uint16_t wait_clock_lo(uint16_t us)
-{
- while (clock_in() && us) { asm(""); _delay_us(1); us--; }
- return us;
-}
-static inline uint16_t wait_clock_hi(uint16_t us)
-{
- while (!clock_in() && us) { asm(""); _delay_us(1); us--; }
- return us;
-}
-static inline uint16_t wait_data_lo(uint16_t us)
-{
- while (data_in() && us) { asm(""); _delay_us(1); us--; }
- return us;
+ uint8_t sreg = SREG;
+ cli();
+ if (pbuf_head != pbuf_tail) {
+ val = pbuf[pbuf_tail];
+ pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE;
+ }
+ SREG = sreg;
+
+ return val;
}
-static inline uint16_t wait_data_hi(uint16_t us)
+static inline bool pbuf_has_data(void)
{
- while (!data_in() && us) { asm(""); _delay_us(1); us--; }
- return us;
+ uint8_t sreg = SREG;
+ cli();
+ bool has_data = (pbuf_head != pbuf_tail);
+ SREG = sreg;
+ return has_data;
}
-
-/* idle state that device can send */
-static inline void idle(void)
+static inline void pbuf_clear(void)
{
- clock_hi();
- data_hi();
+ uint8_t sreg = SREG;
+ cli();
+ pbuf_head = pbuf_tail = 0;
+ SREG = sreg;
}
-/* inhibit device to send */
-static inline void inhibit(void)
-{
- clock_lo();
- data_hi();
-}
diff --git a/protocol/ps2_usart.c b/protocol/ps2_usart.c
index 40c46c497c..c2d9d0a208 100644
--- a/protocol/ps2_usart.c
+++ b/protocol/ps2_usart.c
@@ -36,32 +36,14 @@ POSSIBILITY OF SUCH DAMAGE.
*/
/*
-Primitive PS/2 Library for AVR
-==============================
-Host side is only supported now.
-Synchronous USART is used to receive data by hardware process
-rather than interrupt. During V-USB interrupt runs, CLOCK interrupt
-cannot interpose. In the result it is prone to lost CLOCK edge.
+ * PS/2 protocol USART version
+ */
-
-I/O control
------------
-High state is asserted by internal pull-up.
-If you have a signaling problem, you may need to have
-external pull-up resisters on CLOCK and DATA line.
-
-
-PS/2 References
----------------
-http://www.computer-engineering.org/ps2protocol/
-http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
-*/
#include <stdbool.h>
-#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "ps2.h"
-#include "debug.h"
+#include "print.h"
#define WAIT(stat, us, err) do { \
@@ -75,18 +57,6 @@ http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
uint8_t ps2_error = PS2_ERR_NONE;
-static inline void clock_lo(void);
-static inline void clock_hi(void);
-static inline bool clock_in(void);
-static inline void data_lo(void);
-static inline void data_hi(void);
-static inline bool data_in(void);
-static inline uint16_t wait_clock_lo(uint16_t us);
-static inline uint16_t wait_clock_hi(uint16_t us);
-static inline uint16_t wait_data_lo(uint16_t us);
-static inline uint16_t wait_data_hi(uint16_t us);
-static inline void idle(void);
-static inline void inhibit(void);
static inline uint8_t pbuf_dequeue(void);
static inline void pbuf_enqueue(uint8_t data);
static inline bool pbuf_has_data(void);
@@ -95,14 +65,15 @@ static inline void pbuf_clear(void);
void ps2_host_init(void)
{
- idle();
+ idle(); // without this many USART errors occur when cable is disconnected
PS2_USART_INIT();
PS2_USART_RX_INT_ON();
+ // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
+ //_delay_ms(2500);
}
uint8_t ps2_host_send(uint8_t data)
{
- uint8_t res = 0;
bool parity = true;
ps2_error = PS2_ERR_NONE;
@@ -110,13 +81,14 @@ uint8_t ps2_host_send(uint8_t data)
/* terminate a transmission if we have */
inhibit();
- _delay_us(100);
+ _delay_us(100); // [4]p.13
- /* start bit [1] */
+ /* 'Request to Send' and Start bit */
data_lo();
clock_hi();
- WAIT(clock_lo, 15000, 1);
- /* data [2-9] */
+ WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
+
+ /* Data bit[2-9] */
for (uint8_t i = 0; i < 8; i++) {
_delay_us(15);
if (data&(1<<i)) {
@@ -128,15 +100,18 @@ uint8_t ps2_host_send(uint8_t data)
WAIT(clock_hi, 50, 2);
WAIT(clock_lo, 50, 3);
}
- /* parity [10] */
+
+ /* Parity bit */
_delay_us(15);
if (parity) { data_hi(); } else { data_lo(); }
WAIT(clock_hi, 50, 4);
WAIT(clock_lo, 50, 5);
- /* stop bit [11] */
+
+ /* Stop bit */
_delay_us(15);
data_hi();
- /* ack [12] */
+
+ /* Ack */
WAIT(data_lo, 50, 6);
WAIT(clock_lo, 50, 7);
@@ -144,127 +119,55 @@ uint8_t ps2_host_send(uint8_t data)
WAIT(clock_hi, 50, 8);
WAIT(data_hi, 50, 9);
+ idle();
PS2_USART_INIT();
PS2_USART_RX_INT_ON();
- res = ps2_host_recv_response();
+ return ps2_host_recv_response();
ERROR:
idle();
PS2_USART_INIT();
PS2_USART_RX_INT_ON();
- return res;
+ return 0;
}
-// Do polling data from keyboard to get response to last command.
uint8_t ps2_host_recv_response(void)
{
- while (!pbuf_has_data()) {
- _delay_ms(1); // without this delay it seems to fall into deadlock
+ // Command may take 25ms/20ms at most([5]p.46, [3]p.21)
+ uint8_t retry = 25;
+ while (retry-- && !pbuf_has_data()) {
+ _delay_ms(1);
}
return pbuf_dequeue();
}
uint8_t ps2_host_recv(void)
{
- return pbuf_dequeue();
+ if (pbuf_has_data()) {
+ ps2_error = PS2_ERR_NONE;
+ return pbuf_dequeue();
+ } else {
+ ps2_error = PS2_ERR_NODATA;
+ return 0;
+ }
}
ISR(PS2_USART_RX_VECT)
{
- uint8_t error = PS2_USART_ERROR;
+ // TODO: request RESEND when error occurs?
+ uint8_t error = PS2_USART_ERROR; // USART error should be read before data
uint8_t data = PS2_USART_RX_DATA;
if (!error) {
pbuf_enqueue(data);
+ } else {
+ xprintf("PS2 USART error: %02X data: %02X\n", error, data);
}
}
/* send LED state to keyboard */
void ps2_host_set_led(uint8_t led)
{
- // send 0xED then keyboard keeps waiting for next LED data
- // and keyboard does not send any scan codes during waiting.
- // If fail to send LED data keyboard looks like being freezed.
- uint8_t retry = 3;
- while (retry-- && ps2_host_send(PS2_SET_LED) != PS2_ACK)
- ;
- retry = 3;
- while (retry-- && ps2_host_send(led) != PS2_ACK)
- ;
-}
-
-
-/*--------------------------------------------------------------------
- * static functions
- *------------------------------------------------------------------*/
-static inline void clock_lo()
-{
- PS2_CLOCK_PORT &= ~(1<<PS2_CLOCK_BIT);
- PS2_CLOCK_DDR |= (1<<PS2_CLOCK_BIT);
-}
-static inline void clock_hi()
-{
- /* input with pull up */
- PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT);
- PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT);
-}
-static inline bool clock_in()
-{
- PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT);
- PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT);
- _delay_us(1);
- return PS2_CLOCK_PIN&(1<<PS2_CLOCK_BIT);
-}
-static inline void data_lo()
-{
- PS2_DATA_PORT &= ~(1<<PS2_DATA_BIT);
- PS2_DATA_DDR |= (1<<PS2_DATA_BIT);
-}
-static inline void data_hi()
-{
- /* input with pull up */
- PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT);
- PS2_DATA_PORT |= (1<<PS2_DATA_BIT);
-}
-static inline bool data_in()
-{
- PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT);
- PS2_DATA_PORT |= (1<<PS2_DATA_BIT);
- _delay_us(1);
- return PS2_DATA_PIN&(1<<PS2_DATA_BIT);
-}
-
-static inline uint16_t wait_clock_lo(uint16_t us)
-{
- while (clock_in() && us) { asm(""); _delay_us(1); us--; }
- return us;
-}
-static inline uint16_t wait_clock_hi(uint16_t us)
-{
- while (!clock_in() && us) { asm(""); _delay_us(1); us--; }
- return us;
-}
-static inline uint16_t wait_data_lo(uint16_t us)
-{
- while (data_in() && us) { asm(""); _delay_us(1); us--; }
- return us;
-}
-static inline uint16_t wait_data_hi(uint16_t us)
-{
- while (!data_in() && us) { asm(""); _delay_us(1); us--; }
- return us;
-}
-
-/* idle state that device can send */
-static inline void idle(void)
-{
- clock_hi();
- data_hi();
-}
-
-/* inhibit device to send */
-static inline void inhibit(void)
-{
- clock_lo();
- data_hi();
+ ps2_host_send(0xED);
+ ps2_host_send(led);
}
@@ -284,11 +187,10 @@ static inline void pbuf_enqueue(uint8_t data)
pbuf[pbuf_head] = data;
pbuf_head = next;
} else {
- debug("pbuf: full\n");
+ print("pbuf: full\n");
}
SREG = sreg;
}
-
static inline uint8_t pbuf_dequeue(void)
{
uint8_t val = 0;