summaryrefslogtreecommitdiff
path: root/tmk_core
diff options
context:
space:
mode:
authorJohSchneider <JohSchneider@googlemail.com>2021-08-05 21:51:24 +0000
committerGitHub <noreply@github.com>2021-08-06 07:51:24 +1000
commitbcb6e23387290afb64712314bfb095f8d96c1a4e (patch)
treec82814bce65ba34e28d7df885f23dd083d3c73d2 /tmk_core
parent5bbc527460462fb9961fbd9f972cd5e1c49558da (diff)
Arm ps2 mouse interrupt (#6490)
* ps2_mouse on ARM: an interrupt-version of the ps2-mouse code ported to ARM/chibios * ps2_mouse on ARM: link EXT callback-channel selection to the user defined PS2_LINE_CLOCK * ps2_mouse on ARM: replace DELAY_X defines with hardware-agnostic wait_X * ps2_mouse on ARM: replace chibios-specific defines for the pins/lines with defines from quantum/config_common.h and drop the '_LINE' component from teh define name * ps2_mouse on ARM: expose the software-intterupt port as a user editable define * Update docs/feature_ps2_mouse.md Co-Authored-By: Hugo van Kemenade <hugovk@users.noreply.github.com> * Update feature_ps2_mouse.md * use a define to deduce the PS_DATA_PORT instead * reduce all-zero extcfg to oneliner * ps2_mouse: use generic wait instead of avr-delay * Update docs/feature_ps2_mouse.md * ps2_mouse: changes for new chibios version (17.6.0 -> 19.1.0) replacing the legacy externa-interrupt driver with pal-callbacks * ps2_mouse: use PLATFORM_KEY Co-Authored-By: Joel Challis <git@zvecr.com> * ps2_mouse: clang-format corrections * ps2_mouse: add systemlocks using the chibios equivalent to AVRs cli: chSys[Unl|L]ock Co-authored-by: Johannes <you@example.com> Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com> Co-authored-by: Joel Challis <git@zvecr.com>
Diffstat (limited to 'tmk_core')
-rw-r--r--tmk_core/protocol.mk4
-rw-r--r--tmk_core/protocol/ps2_interrupt.c91
-rw-r--r--tmk_core/protocol/ps2_io_chibios.c55
-rw-r--r--tmk_core/protocol/ps2_mouse.c14
4 files changed, 146 insertions, 18 deletions
diff --git a/tmk_core/protocol.mk b/tmk_core/protocol.mk
index cc87e83478..b61f2f5463 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 5afc8a82e4..780040d152 100644
--- a/tmk_core/protocol/ps2_interrupt.c
+++ b/tmk_core/protocol/ps2_interrupt.c
@@ -40,11 +40,19 @@ POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdbool.h>
-#include <avr/interrupt.h>
-#include <util/delay.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 { \
@@ -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 0000000000..b672bd1f47
--- /dev/null
+++ b/tmk_core/protocol/ps2_io_chibios.c
@@ -0,0 +1,55 @@
+#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))
+# 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 5415453a05..525aeb45a0 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 <http://www.gnu.org/licenses/>.
*/
#include <stdbool.h>
-#include <avr/io.h>
-#include <util/delay.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"
@@ -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