Skip to content

Commit

Permalink
Arm ps2 mouse interrupt (#6490)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
4 people authored Aug 5, 2021
1 parent 5bbc527 commit bcb6e23
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 20 deletions.
28 changes: 26 additions & 2 deletions docs/feature_ps2_mouse.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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.

Expand Down
4 changes: 2 additions & 2 deletions tmk_core/protocol.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
91 changes: 80 additions & 11 deletions tmk_core/protocol/ps2_interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 { \
Expand All @@ -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) {
Expand All @@ -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();
Expand All @@ -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();
Expand All @@ -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 {
Expand All @@ -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 */
Expand All @@ -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();
}
Expand All @@ -148,7 +173,7 @@ uint8_t ps2_host_recv(void) {
}
}

ISR(PS2_INT_VECT) {
void ps2_interrupt_service_routine(void) {
static enum {
INIT,
START,
Expand Down Expand Up @@ -218,6 +243,10 @@ ISR(PS2_INT_VECT) {
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);
Expand All @@ -232,40 +261,80 @@ 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);
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
}
55 changes: 55 additions & 0 deletions tmk_core/protocol/ps2_io_chibios.c
Original file line number Diff line number Diff line change
@@ -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);
}
14 changes: 9 additions & 5 deletions tmk_core/protocol/ps2_mouse.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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");

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit bcb6e23

Please sign in to comment.