Skip to content

Commit

Permalink
PIO version finally working
Browse files Browse the repository at this point in the history
  • Loading branch information
No0ne committed Sep 8, 2023
1 parent 358390e commit 706b5c3
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 168 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ add_executable(ps2x2pico ps2x2pico.c ps2phy.c ps2kb.c ps2ms.c)

pico_generate_pio_header(ps2x2pico ${CMAKE_CURRENT_LIST_DIR}/ps2phy.pio)

add_compile_definitions(DEBUG=1)
add_compile_definitions(DEBUG=0)
# Keyboard data pin. Clock pin is 1 more than the data pin.
add_compile_definitions(KBDAT=11)
# Mouse data pin. Clock pin is 1 more than the data pin.
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Keyboard only variant: https://github.com/No0ne/ps2pico

PC-XT variant: https://github.com/No0ne/ps2pico/tree/xt-version

PiKVM integration: https://docs.pikvm.org/pico_hid/

# Usage
* Download `ps2x2pico.uf2` from https://github.com/No0ne/ps2x2pico/releases
* Copy `ps2x2pico.uf2` to your Pi Pico by pressing BOOTSEL before pluggging in.
Expand Down
2 changes: 1 addition & 1 deletion ps2kb.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,4 +292,4 @@ void kb_task() {

void kb_init() {
ps2phy_init(&kb_phy, pio0, KBDAT, &kb_receive);
}
}
199 changes: 80 additions & 119 deletions ps2ms.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,9 @@
#include "ps2phy.h"
ps2phy ms_phy;

#define MS_TYPE_STANDARD 0x00
#define MS_TYPE_WHEEL_3 0x03
#define MS_TYPE_WHEEL_5 0x04

#define MS_MODE_IDLE 0
#define MS_MODE_STREAMING 1

#define MS_INPUT_CMD 0
#define MS_INPUT_SET_RATE 1

u8 ms_type = MS_TYPE_STANDARD;
u8 ms_mode = MS_MODE_IDLE;
u8 ms_input_mode = MS_INPUT_CMD;
u8 ms_rate = 100;
u32 ms_magic_seq = 0x00;
bool ms_streaming = false;
u32 ms_magic_seq = 0;
u8 ms_type = 0;

void ms_send(u8 byte) {
if(DEBUG) printf("%02x ", byte);
Expand All @@ -60,122 +48,95 @@ void ms_usb_umount(u8 dev_addr, u8 instance) {
void ms_usb_receive(u8 const* report) {
if(DEBUG) printf("%02x %02x %02x %02x\n", report[0], report[1], report[2], report[3]);

if(ms_mode == MS_MODE_STREAMING) {
u8 s = (report[0] & 7) + 8;
u8 x = report[1] & 0x7f;
u8 y = report[2] & 0x7f;
u8 z = report[3] & 7;

if(report[1] >> 7) {
s += 0x10;
x += 0x80;
}

if(report[2] >> 7) {
y = 0x80 - y;
} else if(y) {
s += 0x20;
y = 0x100 - y;
}
if (ms_streaming) {
u8 byte1 = 0x8 | (report[0] & 0x7);
s8 byte2 = report[1];
s8 byte3 = 0x100 - report[2];
s8 byte4 = 0x100 - report[3];

ms_send(s);
ms_send(x);
ms_send(y);
if (byte2 < 0) byte1 |= 0x10;
if (byte3 < 0) byte1 |= 0x20;

if (ms_type == MS_TYPE_WHEEL_3 || ms_type == MS_TYPE_WHEEL_5) {
if(report[3] >> 7) {
z = 0x8 - z;
} else if(z) {
z = 0x10 - z;
}
ms_send(byte1);
ms_send(byte2);
ms_send(byte3);

if (ms_type == MS_TYPE_WHEEL_5) {
if (report[0] & 0x8) {
z += 0x10;
}

if (report[0] & 0x10) {
z += 0x20;
}
if (ms_type == 3 || ms_type == 4) {
if (byte4 < -8) byte4 = -8;
if (byte4 > 7) byte4 = 7;
if (byte4 < 0) byte4 |= 0xf8;
if (ms_type == 4) {
byte4 &= 0xf;
byte4 |= (report[0] << 1) & 0x30;
}

ms_send(z);
ms_send(byte4);
}
}
}

void ms_receive(u8 byte, u8 prev_byte) {
if(DEBUG) printf("!%02x ", byte);

if(ms_input_mode == MS_INPUT_SET_RATE) {
ms_rate = byte; // TODO... need to actually honor the sample rate!
ms_input_mode = MS_INPUT_CMD;
ms_send(0xfa);

ms_magic_seq = (ms_magic_seq << 8) | byte;
if(ms_type == MS_TYPE_STANDARD && ms_magic_seq == 0xc86450) {
ms_type = MS_TYPE_WHEEL_3;
} else if (ms_type == MS_TYPE_WHEEL_3 && ms_magic_seq == 0xc8c850) {
ms_type = MS_TYPE_WHEEL_5;
}
if(DEBUG) printf(" MS magic seq: %06x type: %d\n", ms_magic_seq, ms_type);
return;
}

if(byte != 0xf3) {
ms_magic_seq = 0x00;
}

switch(byte) {
case 0xff: // Reset
ms_type = MS_TYPE_STANDARD;
ms_mode = MS_MODE_IDLE;
ms_rate = 100;

ms_send(0xfa);
ms_send(0xaa);
ms_send(ms_type);
return;

case 0xf6: // Set Defaults
ms_type = MS_TYPE_STANDARD;
ms_rate = 100;
case 0xf5: // Disable Data Reporting
case 0xea: // Set Stream Mode
ms_mode = MS_MODE_IDLE;
ms_send(0xfa);
return;

case 0xf4: // Enable Data Reporting
ms_mode = MS_MODE_STREAMING;
ms_send(0xfa);
return;

switch (prev_byte) {
case 0xf3: // Set Sample Rate
ms_input_mode = MS_INPUT_SET_RATE;
ms_send(0xfa);
return;

case 0xf2: // Get Device ID
ms_send(0xfa);
ms_send(ms_type);
return;

case 0xe9: // Status Request
ms_send(0xfa);
ms_send(0x00); // Bit6: Mode, Bit 5: Enable, Bit 4: Scaling, Bits[2,1,0] = Buttons[L,M,R]
ms_send(0x02); // Resolution
ms_send(ms_rate); // Sample Rate
return;

// TODO: Implement (more of) these?
// case 0xf0: // Set Remote Mode
// case 0xee: // Set Wrap Mode
// case 0xec: // Reset Wrap Mode
// case 0xeb: // Read Data
// case 0xe8: // Set Resolution
// case 0xe7: // Set Scaling 2:1
// case 0xe6: // Set Scaling 1:1
ms_magic_seq = ((ms_magic_seq << 8) | byte) & 0xffffff;

if (ms_type == 0 && ms_magic_seq == 0xc86450) {
ms_type = 3;
} else if (ms_type == 3 && ms_magic_seq == 0xc8c850) {
ms_type = 4;
}
break;

default:
switch (byte) {
case 0xff: // Reset
ms_streaming = false;
ms_type = 0;

ms_send(0xfa);
ms_send(0xaa);
ms_send(ms_type);
return;

case 0xf6: // Set Defaults
ms_streaming = false;
ms_type = 0;
break;

case 0xf5: // Disable Data Reporting
case 0xea: // Set Stream Mode
ms_streaming = false;
break;

case 0xf4: // Enable Data Reporting
ms_streaming = true;
break;

case 0xf2: // Get Device ID
ms_send(0xfa);
ms_send(ms_type);
return;

case 0xe9: // Status Request
ms_send(0xfa);
ms_send(0x00); // Bit6: Mode, Bit 5: Enable, Bit 4: Scaling, Bits[2,1,0] = Buttons[L,M,R]
ms_send(0x02); // Resolution
ms_send(100); // Sample Rate
return;

// TODO: Implement (more of) these?
// case 0xf0: // Set Remote Mode
// case 0xee: // Set Wrap Mode
// case 0xec: // Reset Wrap Mode
// case 0xeb: // Read Data
// case 0xe8: // Set Resolution
// case 0xe7: // Set Scaling 2:1
// case 0xe6: // Set Scaling 1:1
}
break;
}

ms_send(0xfa);
Expand Down
30 changes: 17 additions & 13 deletions ps2phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#include "ps2phy.h"
#include "ps2phy.pio.h"

uint prog = 0;
s8 prog = -1;

u32 ps2phy_frame(u8 byte) {
bool parity = 1;
Expand All @@ -38,7 +38,7 @@ u32 ps2phy_frame(u8 byte) {
}

void ps2phy_init(ps2phy* this, PIO pio, u8 data_pin, rx_callback rx) {
if(!prog) {
if (prog == -1) {
prog = pio_add_program(pio, &ps2phy_program);
}

Expand All @@ -53,7 +53,7 @@ void ps2phy_init(ps2phy* this, PIO pio, u8 data_pin, rx_callback rx) {
this->rx = rx;
this->last_rx = 0;
this->last_tx = 0;
this->idle = true;
this->busy = 0;
}

void ps2phy_task(ps2phy* this) {
Expand All @@ -71,27 +71,31 @@ void ps2phy_task(ps2phy* this) {
queue_try_add(&this->qpacks, &pack);
}

this->idle = !pio_interrupt_get(this->pio, this->sm);
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->idle) {
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, ps2phy_frame(this->last_tx));
}
}
}

if (pio_interrupt_get(this->pio, this->sm + 4)) {
this->sent = 0;
pio_sm_drain_tx_fifo(this->pio, this->sm);
pio_interrupt_clear(this->pio, this->sm + 4);
}

if (!pio_sm_is_rx_fifo_empty(this->pio, this->sm)) {
u32 fifo = pio_sm_get(this->pio, this->sm) >> 23;

Expand All @@ -110,8 +114,8 @@ void ps2phy_task(ps2phy* this) {
return;
}

while(queue_try_remove(&this->qbytes, &byte));
while(queue_try_remove(&this->qpacks, &pack));
while (queue_try_remove(&this->qbytes, &byte));
while (queue_try_remove(&this->qpacks, &pack));

(*this->rx)(fifo, this->last_rx);
this->last_rx = fifo;
Expand Down
4 changes: 2 additions & 2 deletions ps2phy.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ typedef struct {
uint sm;
queue_t qbytes;
queue_t qpacks;
u8 sent;
rx_callback rx;
u8 last_rx;
u8 last_tx;
bool idle;
u8 sent;
u8 busy;
} ps2phy;

void ps2phy_init(ps2phy* this, PIO pio, u8 data_pin, rx_callback rx);
Expand Down
Loading

0 comments on commit 706b5c3

Please sign in to comment.