Rework for custom pcb
This commit is contained in:
parent
5b985bd5ff
commit
2f8a9d7e5f
156
src/main.rs
156
src/main.rs
@ -1,46 +1,48 @@
|
||||
use image::imageops::FilterType;
|
||||
use image::{EncodableLayout, ImageError};
|
||||
use nusb::transfer::{Bulk, Out, TransferError};
|
||||
use nusb::MaybeFuture;
|
||||
use nusb::{list_devices, ErrorKind};
|
||||
use nusb::transfer::{Bulk, In, Out, TransferError};
|
||||
use nusb::{ErrorKind, list_devices};
|
||||
use reqwest::header::ACCEPT;
|
||||
use serde::Deserialize;
|
||||
use std::env;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::io::Write;
|
||||
use std::io::{Read, Write};
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Error {
|
||||
message: &'static str
|
||||
message: String,
|
||||
}
|
||||
|
||||
impl From<nusb::Error> for Error {
|
||||
fn from(value: nusb::Error) -> Self {
|
||||
Error{
|
||||
Error {
|
||||
message: match value.kind() {
|
||||
ErrorKind::Disconnected => "Device disconnected",
|
||||
ErrorKind::Busy => "Device busy",
|
||||
ErrorKind::PermissionDenied => "No permission to access device",
|
||||
ErrorKind::NotFound => "Device not found",
|
||||
ErrorKind::Unsupported => "Device not supported",
|
||||
_ => "Unknown error"
|
||||
}
|
||||
ErrorKind::Disconnected => "Device disconnected".to_owned(),
|
||||
ErrorKind::Busy => "Device busy".to_owned(),
|
||||
ErrorKind::PermissionDenied => "No permission to access device".to_owned(),
|
||||
ErrorKind::NotFound => "Device not found".to_owned(),
|
||||
ErrorKind::Unsupported => "Device not supported".to_owned(),
|
||||
ErrorKind::Other => value.to_string(),
|
||||
_ => "Unknown error".to_owned(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TransferError> for Error {
|
||||
fn from(_: TransferError) -> Self {
|
||||
Error{
|
||||
message: "Error during transfer"
|
||||
fn from(value: TransferError) -> Self {
|
||||
Error {
|
||||
message: value.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for Error {
|
||||
fn from(_: std::io::Error) -> Self {
|
||||
fn from(value: std::io::Error) -> Self {
|
||||
Error {
|
||||
message: "Error during transfer"
|
||||
message: value.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -48,7 +50,7 @@ impl From<std::io::Error> for Error {
|
||||
impl From<ImageError> for Error {
|
||||
fn from(_: ImageError) -> Self {
|
||||
Error {
|
||||
message: "Error reading image"
|
||||
message: "Error reading image".to_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -56,7 +58,7 @@ impl From<ImageError> for Error {
|
||||
impl From<reqwest::Error> for Error {
|
||||
fn from(_: reqwest::Error) -> Self {
|
||||
Error {
|
||||
message: "Error retrieving card info"
|
||||
message: "Error retrieving card info".to_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -69,7 +71,7 @@ impl Display for Error {
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ImageUris {
|
||||
pub png: String
|
||||
pub png: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@ -77,17 +79,20 @@ struct ScryfallCardInfo {
|
||||
pub cmc: f32,
|
||||
pub colors: Vec<String>,
|
||||
pub name: String,
|
||||
pub image_uris: ImageUris
|
||||
pub image_uris: ImageUris,
|
||||
}
|
||||
|
||||
struct RelevantCardInfo {
|
||||
pub cmc: u8,
|
||||
pub colors: u8,
|
||||
pub name: String,
|
||||
pub image: Vec<u8>
|
||||
pub image: Vec<u8>,
|
||||
}
|
||||
|
||||
fn get_relevant_card_info(set_code: &str, collector_number: &str) -> Result<RelevantCardInfo, Error> {
|
||||
fn get_relevant_card_info(
|
||||
set_code: &str,
|
||||
collector_number: &str,
|
||||
) -> Result<RelevantCardInfo, Error> {
|
||||
let client = reqwest::blocking::ClientBuilder::new()
|
||||
.user_agent("Digital MtG Token/0.1.0")
|
||||
.build()?;
|
||||
@ -95,23 +100,28 @@ fn get_relevant_card_info(set_code: &str, collector_number: &str) -> Result<Rele
|
||||
let card_uri = format!("https://api.scryfall.com/cards/{set_code}/{collector_number}");
|
||||
let response = client.get(card_uri).header(ACCEPT, "*/*").send()?;
|
||||
let card_info: ScryfallCardInfo = response.json()?;
|
||||
let card_image = client.get(&card_info.image_uris.png).header(ACCEPT, "*/*").send()?.bytes()?.to_vec();
|
||||
let card_image = client
|
||||
.get(&card_info.image_uris.png)
|
||||
.header(ACCEPT, "*/*")
|
||||
.send()?
|
||||
.bytes()?
|
||||
.to_vec();
|
||||
|
||||
let mut colors = 0;
|
||||
for color in &card_info.colors {
|
||||
match color.as_str() {
|
||||
"W" => {
|
||||
colors |= 0b10000;
|
||||
},
|
||||
}
|
||||
"U" => {
|
||||
colors |= 0b1000;
|
||||
},
|
||||
}
|
||||
"B" => {
|
||||
colors |= 0b100;
|
||||
},
|
||||
}
|
||||
"R" => {
|
||||
colors |= 0b10;
|
||||
},
|
||||
}
|
||||
"G" => {
|
||||
colors |= 0b1;
|
||||
}
|
||||
@ -123,14 +133,17 @@ fn get_relevant_card_info(set_code: &str, collector_number: &str) -> Result<Rele
|
||||
cmc: card_info.cmc.trunc() as u8,
|
||||
colors,
|
||||
name: card_info.name.to_ascii_lowercase(),
|
||||
image: card_image
|
||||
image: card_image,
|
||||
})
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Error> {
|
||||
let device = list_devices().wait()?
|
||||
let device = list_devices()
|
||||
.wait()?
|
||||
.find(|dev| dev.vendor_id() == 0xCAFE && dev.product_id() == 0xCA6D)
|
||||
.ok_or(Error { message: "Device not found" })?;
|
||||
.ok_or(Error {
|
||||
message: "Device not found".to_owned(),
|
||||
})?;
|
||||
|
||||
let device = device.open().wait()?;
|
||||
let interface = device.claim_interface(1).wait()?;
|
||||
@ -138,13 +151,71 @@ fn main() -> Result<(), Error> {
|
||||
let mut writer = interface.endpoint::<Bulk, Out>(0x01)?.writer(4096);
|
||||
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if args.len() == 1 {
|
||||
writer.write(&[0x42])?;
|
||||
if args.len() > 1 {
|
||||
match args[1].as_str() {
|
||||
"erase" => {
|
||||
writer.write_all(&[0x42])?;
|
||||
writer.flush()?;
|
||||
}
|
||||
else {
|
||||
"test" => {
|
||||
writer.write_all(&[0x69])?;
|
||||
writer.flush()?;
|
||||
|
||||
let mut reader = interface
|
||||
.endpoint::<Bulk, In>(0x81)?
|
||||
.reader(128)
|
||||
.with_read_timeout(Duration::from_millis(2500));
|
||||
|
||||
let mut temp = [0u8; 256];
|
||||
let mut buf: Vec<u8> = vec![];
|
||||
loop {
|
||||
match reader.read(&mut temp) {
|
||||
Ok(n) => {
|
||||
if n > 0 {
|
||||
buf.extend_from_slice(&temp[..n]);
|
||||
println!("extended: {}", n);
|
||||
}
|
||||
}
|
||||
Err(e) if e.kind() == std::io::ErrorKind::TimedOut => break,
|
||||
r => {
|
||||
r?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("buflen: {}", buf.len());
|
||||
let mut card_index = 0;
|
||||
for (i, val) in buf.iter().enumerate() {
|
||||
print!("{:02x}", val);
|
||||
if i > 0 && i % 256 == 0 {
|
||||
println!();
|
||||
let b0 = (buf[256 * card_index] as u16)
|
||||
+ ((buf[256 * card_index + 1] as u16) << 8);
|
||||
let is_used = b0 & 0x01 > 0;
|
||||
let name_length = (b0 >> 1) & 0x1F;
|
||||
let cmc = (b0 >> 6) & 0x1F;
|
||||
let colors = (b0 >> 11) & 0x1F;
|
||||
|
||||
let name =
|
||||
&buf[256 * card_index + 8..256 * card_index + 8 + name_length as usize];
|
||||
|
||||
for ch in name {
|
||||
print!("{}", *ch as char);
|
||||
}
|
||||
println!(" ({})", name_length);
|
||||
println!("Used: {}", is_used);
|
||||
println!("CMC: {}", cmc);
|
||||
println!("Colors: {}", colors);
|
||||
println!();
|
||||
|
||||
card_index += 1;
|
||||
}
|
||||
}
|
||||
println!();
|
||||
}
|
||||
_ => {
|
||||
let slash_position = args[1].find("/").ok_or(Error {
|
||||
message: "Error retrieving card info"
|
||||
message: "Error retrieving card info".to_owned(),
|
||||
})?;
|
||||
|
||||
let set_code = &args[1][0..slash_position];
|
||||
@ -153,19 +224,19 @@ fn main() -> Result<(), Error> {
|
||||
let relevant_info = get_relevant_card_info(set_code, collectors_number)?;
|
||||
|
||||
// converted mana cost
|
||||
writer.write(&[relevant_info.cmc])?;
|
||||
writer.write_all(&[relevant_info.cmc])?;
|
||||
|
||||
// colors
|
||||
writer.write(&[relevant_info.colors])?;
|
||||
writer.write_all(&[relevant_info.colors])?;
|
||||
|
||||
let name = relevant_info.name.as_str();
|
||||
let name_len = if name.len() >= 32 { 31 } else { name.len() };
|
||||
|
||||
// length of card name
|
||||
writer.write(&[name_len as u8])?;
|
||||
writer.write_all(&[name_len as u8])?;
|
||||
|
||||
// name of card
|
||||
writer.write(name[0..name_len].as_bytes())?;
|
||||
writer.write_all(&name.as_bytes()[0..name_len])?;
|
||||
|
||||
let img = image::load_from_memory(relevant_info.image.as_bytes())?;
|
||||
let img = img.crop_imm(28, 28, img.width() - 56, img.height() - 56);
|
||||
@ -176,6 +247,11 @@ fn main() -> Result<(), Error> {
|
||||
writer.write_all(img.as_flat_samples().samples)?;
|
||||
writer.flush()?;
|
||||
}
|
||||
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error {
|
||||
message: "Incorrect usage".to_owned(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user