Add agents

This commit is contained in:
Adrian Woźniak 2024-01-03 17:19:45 +01:00
parent d070ff2f91
commit 4561bf5606
11 changed files with 2401 additions and 31 deletions

8
.cargo/config.toml Normal file
View File

@ -0,0 +1,8 @@
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "probe-rs run --chip RP2040"
[build]
target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+
[env]
DEFMT_LOG = "debug"

754
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -55,5 +55,9 @@ pio-proc = "0.2"
pio = "0.2.1"
rand = { version = "0.8.5", default-features = false }
[build-dependencies]
reqwest = { version = "0.11.23", features = ["blocking"] }
[profile.release]
debug = 2

242
build.rs Normal file
View File

@ -0,0 +1,242 @@
use std::collections::{HashMap, HashSet};
use std::env;
use std::fmt::{Display, Formatter};
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
fn main() {
// Put `memory.x` in our output directory and ensure it's
// on the linker search path.
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
File::create(out.join("memory.x"))
.unwrap()
.write_all(include_bytes!("memory.x"))
.unwrap();
println!("cargo:rustc-link-search={}", out.display());
// By default, Cargo will re-run a build script whenever
// any file in the project changes. By specifying `memory.x`
// here, we ensure the build script is only re-run when
// `memory.x` is changed.
println!("cargo:rerun-if-changed=memory.x");
println!("cargo:rustc-link-arg-bins=--nmagic");
println!("cargo:rustc-link-arg-bins=-Tlink.x");
println!("cargo:rustc-link-arg-bins=-Tlink-rp.x");
println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
let client = reqwest::blocking::Client::new();
let res = if Path::new("./target/keycodes.h").exists() {
std::fs::read_to_string("./target/keycodes.h").unwrap()
} else {
let res = client
.get("https://raw.githubusercontent.com/qmk/qmk_firmware/master/quantum/keycodes.h")
.send()
.unwrap()
.text()
.unwrap();
std::fs::write("./target/keycodes.h", res.as_bytes()).unwrap();
res
};
let mut log_file = std::fs::OpenOptions::new()
.create(true)
.append(false)
.write(true)
.open("./target/tokens.log")
.unwrap();
let mut global_register = HashMap::with_capacity(9086);
let mut enums = Vec::with_capacity(64);
let iter = res.lines();
let mut is_block_comment = false;
for line in iter {
parse_line(
line,
&mut enums,
&mut is_block_comment,
&mut global_register,
&mut log_file,
);
}
let mut mod_file = std::fs::OpenOptions::new()
.create(true)
.append(false)
.write(true)
.open("./src/keycodes/mod.rs")
.unwrap();
for info in enums {
mod_file.write_fmt(format_args!("{info}\n")).unwrap();
mod_file.flush().unwrap();
}
}
fn parse_line(
line: &str,
enums: &mut Vec<EnumInfo>,
is_block_comment: &mut bool,
global_register: &mut HashMap<String, String>,
log_file: &mut File,
) {
log_file.write_fmt(format_args!("Line {line:?}\n")).unwrap();
log_file.flush().unwrap();
let line = line.trim();
let mut it = line
.split_ascii_whitespace()
.filter(|s| !s.is_empty())
.peekable();
while let Some(token) = it.next().map(ToOwned::to_owned) {
log_file
.write_fmt(format_args!("token {token:?}\n"))
.unwrap();
log_file.flush().unwrap();
println!("token {token:?}");
match token.as_str() {
_ if token.starts_with("#") => {
return;
}
"//" => {
log_file
.write_fmt(format_args!("skip {token:?}\n"))
.unwrap();
log_file.flush().unwrap();
return;
}
"enum" => {
log_file
.write_fmt(format_args!("new enum {token:?}\n"))
.unwrap();
log_file.flush().unwrap();
enums.push(EnumInfo::new(
it.next().expect("enum must have name").to_owned(),
));
}
"{" => {}
"," => {}
"}" | "};" => {}
_ if token.starts_with("/*") && token.ends_with("*/") => {
println!("closed comment");
}
_ if token.ends_with("*/") => {
*is_block_comment = false;
}
_ if *is_block_comment || token.starts_with("/*") => {
*is_block_comment = true;
println!("comment {token:?}");
log_file
.write_fmt(format_args!("comment {token:?}\n"))
.unwrap();
log_file.flush().unwrap();
while let Some(t) = it.next() {
println!("looking for \"*/\" : {t:?}");
log_file
.write_fmt(format_args!("looking for \"*/\" : {t:?}\n"))
.unwrap();
log_file.flush().unwrap();
if t.ends_with("*/") {
println!("ends looking for closing comment with {t:?}");
*is_block_comment = false;
break;
}
}
}
_ => {
if enums.is_empty() {
return;
}
let name = token.as_str();
println!("new variant name is {name:?}");
it.next().expect("variant must be followed by =");
let val = it.next().expect("variant must have value").trim_end_matches(",");
enums
.last_mut()
.expect("must have enum token before here")
.add_variant(name, val, global_register);
}
}
}
}
pub type VariantName = String;
pub type VariantValue = String;
pub type EnumName = String;
#[derive(Debug)]
pub struct EnumInfo {
pub name: String,
pub variants: HashMap<VariantName, VariantValue>,
pub values_cache: HashSet<VariantValue>,
}
impl Display for EnumInfo {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str("#[derive(Debug)]\n")?;
f.write_str("#[repr(C)]\n")?;
f.write_str("pub enum ")?;
f.write_str(Self::rust_enum_name(&self.name).as_str())?;
f.write_str(" {\n")?;
for (var_name, var_val) in &self.variants {
f.write_fmt(format_args!(
" {} = {},\n",
Self::rust_enum_name(var_name),
var_val
))?;
}
f.write_str("}")?;
Ok(())
}
}
impl EnumInfo {
const CACHE_SIZE: usize = 1024 * 5;
pub fn new(name: String) -> EnumInfo {
Self {
name,
variants: HashMap::with_capacity(Self::CACHE_SIZE),
values_cache: HashSet::with_capacity(Self::CACHE_SIZE),
}
}
pub fn add_variant<'global>(
&mut self,
name: &str,
val: &str,
global_register: &'global mut HashMap<VariantName, EnumName>,
) {
println!("adding variant {name:?} {val:?}");
if self.values_cache.contains(val) {
return;
}
self.variants.insert(
name.to_owned(),
global_register
.get(val)
.map(|enum_name| format!("{enum_name}::{val} as usize"))
.unwrap_or_else(|| val.to_owned()),
);
global_register.insert(name.to_owned(), self.name.clone());
}
fn rust_enum_name(name: &str) -> String {
let mut prev_underscore = false;
name.chars()
.enumerate()
.filter_map(|(idx, c)| {
if idx == 0 {
Some(c.to_ascii_uppercase())
} else if c == '_' {
prev_underscore = true;
None
} else if prev_underscore {
prev_underscore = false;
Some(c.to_ascii_uppercase())
} else {
Some(c)
}
})
.collect()
}
}

17
memory.x Normal file
View File

@ -0,0 +1,17 @@
MEMORY {
BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
/* Pick one of the two options for RAM layout */
/* OPTION A: Use all RAM banks as one big block */
/* Reasonable, unless you are doing something */
/* really particular with DMA or other concurrent */
/* access that would benefit from striping */
RAM : ORIGIN = 0x20000000, LENGTH = 264K
/* OPTION B: Keep the unstriped sections separate */
/* RAM: ORIGIN = 0x20000000, LENGTH = 256K */
/* SCRATCH_A: ORIGIN = 0x20040000, LENGTH = 4K */
/* SCRATCH_B: ORIGIN = 0x20041000, LENGTH = 4K */
}

12
rust-toolchain.toml Normal file
View File

@ -0,0 +1,12 @@
[toolchain]
channel = "stable"
components = [ "rust-src", "rustfmt", "llvm-tools" ]
targets = [
"thumbv7em-none-eabi",
"thumbv7m-none-eabi",
"thumbv6m-none-eabi",
"thumbv7em-none-eabihf",
"thumbv8m.main-none-eabihf",
"riscv32imac-unknown-none-elf",
"wasm32-unknown-unknown",
]

View File

@ -5,11 +5,11 @@ pub type BacklightLevel = u8;
#[cfg(feature = "backlight_breathing")]
pub struct BacklightBreathing {
pub enabled: bool,
pub period: std::time::Duration,
pub period: core::time::Duration,
}
pub struct Backlight<'d> {
pub pins: Vec<Output<'d, AnyPin>>,
pub struct Backlight<'d, const PIN_COUNT: usize> {
pub pins: [Output<'d, AnyPin>; PIN_COUNT],
pub on: bool,
pub default_on: bool,
pub lvl: BacklightLevel,
@ -18,8 +18,8 @@ pub struct Backlight<'d> {
pub breathing: BacklightBreathing,
}
impl<'d> Backlight<'d> {
pub fn new(pins: Vec<Output<'d, AnyPin>>, default_lvl: BacklightLevel) -> Self {
impl<'d, const PIN_COUNT: usize> Backlight<'d, PIN_COUNT> {
pub fn new(pins: [Output<'d, AnyPin>; PIN_COUNT], default_lvl: BacklightLevel) -> Self {
let mut bl = Self {
pins,
on: cfg!(feature = "backlight_default_on"),
@ -29,36 +29,29 @@ impl<'d> Backlight<'d> {
#[cfg(feature = "backlight_breathing")]
breathing: BacklightBreathing {
enabled: cfg!(feature = "backlight_breathing_default_on"),
period: std::time::Duration::from_millis(66),
period: core::time::Duration::from_millis(66),
},
};
bl.backlight_pins_off();
bl
}
fn backlight_pin_on<'d>(pin: &mut Output<'d, AnyPin>) {
if cfg!(feature = "backlight_on_state") {
pin.set_high();
} else {
pin.set_low();
}
}
fn backlight_pin_off<'d>(pin: &mut Output<'d, AnyPin>) {
if cfg!(feature = "backlight_on_state") {
pin.set_low();
} else {
pin.set_high();
}
}
pub fn backlight_pins_on<'d>(&mut self) {
pub fn backlight_pins_on(&mut self) {
for pin in &mut self.pins {
Self::backlight_pin_on(pin);
if cfg!(feature = "backlight_on_state") {
pin.set_high();
} else {
pin.set_low();
}
}
}
pub fn backlight_pins_off<'d>(&mut self) {
pub fn backlight_pins_off(&mut self) {
for pin in &mut self.pins {
Self::backlight_pin_off(pin);
if cfg!(feature = "backlight_on_state") {
pin.set_low();
} else {
pin.set_high();
}
}
}

1340
src/keycodes/mod.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
pub enum QkKeycodeRanges {
/*#[repr(C)]
pub enum QkKeycodeRange {
// Ranges
QkBasic = 0x0000,
QkBasicMax = 0x00FF,
@ -60,6 +61,7 @@ pub enum QkKeycodeRanges {
// QkUnicodemapPairMax = 0xFFFF,
}
#[repr(C)]
enum QkKeycodeDefines {
// Keycodes
KcNo = 0x0000,
@ -762,7 +764,7 @@ enum QkKeycodeDefines {
// Alias
XXXXXXX = QkKeycodeDefines::KcNo as isize,
KcTrns = Keycodes::KcTransparent,
KcTrns = QkKeycodeDefines::KcTransparent as isize,
KcEnt = Keycodes::KcEnter,
KcEsc = Keycodes::KcEscape,
KcBspc = Keycodes::KcBackspace,
@ -1338,3 +1340,4 @@ enum QkKeycodeDefines {
QkRep = Keycodes::QkRepeatKey,
QkArep = Keycodes::QkAltRepeatKey,
}
*/

View File

@ -1,2 +1,5 @@
#![no_std]
#![no_main]
pub mod backlight;
pub mod keycodes;

View File

@ -11,5 +11,5 @@ use {defmt_rtt as _, panic_probe as _};
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = init(Default::default());
let _p = init(Default::default());
}