using ps2x2pico as a library

This commit is contained in:
Maxim Devaev 2023-09-09 13:07:30 +03:00
parent a03c3c2367
commit 2189b77c07
9 changed files with 20 additions and 220 deletions

1
hid/pico/.gitignore vendored
View File

@ -1,4 +1,5 @@
/.pico-sdk*
/.tinyusb*
/.ps2x2pico*
/.build/
/*.uf2

View File

@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.13)
set(PICO_SDK_PATH ${CMAKE_CURRENT_LIST_DIR}/.pico-sdk)
set(PICO_TINYUSB_PATH ${CMAKE_CURRENT_LIST_DIR}/.tinyusb)
# TODO: PS2: set(PS2_PATH ${CMAKE_CURRENT_LIST_DIR}/.yourlib/subdir)
SET(PS2_PATH ${CMAKE_CURRENT_LIST_DIR}/.ps2x2pico)
# For TinyUSB
set(FAMILY rp2040)

View File

@ -15,7 +15,7 @@ install: all
clean:
rm -rf .build hid.uf2
clean-all: clean
rm -rf .pico-sdk* .tinyusb*
rm -rf .pico-sdk* .tinyusb* .ps2x2pico
define libdep
@ -30,8 +30,9 @@ endef
$(call libdep,pico-sdk,raspberrypi/pico-sdk,6a7db34ff63345a7badec79ebea3aaef1712f374)
.tinyusb:
$(call libdep,tinyusb,hathach/tinyusb,d713571cd44f05d2fc72efc09c670787b74106e0)
# TODO: PS2: Add your library here and add it to "all" and "clean-all" targets
deps: .pico-sdk .tinyusb
.ps2x2pico:
$(call libdep,ps2x2pico,No0ne/ps2x2pico,706b5c34cb6a2fcefeb7f1ee0f673c7de9452fc6)
deps: .pico-sdk .tinyusb .ps2x2pico
.PHONY: deps

View File

@ -8,7 +8,6 @@ target_sources(${target_name} PRIVATE
ph_usb_kbd.c
ph_usb_mouse.c
ph_ps2.c
ph_ps2_phy.c
ph_ps2_kbd.c
ph_ps2_mouse.c
ph_cmds.c
@ -17,12 +16,14 @@ target_sources(${target_name} PRIVATE
ph_com_spi.c
ph_com_uart.c
ph_debug.c
${PS2_PATH}/ps2phy.c
)
target_link_options(${target_name} PRIVATE -Xlinker --print-memory-usage)
target_compile_options(${target_name} PRIVATE -Wall -Wextra)
target_include_directories(${target_name} PRIVATE ${CMAKE_CURRENT_LIST_DIR})
target_include_directories(${target_name} PRIVATE ${CMAKE_CURRENT_LIST_DIR} ${PS2_PATH})
pico_generate_pio_header(${target_name} ${CMAKE_CURRENT_LIST_DIR}/ph_ps2_phy.pio)
pico_generate_pio_header(${target_name} ${PS2_PATH}/ps2phy.pio)
target_link_libraries(${target_name} PRIVATE
pico_stdlib

View File

@ -1,10 +1,11 @@
#include "ps2phy.h"
#include "ph_outputs.h"
#include "ph_ps2_phy.h"
extern u8 ph_g_ps2_kbd_leds;
extern bool ph_g_ps2_kbd_online;
ph_ps2_phy ph_ps2_kbd;
ps2phy ph_ps2_kbd;
bool ph_ps2_kbd_scanning;
u32 ph_ps2_kbd_repeat_us;
u16 ph_ps2_kbd_delay_ms;
@ -212,11 +213,11 @@ void ph_ps2_kbd_receive(u8 byte, u8 prev_byte) {
}
void ph_ps2_kbd_task(void) {
ph_ps2_phy_task(&ph_ps2_kbd);
ps2phy_task(&ph_ps2_kbd);
ph_g_ps2_kbd_online = ph_ps2_kbd_scanning && !ph_ps2_kbd.busy;
}
void ph_ps2_kbd_init(u8 gpio) {
ph_ps2_phy_init(&ph_ps2_kbd, pio0, gpio, &ph_ps2_kbd_receive);
ps2phy_init(&ph_ps2_kbd, pio0, gpio, &ph_ps2_kbd_receive);
ph_ps2_kbd_reset();
}

View File

@ -1,9 +1,10 @@
#include "ps2phy.h"
#include "ph_outputs.h"
#include "ph_ps2_phy.h"
extern bool ph_g_ps2_mouse_online;
ph_ps2_phy ph_ps2_mouse;
ps2phy ph_ps2_mouse;
bool ph_ps2_mouse_streaming = false;
u32 ph_ps2_mouse_magic_seq = 0;
u8 ph_ps2_mouse_type = 0;
@ -138,10 +139,10 @@ void ph_ps2_mouse_receive(u8 byte, u8 prev_byte) {
}
void ph_ps2_mouse_task(void) {
ph_ps2_phy_task(&ph_ps2_mouse);
ps2phy_task(&ph_ps2_mouse);
ph_g_ps2_mouse_online = ph_ps2_mouse_streaming && !ph_ps2_mouse.busy;
}
void ph_ps2_mouse_init(u8 gpio) {
ph_ps2_phy_init(&ph_ps2_mouse, pio0, gpio, &ph_ps2_mouse_receive);
ps2phy_init(&ph_ps2_mouse, pio0, gpio, &ph_ps2_mouse_receive);
}

View File

@ -1,100 +0,0 @@
// Source: https://github.com/No0ne/ps2x2pico/blob/main/ps2phy.c
// replace ps2phy with ph_ps2_phy
#include "ph_ps2_phy.h"
#include "ph_ps2_phy.pio.h"
s8 prog = -1;
u32 ph_ps2_phy_frame(u8 byte) {
bool parity = 1;
for (u8 i = 0; i < 8; i++) {
parity = parity ^ (byte >> i & 1);
}
return ((1 << 10) | (parity << 9) | (byte << 1)) ^ 0x7ff;
}
void ph_ps2_phy_init(ph_ps2_phy* this, PIO pio, u8 data_pin, rx_callback rx) {
if (prog == -1) {
prog = pio_add_program(pio, &ph_ps2_phy_program);
}
queue_init(&this->qbytes, sizeof(u8), 9);
queue_init(&this->qpacks, sizeof(u8) * 9, 16);
this->sm = pio_claim_unused_sm(pio, true);
ph_ps2_phy_program_init(pio, this->sm, prog, data_pin);
this->pio = pio;
this->sent = 0;
this->rx = rx;
this->last_rx = 0;
this->last_tx = 0;
this->busy = 0;
}
void ph_ps2_phy_task(ph_ps2_phy* this) {
u8 i = 0;
u8 byte;
u8 pack[9];
if (!queue_is_empty(&this->qbytes)) {
while (i < 9 && queue_try_remove(&this->qbytes, &byte)) {
i++;
pack[i] = byte;
}
pack[0] = i;
queue_try_add(&this->qpacks, &pack);
}
if (pio_interrupt_get(this->pio, this->sm)) {
this->busy = 1;
} else {
this->busy &= 2;
}
if (pio_interrupt_get(this->pio, this->sm + 4)) {
this->sent--;
pio_interrupt_clear(this->pio, this->sm + 4);
}
if (!queue_is_empty(&this->qpacks) && pio_sm_is_tx_fifo_empty(this->pio, this->sm) && !this->busy) {
if (queue_try_peek(&this->qpacks, &pack)) {
if (this->sent == pack[0]) {
this->sent = 0;
queue_try_remove(&this->qpacks, &pack);
} else {
this->sent++;
this->last_tx = pack[this->sent];
this->busy |= 2;
pio_sm_put(this->pio, this->sm, ph_ps2_phy_frame(this->last_tx));
}
}
}
if (!pio_sm_is_rx_fifo_empty(this->pio, this->sm)) {
u32 fifo = pio_sm_get(this->pio, this->sm) >> 23;
bool parity = 1;
for (i = 0; i < 8; i++) {
parity = parity ^ (fifo >> i & 1);
}
if (parity != fifo >> 8) {
pio_sm_put(this->pio, this->sm, ph_ps2_phy_frame(0xfe));
return;
}
if (fifo == 0xfe) {
pio_sm_put(this->pio, this->sm, ph_ps2_phy_frame(this->last_tx));
return;
}
while (queue_try_remove(&this->qbytes, &byte));
while (queue_try_remove(&this->qpacks, &pack));
(*this->rx)(fifo, this->last_rx);
this->last_rx = fifo;
}
}

View File

@ -1,22 +0,0 @@
#pragma once
#include "ph_types.h"
#include "hardware/pio.h"
#include "pico/util/queue.h"
typedef void (*rx_callback)(u8 byte, u8 prev_byte);
typedef struct {
PIO pio;
uint sm;
queue_t qbytes;
queue_t qpacks;
rx_callback rx;
u8 last_rx;
u8 last_tx;
u8 sent;
u8 busy;
} ph_ps2_phy;
void ph_ps2_phy_init(ph_ps2_phy* this, PIO pio, u8 data_pin, rx_callback rx);
void ph_ps2_phy_task(ph_ps2_phy* this);

View File

@ -1,83 +0,0 @@
;
; Copyright (c) 2022 No0ne (https://github.com/No0ne)
; (c) 2023 Dustin Hoffman
;
; SPDX-License-Identifier: MIT
;
; Source: https://github.com/No0ne/ps2x2pico/blob/main/ps2phy.pio
.program ph_ps2_phy
.side_set 1 opt pindirs
restart:
set pindirs, 0 // set clock to input mode
irq clear 0 rel side 0 // clear busy flag, set data to input mode
receivecheck:
jmp pin, sendcheck // if clock is high, see if we have data to send
irq nowait 0 rel // clock is being pulled low, set busy flag
wait 1 pin, 1 // wait for clock to be pulled high
// we are not sending, look for a start bit (clock high, data low)
in pins, 1 // read in from data
mov x, isr // move what we read to x
mov isr, null // clear ISR
jmp !x, receive // if x is low, start the receive process
jmp restart // not receiving
receive:
set pindirs, 1 [6] // clock low
set x, 8 // set loop counter
receiveloop:
set pindirs, 0 [6] // clock high
in pins, 1 [4] // read a bit into ISR
set pindirs, 1 [6] // clock low
jmp x--, receiveloop [4] // iterate
set pindirs, 0 [6] // clock high
nop side 1 [6] // data low
set pindirs, 1 [7] // clock low
jmp restart [7]
sendcheck:
jmp !osre, send // see if we have data to send
jmp receivecheck // no data to send, restart
send:
irq nowait 0 rel // set busy flag
set x, 10 // number of bits to write out
sendloop:
set pindirs, 0 [6] // clock set to input (high)
jmp pin, sendcontinue // if clock is high, host is still receiving data
out null, 32 // clear OSR
irq wait 4 rel // clock was low, host wants to send data, notify of failure to send data
jmp restart // and wait for restart
sendcontinue:
out pindirs, 1 [6] // write out data
set pindirs, 1 [6] // set clock low
jmp x--, sendloop [6]
% c-sdk {
void ph_ps2_phy_program_init(PIO pio, uint sm, uint offset, uint dat) {
pio_sm_config c = ph_ps2_phy_program_get_default_config(offset);
u8 clk = dat + 1;
pio_gpio_init(pio, clk);
pio_gpio_init(pio, dat);
// Use a frequency high enough to effectivly sample clock and data.
sm_config_set_clkdiv(&c, 427); // 2560 is 20 µs, 640 is 5 µs, 427 is 3.3333 µs
sm_config_set_jmp_pin(&c, clk);
sm_config_set_set_pins(&c, clk, 1);
sm_config_set_sideset_pins(&c, dat);
sm_config_set_out_pins(&c, dat, 1);
sm_config_set_out_shift(&c, true, true, 11);
sm_config_set_in_pins(&c, dat);
sm_config_set_in_shift(&c, true, true, 9);
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
}
%}