mirror of
https://github.com/4yn/slidershim.git
synced 2024-11-27 23:10:49 +01:00
Tasoller hid
This commit is contained in:
parent
a44220fed1
commit
06707302d1
116
README.md
116
README.md
@ -1,109 +1,9 @@
|
||||
*Psst — looking for a more complete solution? Check out [SvelteKit](https://kit.svelte.dev), the official framework for building web applications of all sizes, with a beautiful development experience and flexible filesystem-based routing.*
|
||||
# Todo
|
||||
|
||||
*Looking for a shareable component template instead? You can [use SvelteKit for that as well](https://kit.svelte.dev/docs#packaging) or the older [sveltejs/component-template](https://github.com/sveltejs/component-template)*
|
||||
|
||||
---
|
||||
|
||||
# svelte app
|
||||
|
||||
This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template.
|
||||
|
||||
To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit):
|
||||
|
||||
```bash
|
||||
npx degit sveltejs/template svelte-app
|
||||
cd svelte-app
|
||||
```
|
||||
|
||||
*Note that you will need to have [Node.js](https://nodejs.org) installed.*
|
||||
|
||||
|
||||
## Get started
|
||||
|
||||
Install the dependencies...
|
||||
|
||||
```bash
|
||||
cd svelte-app
|
||||
npm install
|
||||
```
|
||||
|
||||
...then start [Rollup](https://rollupjs.org):
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Navigate to [localhost:8080](http://localhost:8080). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
|
||||
|
||||
By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`.
|
||||
|
||||
If you're using [Visual Studio Code](https://code.visualstudio.com/) we recommend installing the official extension [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense.
|
||||
|
||||
## Building and running in production mode
|
||||
|
||||
To create an optimised version of the app:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com).
|
||||
|
||||
|
||||
## Single-page app mode
|
||||
|
||||
By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere.
|
||||
|
||||
If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json:
|
||||
|
||||
```js
|
||||
"start": "sirv public --single"
|
||||
```
|
||||
|
||||
## Using TypeScript
|
||||
|
||||
This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with:
|
||||
|
||||
```bash
|
||||
node scripts/setupTypeScript.js
|
||||
```
|
||||
|
||||
Or remove the script via:
|
||||
|
||||
```bash
|
||||
rm scripts/setupTypeScript.js
|
||||
```
|
||||
|
||||
If you want to use `baseUrl` or `path` aliases within your `tsconfig`, you need to set up `@rollup/plugin-alias` to tell Rollup to resolve the aliases. For more info, see [this StackOverflow question](https://stackoverflow.com/questions/63427935/setup-tsconfig-path-in-svelte).
|
||||
|
||||
## Deploying to the web
|
||||
|
||||
### With [Vercel](https://vercel.com)
|
||||
|
||||
Install `vercel` if you haven't already:
|
||||
|
||||
```bash
|
||||
npm install -g vercel
|
||||
```
|
||||
|
||||
Then, from within your project folder:
|
||||
|
||||
```bash
|
||||
cd public
|
||||
vercel deploy --name my-project
|
||||
```
|
||||
|
||||
### With [surge](https://surge.sh/)
|
||||
|
||||
Install `surge` if you haven't already:
|
||||
|
||||
```bash
|
||||
npm install -g surge
|
||||
```
|
||||
|
||||
Then, from within your project folder:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
surge public my-project.surge.sh
|
||||
```
|
||||
- input polling rate counter
|
||||
- led polling rate settings
|
||||
- settings serializer
|
||||
- brokenithm server
|
||||
- ouptut websocket
|
||||
- led websocket
|
||||
- comments
|
||||
|
@ -5,12 +5,23 @@ use std::io;
|
||||
use slidershim::slider_io::{Config, Manager};
|
||||
|
||||
fn main() {
|
||||
// let config = Config::from_str(
|
||||
// r#"{
|
||||
// "deviceMode": "yuancon",
|
||||
// "outputMode": "kb-32-tasoller",
|
||||
// "ledMode": "reactive-8",
|
||||
// "keyboardSensitivity": 50
|
||||
// }"#,
|
||||
// )
|
||||
// .unwrap();
|
||||
|
||||
let config = Config::from_str(
|
||||
r#"{
|
||||
"deviceMode": "yuancon",
|
||||
"outputMode": "kb-32-tasoller",
|
||||
"keyboardSensitivity": 50,
|
||||
"ledMode": "reactive-8",
|
||||
"keyboardSensitivity": 50
|
||||
"ledSensitivity": 50
|
||||
}"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -1,4 +1,8 @@
|
||||
use std::{error, ops::DerefMut, time::Duration};
|
||||
use std::{
|
||||
error,
|
||||
ops::{Deref, DerefMut},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use rusb::{self, DeviceHandle, GlobalContext};
|
||||
|
||||
@ -9,14 +13,14 @@ use crate::slider_io::{
|
||||
};
|
||||
|
||||
pub struct Buffer {
|
||||
pub data: [u8; 128],
|
||||
pub data: [u8; 256],
|
||||
pub len: usize,
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
pub fn new() -> Self {
|
||||
Buffer {
|
||||
data: [0; 128],
|
||||
data: [0; 256],
|
||||
len: 0,
|
||||
}
|
||||
}
|
||||
@ -27,7 +31,12 @@ impl Buffer {
|
||||
}
|
||||
|
||||
type HidReadCallback = fn(&Buffer, &mut ControllerState) -> ();
|
||||
type HidLedCallback = fn(&mut Buffer, &mut LedState) -> ();
|
||||
type HidLedCallback = fn(&mut Buffer, &LedState) -> ();
|
||||
|
||||
enum WriteType {
|
||||
Bulk,
|
||||
Interrupt,
|
||||
}
|
||||
|
||||
pub struct HidDeviceJob {
|
||||
state: FullState,
|
||||
@ -39,6 +48,7 @@ pub struct HidDeviceJob {
|
||||
read_callback: HidReadCallback,
|
||||
read_buf: Buffer,
|
||||
|
||||
led_write_type: WriteType,
|
||||
led_callback: HidLedCallback,
|
||||
led_buf: Buffer,
|
||||
|
||||
@ -53,6 +63,7 @@ impl HidDeviceJob {
|
||||
read_endpoint: u8,
|
||||
led_endpoint: u8,
|
||||
read_callback: HidReadCallback,
|
||||
led_type: WriteType,
|
||||
led_callback: HidLedCallback,
|
||||
) -> Self {
|
||||
Self {
|
||||
@ -63,6 +74,7 @@ impl HidDeviceJob {
|
||||
led_endpoint,
|
||||
read_callback,
|
||||
read_buf: Buffer::new(),
|
||||
led_write_type: led_type,
|
||||
led_callback,
|
||||
led_buf: Buffer::new(),
|
||||
handle: None,
|
||||
@ -71,6 +83,65 @@ impl HidDeviceJob {
|
||||
|
||||
pub fn from_config(state: &FullState, mode: &DeviceMode) -> Self {
|
||||
match mode {
|
||||
DeviceMode::TasollerOne => Self::new(
|
||||
state.clone(),
|
||||
0x1ccf,
|
||||
0x2333,
|
||||
0x84,
|
||||
0x03,
|
||||
|buf, controller_state| {
|
||||
if buf.len != 11 {
|
||||
return;
|
||||
}
|
||||
|
||||
let bits: Vec<u8> = buf
|
||||
.data
|
||||
.iter()
|
||||
.flat_map(|x| (0..8).map(move |i| ((x) >> i) & 1))
|
||||
.collect();
|
||||
for i in 0..32 {
|
||||
controller_state.ground_state[i] = bits[34 + i] * 255;
|
||||
}
|
||||
controller_state.air_state.copy_from_slice(&bits[28..34]);
|
||||
},
|
||||
WriteType::Bulk,
|
||||
|buf, led_state| {
|
||||
buf.len = 240;
|
||||
buf.data[0] = 'B' as u8;
|
||||
buf.data[1] = 'L' as u8;
|
||||
buf.data[2] = '\x00' as u8;
|
||||
buf.data[3..96].copy_from_slice(&led_state.led_state[..3 * 31]);
|
||||
buf.data[96..240].fill(0);
|
||||
},
|
||||
),
|
||||
DeviceMode::TasollerTwo => Self::new(
|
||||
state.clone(),
|
||||
0x1ccf,
|
||||
0x2333,
|
||||
0x84,
|
||||
0x03,
|
||||
|buf, controller_state| {
|
||||
if buf.len != 36 {
|
||||
return;
|
||||
}
|
||||
|
||||
controller_state
|
||||
.ground_state
|
||||
.copy_from_slice(&buf.data[4..36]);
|
||||
for i in 0..6 {
|
||||
controller_state.air_state[i] = (buf.data[3] >> (i + 2)) & 1;
|
||||
}
|
||||
},
|
||||
WriteType::Bulk,
|
||||
|buf, led_state| {
|
||||
buf.len = 240;
|
||||
buf.data[0] = 'B' as u8;
|
||||
buf.data[1] = 'L' as u8;
|
||||
buf.data[2] = '\x00' as u8;
|
||||
buf.data[3..96].copy_from_slice(&led_state.led_state[..3 * 31]);
|
||||
buf.data[96..240].fill(0);
|
||||
},
|
||||
),
|
||||
DeviceMode::Yuancon => Self::new(
|
||||
state.clone(),
|
||||
0x1973,
|
||||
@ -84,7 +155,7 @@ impl HidDeviceJob {
|
||||
|
||||
controller_state
|
||||
.ground_state
|
||||
.clone_from_slice(&buf.data[2..34]);
|
||||
.copy_from_slice(&buf.data[2..34]);
|
||||
for i in 0..6 {
|
||||
controller_state.air_state[i ^ 1] = if buf.data[0] & (1 << i) == 0 { 1 } else { 0 };
|
||||
}
|
||||
@ -92,21 +163,18 @@ impl HidDeviceJob {
|
||||
controller_state.extra_state[i] = if buf.data[1] & (1 << i) == 0 { 1 } else { 0 };
|
||||
}
|
||||
},
|
||||
WriteType::Interrupt,
|
||||
|buf, led_state| {
|
||||
if !led_state.dirty {
|
||||
return;
|
||||
}
|
||||
buf.len = 31 * 2;
|
||||
buf
|
||||
for (buf_chunk, state_chunk) in buf
|
||||
.data
|
||||
.chunks_mut(2)
|
||||
.take(31)
|
||||
.zip(led_state.led_state.chunks(3).rev())
|
||||
.for_each(|(buf_chunk, state_chunk)| {
|
||||
buf_chunk[0] = (state_chunk[0] << 3 & 0xe0) | (state_chunk[2] >> 3);
|
||||
buf_chunk[1] = (state_chunk[1] & 0xf8) | (state_chunk[0] >> 5);
|
||||
});
|
||||
led_state.dirty = false;
|
||||
{
|
||||
buf_chunk[0] = (state_chunk[0] << 3 & 0xe0) | (state_chunk[2] >> 3);
|
||||
buf_chunk[1] = (state_chunk[1] & 0xf8) | (state_chunk[0] >> 5);
|
||||
}
|
||||
},
|
||||
),
|
||||
_ => panic!("Not implemented"),
|
||||
@ -150,13 +218,20 @@ impl Job for HidDeviceJob {
|
||||
// Led loop
|
||||
{
|
||||
let mut led_state_handle = self.state.led_state.lock().unwrap();
|
||||
(self.led_callback)(&mut self.led_buf, led_state_handle.deref_mut());
|
||||
if self.led_buf.len != 0 {
|
||||
let res = handle
|
||||
.write_interrupt(self.led_endpoint, &self.led_buf.data, TIMEOUT)
|
||||
if led_state_handle.dirty {
|
||||
(self.led_callback)(&mut self.led_buf, led_state_handle.deref());
|
||||
led_state_handle.dirty = false;
|
||||
if self.led_buf.len != 0 {
|
||||
let res = (match self.led_write_type {
|
||||
WriteType::Bulk => handle.write_bulk(self.led_endpoint, &self.led_buf.data, TIMEOUT),
|
||||
WriteType::Interrupt => {
|
||||
handle.write_interrupt(self.led_endpoint, &self.led_buf.data, TIMEOUT)
|
||||
}
|
||||
})
|
||||
.unwrap_or(0);
|
||||
if res == self.led_buf.len + 1 {
|
||||
self.led_buf.len = 0;
|
||||
if res == self.led_buf.len + 1 {
|
||||
self.led_buf.len = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user