diff --git a/docs/feature_ps2_mouse.md b/docs/feature_ps2_mouse.md index 8e84e22d8a7..00c7ee72ee9 100644 --- a/docs/feature_ps2_mouse.md +++ b/docs/feature_ps2_mouse.md @@ -50,7 +50,7 @@ In your keyboard config.h: #endif ``` -## Interrupt Version :id=interrupt-version +### Interrupt Version (AVR/ATMega32u4) :id=interrupt-version-avr The following example uses D2 for clock and D5 for data. You can use any INT or PCINT pin for clock, and any pin for data. @@ -88,7 +88,31 @@ In your keyboard config.h: #endif ``` -## USART Version :id=usart-version +### Interrupt Version (ARM chibios) :id=interrupt-version-chibios + +Pretty much any two pins can be used for the (software) interrupt variant on ARM cores. The example below uses A8 for clock, and A9 for data. + +In rules.mk: + +``` +PS2_MOUSE_ENABLE = yes +PS2_USE_INT = yes +``` + +In your keyboard config.h: + +```c +#define PS2_CLOCK A8 +#define PS2_DATA A9 +``` + +And in the chibios specifig halconf.h: +```c +#define PAL_USE_CALLBACKS TRUE +``` + + +### USART Version :id=usart-version To use USART on the ATMega32u4, you have to use PD5 for clock and PD2 for data. If one of those are unavailable, you need to use interrupt version. diff --git a/tmk_core/protocol.mk b/tmk_core/protocol.mk index cc87e834783..b61f2f5463a 100644 --- a/tmk_core/protocol.mk +++ b/tmk_core/protocol.mk @@ -14,13 +14,13 @@ endif ifeq ($(strip $(PS2_USE_INT)), yes) SRC += protocol/ps2_interrupt.c - SRC += protocol/ps2_io_avr.c + SRC += protocol/ps2_io_$(PLATFORM_KEY).c OPT_DEFS += -DPS2_USE_INT endif ifeq ($(strip $(PS2_USE_USART)), yes) SRC += protocol/ps2_usart.c - SRC += protocol/ps2_io_avr.c + SRC += protocol/ps2_io_$(PLATFORM_KEY).c OPT_DEFS += -DPS2_USE_USART endif diff --git a/tmk_core/protocol/ps2_interrupt.c b/tmk_core/protocol/ps2_interrupt.c index 5afc8a82e47..780040d1526 100644 --- a/tmk_core/protocol/ps2_interrupt.c +++ b/tmk_core/protocol/ps2_interrupt.c @@ -40,11 +40,19 @@ POSSIBILITY OF SUCH DAMAGE. */ #include -#include -#include + +#if defined(__AVR__) +# include +#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 { \ @@ -61,12 +69,30 @@ 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, PAL_MODE_INPUT); } \ + while (0) +# define PS2_INT_ON() \ + { \ + palEnableLineEvent(PS2_CLOCK, PAL_EVENT_MODE_FALLING_EDGE); \ + palSetLineCallback(PS2_CLOCK, palCallback, NULL); \ + } \ + while (0) +# define PS2_INT_OFF() \ + { palDisableLineEvent(PS2_CLOCK); } \ + 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) - //_delay_ms(2500); + // wait_ms(2500); } uint8_t ps2_host_send(uint8_t data) { @@ -77,7 +103,7 @@ uint8_t ps2_host_send(uint8_t data) { /* terminate a transmission if we have */ inhibit(); - _delay_us(100); // 100us [4]p.13, [5]p.50 + wait_us(100); // 100us [4]p.13, [5]p.50 /* 'Request to Send' and Start bit */ data_lo(); @@ -86,7 +112,6 @@ uint8_t ps2_host_send(uint8_t data) { /* Data bit[2-9] */ for (uint8_t i = 0; i < 8; i++) { - _delay_us(15); if (data & (1 << i)) { parity = !parity; data_hi(); @@ -98,7 +123,7 @@ uint8_t ps2_host_send(uint8_t data) { } /* Parity bit */ - _delay_us(15); + wait_us(15); if (parity) { data_hi(); } else { @@ -108,7 +133,7 @@ uint8_t ps2_host_send(uint8_t data) { WAIT(clock_lo, 50, 5); /* Stop bit */ - _delay_us(15); + wait_us(15); data_hi(); /* Ack */ @@ -132,7 +157,7 @@ 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); + wait_ms(1); } return pbuf_dequeue(); } @@ -148,7 +173,7 @@ uint8_t ps2_host_recv(void) { } } -ISR(PS2_INT_VECT) { +void ps2_interrupt_service_routine(void) { static enum { INIT, START, @@ -218,6 +243,10 @@ 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); @@ -232,8 +261,13 @@ 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; @@ -241,31 +275,66 @@ static inline void pbuf_enqueue(uint8_t data) { } 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); - SREG = sreg; + +#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; - SREG = sreg; + +#if defined(__AVR__) + SREG = sreg; +#elif defined(PROTOCOL_CHIBIOS) + chSysUnlock(); +#endif } diff --git a/tmk_core/protocol/ps2_io_chibios.c b/tmk_core/protocol/ps2_io_chibios.c new file mode 100644 index 00000000000..b672bd1f47f --- /dev/null +++ b/tmk_core/protocol/ps2_io_chibios.c @@ -0,0 +1,55 @@ +#include +#include "ps2_io.h" + +// chibiOS headers +#include "ch.h" +#include "hal.h" + +/* Check port settings for clock and data line */ +#if !(defined(PS2_CLOCK)) +# error "PS/2 clock setting is required in config.h" +#endif + +#if !(defined(PS2_DATA)) +# error "PS/2 data setting is required in config.h" +#endif + +/* + * Clock + */ +void clock_init(void) {} + +void clock_lo(void) { + palSetLineMode(PS2_CLOCK, PAL_MODE_OUTPUT_OPENDRAIN); + palWriteLine(PS2_CLOCK, PAL_LOW); +} + +void clock_hi(void) { + palSetLineMode(PS2_CLOCK, PAL_MODE_OUTPUT_OPENDRAIN); + palWriteLine(PS2_CLOCK, PAL_HIGH); +} + +bool clock_in(void) { + palSetLineMode(PS2_CLOCK, PAL_MODE_INPUT); + return palReadLine(PS2_CLOCK); +} + +/* + * Data + */ +void data_init(void) {} + +void data_lo(void) { + palSetLineMode(PS2_DATA, PAL_MODE_OUTPUT_OPENDRAIN); + palWriteLine(PS2_DATA, PAL_LOW); +} + +void data_hi(void) { + palSetLineMode(PS2_DATA, PAL_MODE_OUTPUT_OPENDRAIN); + palWriteLine(PS2_DATA, PAL_HIGH); +} + +bool data_in(void) { + palSetLineMode(PS2_DATA, PAL_MODE_INPUT); + return palReadLine(PS2_DATA); +} diff --git a/tmk_core/protocol/ps2_mouse.c b/tmk_core/protocol/ps2_mouse.c index 5415453a05f..525aeb45a04 100644 --- a/tmk_core/protocol/ps2_mouse.c +++ b/tmk_core/protocol/ps2_mouse.c @@ -16,9 +16,13 @@ along with this program. If not, see . */ #include -#include -#include + +#if defined(__AVR__) +# include +#endif + #include "ps2_mouse.h" +#include "wait.h" #include "host.h" #include "timer.h" #include "print.h" @@ -42,7 +46,7 @@ static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report); void ps2_mouse_init(void) { ps2_host_init(); - _delay_ms(PS2_MOUSE_INIT_DELAY); // wait for powering up + wait_ms(PS2_MOUSE_INIT_DELAY); // wait for powering up PS2_MOUSE_SEND(PS2_MOUSE_RESET, "ps2_mouse_init: sending reset"); @@ -210,7 +214,7 @@ static inline void ps2_mouse_enable_scrolling(void) { 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"); - _delay_ms(20); + wait_ms(20); } #define PRESS_SCROLL_BUTTONS mouse_report->buttons |= (PS2_MOUSE_SCROLL_BTN_MASK) @@ -252,7 +256,7 @@ static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report) { if (scroll_state == SCROLL_BTN && timer_elapsed(scroll_button_time) < PS2_MOUSE_SCROLL_BTN_SEND) { PRESS_SCROLL_BUTTONS; host_mouse_send(mouse_report); - _delay_ms(100); + wait_ms(100); RELEASE_SCROLL_BUTTONS; } #endif