diff options
author | Joel Challis <git@zvecr.com> | 2021-10-20 21:18:49 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-20 21:18:49 +0100 |
commit | d4be4b67a251ecc046d857c5cd00cfb37c394ab7 (patch) | |
tree | 15f6dd05ec293081782a9b42a30e1a81b33b6aa0 /tmk_core/protocol | |
parent | 5500c428dd41348243e8a1695986b0da070e2ffa (diff) | |
download | qmk_firmware-d4be4b67a251ecc046d857c5cd00cfb37c394ab7.tar.gz qmk_firmware-d4be4b67a251ecc046d857c5cd00cfb37c394ab7.zip |
Relocate PS2 code (#14895)
* Relocate ps2 protocol code
* clang
* Move makefile logic
Diffstat (limited to 'tmk_core/protocol')
-rw-r--r-- | tmk_core/protocol/ps2.h | 139 | ||||
-rw-r--r-- | tmk_core/protocol/ps2_busywait.c | 187 | ||||
-rw-r--r-- | tmk_core/protocol/ps2_interrupt.c | 340 | ||||
-rw-r--r-- | tmk_core/protocol/ps2_io.h | 11 | ||||
-rw-r--r-- | tmk_core/protocol/ps2_io_avr.c | 51 | ||||
-rw-r--r-- | tmk_core/protocol/ps2_io_chibios.c | 55 | ||||
-rw-r--r-- | tmk_core/protocol/ps2_mouse.c | 274 | ||||
-rw-r--r-- | tmk_core/protocol/ps2_mouse.h | 177 | ||||
-rw-r--r-- | tmk_core/protocol/ps2_usart.c | 226 |
9 files changed, 0 insertions, 1460 deletions
diff --git a/tmk_core/protocol/ps2.h b/tmk_core/protocol/ps2.h deleted file mode 100644 index f123192852..0000000000 --- a/tmk_core/protocol/ps2.h +++ /dev/null @@ -1,139 +0,0 @@ -/* -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. -*/ - -#pragma once - -#include <stdbool.h> -#include "wait.h" -#include "ps2_io.h" -#include "print.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 - */ -#define PS2_ACK 0xFA -#define PS2_RESEND 0xFE -#define PS2_SET_LED 0xED - -// 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 -#define PS2_LED_CAPS_LOCK 2 - -extern uint8_t ps2_error; - -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); - -/*-------------------------------------------------------------------- - * static functions - *------------------------------------------------------------------*/ -static inline uint16_t wait_clock_lo(uint16_t us) { - while (clock_in() && us) { - asm(""); - wait_us(1); - us--; - } - return us; -} -static inline uint16_t wait_clock_hi(uint16_t us) { - while (!clock_in() && us) { - asm(""); - wait_us(1); - us--; - } - return us; -} -static inline uint16_t wait_data_lo(uint16_t us) { - while (data_in() && us) { - asm(""); - wait_us(1); - us--; - } - return us; -} -static inline uint16_t wait_data_hi(uint16_t us) { - while (!data_in() && us) { - asm(""); - wait_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(); -} diff --git a/tmk_core/protocol/ps2_busywait.c b/tmk_core/protocol/ps2_busywait.c deleted file mode 100644 index 983194eea8..0000000000 --- a/tmk_core/protocol/ps2_busywait.c +++ /dev/null @@ -1,187 +0,0 @@ -/* -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 "wait.h" -#include "ps2.h" -#include "ps2_io.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) { - clock_init(); - data_init(); - - // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20) - wait_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(); - wait_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++) { - wait_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 */ - wait_us(15); - if (parity) { - data_hi(); - } else { - data_lo(); - } - WAIT(clock_hi, 50, 4); - WAIT(clock_lo, 50, 5); - - /* Stop bit */ - wait_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/tmk_core/protocol/ps2_interrupt.c b/tmk_core/protocol/ps2_interrupt.c deleted file mode 100644 index 70debd02f7..0000000000 --- a/tmk_core/protocol/ps2_interrupt.c +++ /dev/null @@ -1,340 +0,0 @@ -/* -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 Pin interrupt version - */ - -#include <stdbool.h> - -#if defined(__AVR__) -# include <avr/interrupt.h> -#elif defined(PROTOCOL_CHIBIOS) // TODO: or STM32 ? -// chibiOS headers -# include "ch.h" -# include "hal.h" -#endif - -#include "ps2.h" -#include "ps2_io.h" -#include "print.h" -#include "wait.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; - -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); - -#if defined(PROTOCOL_CHIBIOS) -void ps2_interrupt_service_routine(void); -void palCallback(void *arg) { ps2_interrupt_service_routine(); } - -# define PS2_INT_INIT() \ - { palSetLineMode(PS2_CLOCK_PIN, PAL_MODE_INPUT); } \ - while (0) -# define PS2_INT_ON() \ - { \ - palEnableLineEvent(PS2_CLOCK_PIN, PAL_EVENT_MODE_FALLING_EDGE); \ - palSetLineCallback(PS2_CLOCK_PIN, palCallback, NULL); \ - } \ - while (0) -# define PS2_INT_OFF() \ - { palDisableLineEvent(PS2_CLOCK_PIN); } \ - while (0) -#endif // PROTOCOL_CHIBIOS - -void ps2_host_init(void) { - idle(); - PS2_INT_INIT(); - PS2_INT_ON(); - // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20) - // wait_ms(2500); -} - -uint8_t ps2_host_send(uint8_t data) { - bool parity = true; - ps2_error = PS2_ERR_NONE; - - PS2_INT_OFF(); - - /* terminate a transmission if we have */ - inhibit(); - wait_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[2-9] */ - for (uint8_t i = 0; i < 8; i++) { - if (data & (1 << i)) { - parity = !parity; - data_hi(); - } else { - data_lo(); - } - WAIT(clock_hi, 50, 2); - WAIT(clock_lo, 50, 3); - } - - /* Parity bit */ - wait_us(15); - if (parity) { - data_hi(); - } else { - data_lo(); - } - WAIT(clock_hi, 50, 4); - WAIT(clock_lo, 50, 5); - - /* Stop bit */ - wait_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); - - idle(); - PS2_INT_ON(); - return ps2_host_recv_response(); -ERROR: - idle(); - PS2_INT_ON(); - return 0; -} - -uint8_t ps2_host_recv_response(void) { - // Command may take 25ms/20ms at most([5]p.46, [3]p.21) - uint8_t retry = 25; - while (retry-- && !pbuf_has_data()) { - wait_ms(1); - } - return pbuf_dequeue(); -} - -/* get data received by interrupt */ -uint8_t ps2_host_recv(void) { - if (pbuf_has_data()) { - ps2_error = PS2_ERR_NONE; - return pbuf_dequeue(); - } else { - ps2_error = PS2_ERR_NODATA; - return 0; - } -} - -void ps2_interrupt_service_routine(void) { - static enum { - INIT, - START, - BIT0, - BIT1, - BIT2, - BIT3, - BIT4, - BIT5, - BIT6, - BIT7, - PARITY, - STOP, - } state = INIT; - static uint8_t data = 0; - static uint8_t parity = 1; - - // TODO: abort if elapse 100us from previous interrupt - - // return unless falling edge - if (clock_in()) { - goto RETURN; - } - - state++; - switch (state) { - case START: - if (data_in()) goto ERROR; - break; - case BIT0: - case BIT1: - case BIT2: - case BIT3: - case BIT4: - case BIT5: - case BIT6: - case BIT7: - data >>= 1; - if (data_in()) { - data |= 0x80; - parity++; - } - break; - case PARITY: - if (data_in()) { - if (!(parity & 0x01)) goto ERROR; - } else { - if (parity & 0x01) goto ERROR; - } - break; - case STOP: - if (!data_in()) goto ERROR; - pbuf_enqueue(data); - goto DONE; - break; - default: - goto ERROR; - } - goto RETURN; -ERROR: - ps2_error = state; -DONE: - state = INIT; - data = 0; - parity = 1; -RETURN: - return; -} - -#if defined(__AVR__) -ISR(PS2_INT_VECT) { ps2_interrupt_service_routine(); } -#endif - -/* send LED state to keyboard */ -void ps2_host_set_led(uint8_t led) { - ps2_host_send(0xED); - ps2_host_send(led); -} - -/*-------------------------------------------------------------------- - * 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) { -#if defined(__AVR__) - uint8_t sreg = SREG; - cli(); -#elif defined(PROTOCOL_CHIBIOS) - chSysLockFromISR(); -#endif - - uint8_t next = (pbuf_head + 1) % PBUF_SIZE; - if (next != pbuf_tail) { - pbuf[pbuf_head] = data; - pbuf_head = next; - } else { - print("pbuf: full\n"); - } - -#if defined(__AVR__) - SREG = sreg; -#elif defined(PROTOCOL_CHIBIOS) - chSysUnlockFromISR(); -#endif -} -static inline uint8_t pbuf_dequeue(void) { - uint8_t val = 0; - -#if defined(__AVR__) - uint8_t sreg = SREG; - cli(); -#elif defined(PROTOCOL_CHIBIOS) - chSysLock(); -#endif - - if (pbuf_head != pbuf_tail) { - val = pbuf[pbuf_tail]; - pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE; - } - -#if defined(__AVR__) - SREG = sreg; -#elif defined(PROTOCOL_CHIBIOS) - chSysUnlock(); -#endif - - return val; -} -static inline bool pbuf_has_data(void) { -#if defined(__AVR__) - uint8_t sreg = SREG; - cli(); -#elif defined(PROTOCOL_CHIBIOS) - chSysLock(); -#endif - - bool has_data = (pbuf_head != pbuf_tail); - -#if defined(__AVR__) - SREG = sreg; -#elif defined(PROTOCOL_CHIBIOS) - chSysUnlock(); -#endif - return has_data; -} -static inline void pbuf_clear(void) { -#if defined(__AVR__) - uint8_t sreg = SREG; - cli(); -#elif defined(PROTOCOL_CHIBIOS) - chSysLock(); -#endif - - pbuf_head = pbuf_tail = 0; - -#if defined(__AVR__) - SREG = sreg; -#elif defined(PROTOCOL_CHIBIOS) - chSysUnlock(); -#endif -} diff --git a/tmk_core/protocol/ps2_io.h b/tmk_core/protocol/ps2_io.h deleted file mode 100644 index de93cb7a39..0000000000 --- a/tmk_core/protocol/ps2_io.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -void clock_init(void); -void clock_lo(void); -void clock_hi(void); -bool clock_in(void); - -void data_init(void); -void data_lo(void); -void data_hi(void); -bool data_in(void); diff --git a/tmk_core/protocol/ps2_io_avr.c b/tmk_core/protocol/ps2_io_avr.c deleted file mode 100644 index 7c826fbf1a..0000000000 --- a/tmk_core/protocol/ps2_io_avr.c +++ /dev/null @@ -1,51 +0,0 @@ -#include <stdbool.h> -#include "ps2_io.h" -#include "gpio.h" -#include "wait.h" - -/* Check port settings for clock and data line */ -#if !(defined(PS2_CLOCK_PIN)) -# error "PS/2 clock setting is required in config.h" -#endif - -#if !(defined(PS2_DATA_PIN)) -# error "PS/2 data setting is required in config.h" -#endif - -/* - * Clock - */ -void clock_init(void) {} - -void clock_lo(void) { - // Transition from input with pull-up to output low via Hi-Z instead of output high - writePinLow(PS2_CLOCK_PIN); - setPinOutput(PS2_CLOCK_PIN); -} - -void clock_hi(void) { setPinInputHigh(PS2_CLOCK_PIN); } - -bool clock_in(void) { - setPinInputHigh(PS2_CLOCK_PIN); - wait_us(1); - return readPin(PS2_CLOCK_PIN); -} - -/* - * Data - */ -void data_init(void) {} - -void data_lo(void) { - // Transition from input with pull-up to output low via Hi-Z instead of output high - writePinLow(PS2_DATA_PIN); - setPinOutput(PS2_DATA_PIN); -} - -void data_hi(void) { setPinInputHigh(PS2_DATA_PIN); } - -bool data_in(void) { - setPinInputHigh(PS2_DATA_PIN); - wait_us(1); - return readPin(PS2_DATA_PIN); -} diff --git a/tmk_core/protocol/ps2_io_chibios.c b/tmk_core/protocol/ps2_io_chibios.c deleted file mode 100644 index 906d85d848..0000000000 --- a/tmk_core/protocol/ps2_io_chibios.c +++ /dev/null @@ -1,55 +0,0 @@ -#include <stdbool.h> -#include "ps2_io.h" - -// chibiOS headers -#include "ch.h" -#include "hal.h" - -/* Check port settings for clock and data line */ -#if !(defined(PS2_CLOCK_PIN)) -# error "PS/2 clock setting is required in config.h" -#endif - -#if !(defined(PS2_DATA_PIN)) -# error "PS/2 data setting is required in config.h" -#endif - -/* - * Clock - */ -void clock_init(void) {} - -void clock_lo(void) { - palSetLineMode(PS2_CLOCK_PIN, PAL_MODE_OUTPUT_OPENDRAIN); - palWriteLine(PS2_CLOCK_PIN, PAL_LOW); -} - -void clock_hi(void) { - palSetLineMode(PS2_CLOCK_PIN, PAL_MODE_OUTPUT_OPENDRAIN); - palWriteLine(PS2_CLOCK_PIN, PAL_HIGH); -} - -bool clock_in(void) { - palSetLineMode(PS2_CLOCK_PIN, PAL_MODE_INPUT); - return palReadLine(PS2_CLOCK_PIN); -} - -/* - * Data - */ -void data_init(void) {} - -void data_lo(void) { - palSetLineMode(PS2_DATA_PIN, PAL_MODE_OUTPUT_OPENDRAIN); - palWriteLine(PS2_DATA_PIN, PAL_LOW); -} - -void data_hi(void) { - palSetLineMode(PS2_DATA_PIN, PAL_MODE_OUTPUT_OPENDRAIN); - palWriteLine(PS2_DATA_PIN, PAL_HIGH); -} - -bool data_in(void) { - palSetLineMode(PS2_DATA_PIN, PAL_MODE_INPUT); - return palReadLine(PS2_DATA_PIN); -} diff --git a/tmk_core/protocol/ps2_mouse.c b/tmk_core/protocol/ps2_mouse.c deleted file mode 100644 index 39251a6434..0000000000 --- a/tmk_core/protocol/ps2_mouse.c +++ /dev/null @@ -1,274 +0,0 @@ -/* -Copyright 2011,2013 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 <stdbool.h> - -#if defined(__AVR__) -# include <avr/io.h> -#endif - -#include "ps2_mouse.h" -#include "wait.h" -#include "host.h" -#include "timer.h" -#include "print.h" -#include "report.h" -#include "debug.h" -#include "ps2.h" - -/* ============================= MACROS ============================ */ - -static report_mouse_t mouse_report = {}; - -static inline void ps2_mouse_print_report(report_mouse_t *mouse_report); -static inline void ps2_mouse_convert_report_to_hid(report_mouse_t *mouse_report); -static inline void ps2_mouse_clear_report(report_mouse_t *mouse_report); -static inline void ps2_mouse_enable_scrolling(void); -static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report); - -/* ============================= IMPLEMENTATION ============================ */ - -/* supports only 3 button mouse at this time */ -void ps2_mouse_init(void) { - ps2_host_init(); - - wait_ms(PS2_MOUSE_INIT_DELAY); // wait for powering up - - PS2_MOUSE_SEND(PS2_MOUSE_RESET, "ps2_mouse_init: sending reset"); - - PS2_MOUSE_RECEIVE("ps2_mouse_init: read BAT"); - PS2_MOUSE_RECEIVE("ps2_mouse_init: read DevID"); - -#ifdef PS2_MOUSE_USE_REMOTE_MODE - ps2_mouse_set_remote_mode(); -#else - ps2_mouse_enable_data_reporting(); -#endif - -#ifdef PS2_MOUSE_ENABLE_SCROLLING - ps2_mouse_enable_scrolling(); -#endif - -#ifdef PS2_MOUSE_USE_2_1_SCALING - ps2_mouse_set_scaling_2_1(); -#endif - - ps2_mouse_init_user(); -} - -__attribute__((weak)) void ps2_mouse_init_user(void) {} - -__attribute__((weak)) void ps2_mouse_moved_user(report_mouse_t *mouse_report) {} - -void ps2_mouse_task(void) { - static uint8_t buttons_prev = 0; - extern int tp_buttons; - - /* receives packet from mouse */ - uint8_t rcv; - rcv = ps2_host_send(PS2_MOUSE_READ_DATA); - if (rcv == PS2_ACK) { - mouse_report.buttons = ps2_host_recv_response() | tp_buttons; - mouse_report.x = ps2_host_recv_response() * PS2_MOUSE_X_MULTIPLIER; - mouse_report.y = ps2_host_recv_response() * PS2_MOUSE_Y_MULTIPLIER; -#ifdef PS2_MOUSE_ENABLE_SCROLLING - mouse_report.v = -(ps2_host_recv_response() & PS2_MOUSE_SCROLL_MASK) * PS2_MOUSE_V_MULTIPLIER; -#endif - } else { - if (debug_mouse) print("ps2_mouse: fail to get mouse packet\n"); - return; - } - - /* if mouse moves or buttons state changes */ - if (mouse_report.x || mouse_report.y || mouse_report.v || ((mouse_report.buttons ^ buttons_prev) & PS2_MOUSE_BTN_MASK)) { -#ifdef PS2_MOUSE_DEBUG_RAW - // Used to debug raw ps2 bytes from mouse - ps2_mouse_print_report(&mouse_report); -#endif - buttons_prev = mouse_report.buttons; - ps2_mouse_convert_report_to_hid(&mouse_report); -#if PS2_MOUSE_SCROLL_BTN_MASK - ps2_mouse_scroll_button_task(&mouse_report); -#endif - if (mouse_report.x || mouse_report.y || mouse_report.v) { - ps2_mouse_moved_user(&mouse_report); - } -#ifdef PS2_MOUSE_DEBUG_HID - // Used to debug the bytes sent to the host - ps2_mouse_print_report(&mouse_report); -#endif - host_mouse_send(&mouse_report); - } - - ps2_mouse_clear_report(&mouse_report); -} - -void ps2_mouse_disable_data_reporting(void) { PS2_MOUSE_SEND(PS2_MOUSE_DISABLE_DATA_REPORTING, "ps2 mouse disable data reporting"); } - -void ps2_mouse_enable_data_reporting(void) { PS2_MOUSE_SEND(PS2_MOUSE_ENABLE_DATA_REPORTING, "ps2 mouse enable data reporting"); } - -void ps2_mouse_set_remote_mode(void) { - PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_REMOTE_MODE, "ps2 mouse set remote mode"); - ps2_mouse_mode = PS2_MOUSE_REMOTE_MODE; -} - -void ps2_mouse_set_stream_mode(void) { - PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_STREAM_MODE, "ps2 mouse set stream mode"); - ps2_mouse_mode = PS2_MOUSE_STREAM_MODE; -} - -void ps2_mouse_set_scaling_2_1(void) { PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_2_1, "ps2 mouse set scaling 2:1"); } - -void ps2_mouse_set_scaling_1_1(void) { PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_1_1, "ps2 mouse set scaling 1:1"); } - -void ps2_mouse_set_resolution(ps2_mouse_resolution_t resolution) { PS2_MOUSE_SET_SAFE(PS2_MOUSE_SET_RESOLUTION, resolution, "ps2 mouse set resolution"); } - -void ps2_mouse_set_sample_rate(ps2_mouse_sample_rate_t sample_rate) { PS2_MOUSE_SET_SAFE(PS2_MOUSE_SET_SAMPLE_RATE, sample_rate, "ps2 mouse set sample rate"); } - -/* ============================= HELPERS ============================ */ - -#define X_IS_NEG (mouse_report->buttons & (1 << PS2_MOUSE_X_SIGN)) -#define Y_IS_NEG (mouse_report->buttons & (1 << PS2_MOUSE_Y_SIGN)) -#define X_IS_OVF (mouse_report->buttons & (1 << PS2_MOUSE_X_OVFLW)) -#define Y_IS_OVF (mouse_report->buttons & (1 << PS2_MOUSE_Y_OVFLW)) -static inline void ps2_mouse_convert_report_to_hid(report_mouse_t *mouse_report) { - // PS/2 mouse data is '9-bit integer'(-256 to 255) which is comprised of sign-bit and 8-bit value. - // bit: 8 7 ... 0 - // sign \8-bit/ - // - // Meanwhile USB HID mouse indicates 8bit data(-127 to 127), note that -128 is not used. - // - // This converts PS/2 data into HID value. Use only -127-127 out of PS/2 9-bit. - mouse_report->x = X_IS_NEG ? ((!X_IS_OVF && -127 <= mouse_report->x && mouse_report->x <= -1) ? mouse_report->x : -127) : ((!X_IS_OVF && 0 <= mouse_report->x && mouse_report->x <= 127) ? mouse_report->x : 127); - mouse_report->y = Y_IS_NEG ? ((!Y_IS_OVF && -127 <= mouse_report->y && mouse_report->y <= -1) ? mouse_report->y : -127) : ((!Y_IS_OVF && 0 <= mouse_report->y && mouse_report->y <= 127) ? mouse_report->y : 127); - -#ifdef PS2_MOUSE_INVERT_BUTTONS - // swap left & right buttons - uint8_t needs_left = mouse_report->buttons & PS2_MOUSE_BTN_RIGHT; - uint8_t needs_right = mouse_report->buttons & PS2_MOUSE_BTN_LEFT; - mouse_report->buttons = (mouse_report->buttons & ~(PS2_MOUSE_BTN_MASK)) | (needs_left ? PS2_MOUSE_BTN_LEFT : 0) | (needs_right ? PS2_MOUSE_BTN_RIGHT : 0); -#else - // remove sign and overflow flags - mouse_report->buttons &= PS2_MOUSE_BTN_MASK; -#endif - -#ifdef PS2_MOUSE_INVERT_X - mouse_report->x = -mouse_report->x; -#endif -#ifndef PS2_MOUSE_INVERT_Y // NOTE if not! - // invert coordinate of y to conform to USB HID mouse - mouse_report->y = -mouse_report->y; -#endif - -#ifdef PS2_MOUSE_ROTATE - int8_t x = mouse_report->x; - int8_t y = mouse_report->y; -# if PS2_MOUSE_ROTATE == 90 - mouse_report->x = y; - mouse_report->y = -x; -# elif PS2_MOUSE_ROTATE == 180 - mouse_report->x = -x; - mouse_report->y = -y; -# elif PS2_MOUSE_ROTATE == 270 - mouse_report->x = -y; - mouse_report->y = x; -# endif -#endif -} - -static inline void ps2_mouse_clear_report(report_mouse_t *mouse_report) { - mouse_report->x = 0; - mouse_report->y = 0; - mouse_report->v = 0; - mouse_report->h = 0; - mouse_report->buttons = 0; -} - -static inline void ps2_mouse_print_report(report_mouse_t *mouse_report) { - if (!debug_mouse) return; - print("ps2_mouse: ["); - print_hex8(mouse_report->buttons); - print("|"); - print_hex8((uint8_t)mouse_report->x); - print(" "); - print_hex8((uint8_t)mouse_report->y); - print(" "); - print_hex8((uint8_t)mouse_report->v); - print(" "); - print_hex8((uint8_t)mouse_report->h); - print("]\n"); -} - -static inline void ps2_mouse_enable_scrolling(void) { - PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Initiaing scroll wheel enable: Set sample rate"); - PS2_MOUSE_SEND(200, "200"); - PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Set sample rate"); - PS2_MOUSE_SEND(100, "100"); - PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Set sample rate"); - PS2_MOUSE_SEND(80, "80"); - PS2_MOUSE_SEND(PS2_MOUSE_GET_DEVICE_ID, "Finished enabling scroll wheel"); - wait_ms(20); -} - -#define PRESS_SCROLL_BUTTONS mouse_report->buttons |= (PS2_MOUSE_SCROLL_BTN_MASK) -#define RELEASE_SCROLL_BUTTONS mouse_report->buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK) -static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report) { - static enum { - SCROLL_NONE, - SCROLL_BTN, - SCROLL_SENT, - } scroll_state = SCROLL_NONE; - static uint16_t scroll_button_time = 0; - - if (PS2_MOUSE_SCROLL_BTN_MASK == (mouse_report->buttons & (PS2_MOUSE_SCROLL_BTN_MASK))) { - // All scroll buttons are pressed - - if (scroll_state == SCROLL_NONE) { - scroll_button_time = timer_read(); - scroll_state = SCROLL_BTN; - } - - // If the mouse has moved, update the report to scroll instead of move the mouse - if (mouse_report->x || mouse_report->y) { - scroll_state = SCROLL_SENT; - mouse_report->v = -mouse_report->y / (PS2_MOUSE_SCROLL_DIVISOR_V); - mouse_report->h = mouse_report->x / (PS2_MOUSE_SCROLL_DIVISOR_H); - mouse_report->x = 0; - mouse_report->y = 0; -#ifdef PS2_MOUSE_INVERT_H - mouse_report->h = -mouse_report->h; -#endif -#ifdef PS2_MOUSE_INVERT_V - mouse_report->v = -mouse_report->v; -#endif - } - } else if (0 == (PS2_MOUSE_SCROLL_BTN_MASK & mouse_report->buttons)) { - // None of the scroll buttons are pressed - -#if PS2_MOUSE_SCROLL_BTN_SEND - if (scroll_state == SCROLL_BTN && timer_elapsed(scroll_button_time) < PS2_MOUSE_SCROLL_BTN_SEND) { - PRESS_SCROLL_BUTTONS; - host_mouse_send(mouse_report); - wait_ms(100); - RELEASE_SCROLL_BUTTONS; - } -#endif - scroll_state = SCROLL_NONE; - } - - RELEASE_SCROLL_BUTTONS; -} diff --git a/tmk_core/protocol/ps2_mouse.h b/tmk_core/protocol/ps2_mouse.h deleted file mode 100644 index c97c6c893a..0000000000 --- a/tmk_core/protocol/ps2_mouse.h +++ /dev/null @@ -1,177 +0,0 @@ -/* -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/>. -*/ - -#pragma once - -#include <stdbool.h> -#include "debug.h" -#include "report.h" - -#define PS2_MOUSE_SEND(command, message) \ - do { \ - __attribute__((unused)) uint8_t rcv = ps2_host_send(command); \ - if (debug_mouse) { \ - print((message)); \ - xprintf(" command: %X, result: %X, error: %X \n", command, rcv, ps2_error); \ - } \ - } while (0) - -#define PS2_MOUSE_SEND_SAFE(command, message) \ - do { \ - if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \ - ps2_mouse_disable_data_reporting(); \ - } \ - PS2_MOUSE_SEND(command, message); \ - if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \ - ps2_mouse_enable_data_reporting(); \ - } \ - } while (0) - -#define PS2_MOUSE_SET_SAFE(command, value, message) \ - do { \ - if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \ - ps2_mouse_disable_data_reporting(); \ - } \ - PS2_MOUSE_SEND(command, message); \ - PS2_MOUSE_SEND(value, "Sending value"); \ - if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \ - ps2_mouse_enable_data_reporting(); \ - } \ - } while (0) - -#define PS2_MOUSE_RECEIVE(message) \ - do { \ - __attribute__((unused)) uint8_t rcv = ps2_host_recv_response(); \ - if (debug_mouse) { \ - print((message)); \ - xprintf(" result: %X, error: %X \n", rcv, ps2_error); \ - } \ - } while (0) - -__attribute__((unused)) static enum ps2_mouse_mode_e { - PS2_MOUSE_STREAM_MODE, - PS2_MOUSE_REMOTE_MODE, -} ps2_mouse_mode = PS2_MOUSE_STREAM_MODE; - -/* - * Data format: - * byte|7 6 5 4 3 2 1 0 - * ----+---------------------------------------------------------------- - * 0|[Yovflw][Xovflw][Ysign ][Xsign ][ 1 ][Middle][Right ][Left ] - * 1|[ X movement(0-255) ] - * 2|[ Y movement(0-255) ] - */ -#define PS2_MOUSE_BTN_MASK 0x07 -#define PS2_MOUSE_BTN_LEFT 0 -#define PS2_MOUSE_BTN_RIGHT 1 -#define PS2_MOUSE_BTN_MIDDLE 2 -#define PS2_MOUSE_X_SIGN 4 -#define PS2_MOUSE_Y_SIGN 5 -#define PS2_MOUSE_X_OVFLW 6 -#define PS2_MOUSE_Y_OVFLW 7 - -/* mouse button to start scrolling; set 0 to disable scroll */ -#ifndef PS2_MOUSE_SCROLL_BTN_MASK -# define PS2_MOUSE_SCROLL_BTN_MASK (1 << PS2_MOUSE_BTN_MIDDLE) -#endif -/* send button event when button is released within this value(ms); set 0 to disable */ -#ifndef PS2_MOUSE_SCROLL_BTN_SEND -# define PS2_MOUSE_SCROLL_BTN_SEND 300 -#endif -/* divide virtical and horizontal mouse move by this to convert to scroll move */ -#ifndef PS2_MOUSE_SCROLL_DIVISOR_V -# define PS2_MOUSE_SCROLL_DIVISOR_V 2 -#endif -#ifndef PS2_MOUSE_SCROLL_DIVISOR_H -# define PS2_MOUSE_SCROLL_DIVISOR_H 2 -#endif -/* multiply reported mouse values by these */ -#ifndef PS2_MOUSE_X_MULTIPLIER -# define PS2_MOUSE_X_MULTIPLIER 1 -#endif -#ifndef PS2_MOUSE_Y_MULTIPLIER -# define PS2_MOUSE_Y_MULTIPLIER 1 -#endif -#ifndef PS2_MOUSE_V_MULTIPLIER -# define PS2_MOUSE_V_MULTIPLIER 1 -#endif -/* For some mice this will need to be 0x0F */ -#ifndef PS2_MOUSE_SCROLL_MASK -# define PS2_MOUSE_SCROLL_MASK 0xFF -#endif -#ifndef PS2_MOUSE_INIT_DELAY -# define PS2_MOUSE_INIT_DELAY 1000 -#endif - -enum ps2_mouse_command_e { - PS2_MOUSE_RESET = 0xFF, - PS2_MOUSE_RESEND = 0xFE, - PS2_MOSUE_SET_DEFAULTS = 0xF6, - PS2_MOUSE_DISABLE_DATA_REPORTING = 0xF5, - PS2_MOUSE_ENABLE_DATA_REPORTING = 0xF4, - PS2_MOUSE_SET_SAMPLE_RATE = 0xF3, - PS2_MOUSE_GET_DEVICE_ID = 0xF2, - PS2_MOUSE_SET_REMOTE_MODE = 0xF0, - PS2_MOUSE_SET_WRAP_MODE = 0xEC, - PS2_MOUSE_READ_DATA = 0xEB, - PS2_MOUSE_SET_STREAM_MODE = 0xEA, - PS2_MOUSE_STATUS_REQUEST = 0xE9, - PS2_MOUSE_SET_RESOLUTION = 0xE8, - PS2_MOUSE_SET_SCALING_2_1 = 0xE7, - PS2_MOUSE_SET_SCALING_1_1 = 0xE6, -}; - -typedef enum ps2_mouse_resolution_e { - PS2_MOUSE_1_COUNT_MM, - PS2_MOUSE_2_COUNT_MM, - PS2_MOUSE_4_COUNT_MM, - PS2_MOUSE_8_COUNT_MM, -} ps2_mouse_resolution_t; - -typedef enum ps2_mouse_sample_rate_e { - PS2_MOUSE_10_SAMPLES_SEC = 10, - PS2_MOUSE_20_SAMPLES_SEC = 20, - PS2_MOUSE_40_SAMPLES_SEC = 40, - PS2_MOUSE_60_SAMPLES_SEC = 60, - PS2_MOUSE_80_SAMPLES_SEC = 80, - PS2_MOUSE_100_SAMPLES_SEC = 100, - PS2_MOUSE_200_SAMPLES_SEC = 200, -} ps2_mouse_sample_rate_t; - -void ps2_mouse_init(void); - -void ps2_mouse_init_user(void); - -void ps2_mouse_task(void); - -void ps2_mouse_disable_data_reporting(void); - -void ps2_mouse_enable_data_reporting(void); - -void ps2_mouse_set_remote_mode(void); - -void ps2_mouse_set_stream_mode(void); - -void ps2_mouse_set_scaling_2_1(void); - -void ps2_mouse_set_scaling_1_1(void); - -void ps2_mouse_set_resolution(ps2_mouse_resolution_t resolution); - -void ps2_mouse_set_sample_rate(ps2_mouse_sample_rate_t sample_rate); - -void ps2_mouse_moved_user(report_mouse_t *mouse_report); diff --git a/tmk_core/protocol/ps2_usart.c b/tmk_core/protocol/ps2_usart.c deleted file mode 100644 index 5f70083698..0000000000 --- a/tmk_core/protocol/ps2_usart.c +++ /dev/null @@ -1,226 +0,0 @@ -/* -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 USART version - */ - -#include <stdbool.h> -#include <avr/interrupt.h> -#include <util/delay.h> -#include "ps2.h" -#include "ps2_io.h" -#include "print.h" - -#ifndef PS2_CLOCK_DDR -# define PS2_CLOCK_DDR PORTx_ADDRESS(PS2_CLOCK_PIN) -#endif -#ifndef PS2_CLOCK_BIT -# define PS2_CLOCK_BIT (PS2_CLOCK_PIN & 0xF) -#endif -#ifndef PS2_DATA_DDR -# define PS2_DATA_DDR PORTx_ADDRESS(PS2_DATA_PIN) -#endif -#ifndef PS2_DATA_BIT -# define PS2_DATA_BIT (PS2_DATA_PIN & 0xF) -#endif - -#define WAIT(stat, us, err) \ - do { \ - if (!wait_##stat(us)) { \ - ps2_error = err; \ - goto ERROR; \ - } \ - } while (0) - -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) { - 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) { - bool parity = true; - ps2_error = PS2_ERR_NONE; - - PS2_USART_OFF(); - - /* terminate a transmission if we have */ - inhibit(); - _delay_us(100); // [4]p.13 - - /* 'Request to Send' and Start bit */ - data_lo(); - clock_hi(); - 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)) { - 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); - - idle(); - PS2_USART_INIT(); - PS2_USART_RX_INT_ON(); - return ps2_host_recv_response(); -ERROR: - idle(); - PS2_USART_INIT(); - PS2_USART_RX_INT_ON(); - return 0; -} - -uint8_t ps2_host_recv_response(void) { - // 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) { - 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) { - // 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) { - ps2_host_send(0xED); - ps2_host_send(led); -} - -/*-------------------------------------------------------------------- - * 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 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"); - } - 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; - } - 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; -} |