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>
This commit is contained in:
		
							parent
							
								
									5bbc527460
								
							
						
					
					
						commit
						bcb6e23387
					
				
					 5 changed files with 172 additions and 20 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										55
									
								
								tmk_core/protocol/ps2_io_chibios.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								tmk_core/protocol/ps2_io_chibios.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue