From d2efe4da3b90ab22cd7dd06f3401a213b4d542f9 Mon Sep 17 00:00:00 2001
From: doinkythederp <doinkythederp@icloud.com>
Date: Fri, 17 Nov 2023 16:09:03 -0800
Subject: [PATCH 1/6] feat(sys): add colors to xapi in llemu

---
 .vscode/settings.json |  7 +++++
 pros-sys/Cargo.toml   |  3 ++
 pros-sys/src/llemu.rs | 72 +++++++++++++++++++++++++++++++++++++------
 3 files changed, 72 insertions(+), 10 deletions(-)

diff --git a/.vscode/settings.json b/.vscode/settings.json
index c9eb925f..4f651be4 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -11,4 +11,11 @@
         "vexlink"
     ],
     "rust-analyzer.check.allTargets": false,
+    "rust-analyzer.cargo.features": [
+        "xapi"
+    ],
+    "rust-analyzer.check.targets": [
+        "${workspaceFolder}/armv7a-vexos-eabi.json",
+        "wasm32-unknown-unknown",
+    ]
 }
diff --git a/pros-sys/Cargo.toml b/pros-sys/Cargo.toml
index d26cfae1..20da4d78 100644
--- a/pros-sys/Cargo.toml
+++ b/pros-sys/Cargo.toml
@@ -24,3 +24,6 @@ no-link = []
 
 [build-dependencies]
 cfg-if = "1.0"
+
+[dependencies]
+cfg-if = "1.0"
diff --git a/pros-sys/src/llemu.rs b/pros-sys/src/llemu.rs
index 4eb6b9c3..c4a4c251 100644
--- a/pros-sys/src/llemu.rs
+++ b/pros-sys/src/llemu.rs
@@ -1,5 +1,7 @@
-#[cfg(feature = "xapi")]
-compile_error!("LVGL bindings (xapi) are a todo for now");
+// #[cfg(feature = "xapi")]
+// compile_error!("LVGL bindings (xapi) are a todo for now");
+
+use cfg_if::cfg_if;
 
 pub const LCD_BTN_LEFT: core::ffi::c_int = 4;
 pub const LCD_BTN_CENTER: core::ffi::c_int = 2;
@@ -7,10 +9,42 @@ pub const LCD_BTN_RIGHT: core::ffi::c_int = 1;
 
 pub type lcd_button_cb_fn_t = Option<unsafe extern "C" fn()>;
 
-#[cfg(feature = "xapi")]
-#[repr(C)]
-pub struct lcd_s_t {
-    //TODO
+cfg_if! {
+    if #[cfg(feature = "xapi")] {
+        // #[repr(C)]
+        // pub struct lcd_s_t {
+        //     //TODO
+        // }
+
+        #[repr(C)]
+        #[derive(Debug, Clone, Copy, PartialEq, Eq)]
+        pub struct lv_color_t {
+            pub blue: u8,
+            pub green: u8,
+            pub red: u8,
+            pub alpha: u8,
+        }
+
+        impl From<u32> for lv_color_t {
+            fn from(color: u32) -> Self {
+                Self {
+                    blue: (color & 0xFF) as u8,
+                    green: ((color >> 8) & 0xFF) as u8,
+                    red: ((color >> 16) & 0xFF) as u8,
+                    alpha: ((color >> 24) & 0xFF) as u8,
+                }
+            }
+        }
+
+        impl From<lv_color_t> for u32 {
+            fn from(color: lv_color_t) -> Self {
+                (color.blue as u32)
+                    | ((color.green as u32) << 8)
+                    | ((color.red as u32) << 16)
+                    | ((color.alpha as u32) << 24)
+            }
+        }
+    }
 }
 
 extern "C" {
@@ -149,8 +183,26 @@ extern "C" {
     \return The buttons pressed as a bit mask*/
     pub fn lcd_read_buttons() -> u8;
 
-    #[cfg(feature = "xapi")]
-    pub fn lcd_set_background_color(); //TODO
-    #[cfg(feature = "xapi")]
-    pub fn lcd_set_text_color(); //TODO
+    cfg_if! {
+        if #[cfg(feature = "xapi")] {
+            /** Changes the color of the LCD background to a provided color expressed in
+            type lv_color_t.
+
+            \param color
+                   A color of type lv_color_t
+
+            \return void
+            */
+            pub fn lcd_set_background_color(color: lv_color_t);
+            /** Changes the text color of the LCD to a provided color expressed in
+            type lv_color_t.
+
+            \param color
+                   A color of type lv_color_t
+
+            \return void
+            */
+            pub fn lcd_set_text_color(color: lv_color_t);
+        }
+    }
 }

From 68045ad20536daf9afcadbe6e8329059bddec52a Mon Sep 17 00:00:00 2001
From: doinkythederp <doinkythederp@icloud.com>
Date: Fri, 17 Nov 2023 16:26:54 -0800
Subject: [PATCH 2/6] feat(lcd): add LcdColor struct

---
 pros/src/lcd/colors.rs     | 65 ++++++++++++++++++++++++++++++++++++++
 pros/src/lcd/mod.rs        |  1 +
 pros/src/sensors/vision.rs | 28 ++++++++++++++--
 3 files changed, 92 insertions(+), 2 deletions(-)
 create mode 100644 pros/src/lcd/colors.rs

diff --git a/pros/src/lcd/colors.rs b/pros/src/lcd/colors.rs
new file mode 100644
index 00000000..eb84a638
--- /dev/null
+++ b/pros/src/lcd/colors.rs
@@ -0,0 +1,65 @@
+use core::ops::{Deref, DerefMut};
+use pros_sys::lv_color_t;
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct LcdColor(pub lv_color_t);
+
+impl LcdColor {
+    pub const fn new_rgb(red: u8, green: u8, blue: u8) -> Self {
+        Self(lv_color_t {
+            red,
+            green,
+            blue,
+            alpha: 0xFF,
+        })
+    }
+    pub const fn new_rgba(red: u8, green: u8, blue: u8, alpha: u8) -> Self {
+        Self(lv_color_t {
+            red,
+            green,
+            blue,
+            alpha,
+        })
+    }
+}
+
+impl From<lv_color_t> for LcdColor {
+    fn from(other: lv_color_t) -> Self {
+        Self(other)
+    }
+}
+
+impl Deref for LcdColor {
+    type Target = lv_color_t;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl DerefMut for LcdColor {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.0
+    }
+}
+
+impl LcdColor {
+    pub const WHITE: Self = Self::new_rgb(0xFF, 0xFF, 0xFF);
+    pub const SILVER: Self = Self::new_rgb(0xC0, 0xC0, 0xC0);
+    pub const GRAY: Self = Self::new_rgb(0x80, 0x80, 0x80);
+    pub const BLACK: Self = Self::new_rgb(0x00, 0x00, 0x00);
+    pub const RED: Self = Self::new_rgb(0xFF, 0x00, 0x00);
+    pub const MAROON: Self = Self::new_rgb(0x80, 0x00, 0x00);
+    pub const YELLOW: Self = Self::new_rgb(0xFF, 0xFF, 0x00);
+    pub const OLIVE: Self = Self::new_rgb(0x80, 0x80, 0x00);
+    pub const LIME: Self = Self::new_rgb(0x00, 0xFF, 0x00);
+    pub const GREEN: Self = Self::new_rgb(0x00, 0x80, 0x00);
+    pub const CYAN: Self = Self::new_rgb(0x00, 0xFF, 0xFF);
+    pub const AQUA: Self = Self::CYAN;
+    pub const TEAL: Self = Self::new_rgb(0x00, 0x80, 0x80);
+    pub const BLUE: Self = Self::new_rgb(0x00, 0x00, 0xFF);
+    pub const NAVY: Self = Self::new_rgb(0x00, 0x00, 0x80);
+    pub const MAGENTA: Self = Self::new_rgb(0xFF, 0x00, 0xFF);
+    pub const PURPLE: Self = Self::new_rgb(0x80, 0x00, 0x80);
+    pub const ORANGE: Self = Self::new_rgb(0xFF, 0xA5, 0x00);
+}
diff --git a/pros/src/lcd/mod.rs b/pros/src/lcd/mod.rs
index 97361adf..2bf46cff 100644
--- a/pros/src/lcd/mod.rs
+++ b/pros/src/lcd/mod.rs
@@ -5,6 +5,7 @@ use crate::sync::Mutex;
 #[macro_use]
 pub mod macros;
 pub mod buttons;
+pub mod colors;
 
 pub(crate) mod writer;
 
diff --git a/pros/src/sensors/vision.rs b/pros/src/sensors/vision.rs
index e4f5db66..9b9a2791 100644
--- a/pros/src/sensors/vision.rs
+++ b/pros/src/sensors/vision.rs
@@ -1,9 +1,12 @@
 extern crate alloc;
 use alloc::vec::Vec;
-use pros_sys::{PROS_ERR, VISION_OBJECT_ERR_SIG};
+use pros_sys::{lv_color_t, PROS_ERR, VISION_OBJECT_ERR_SIG};
 use snafu::Snafu;
 
-use crate::error::{bail_errno, bail_on, map_errno, PortError};
+use crate::{
+    error::{bail_errno, bail_on, map_errno, PortError},
+    lcd::colors::LcdColor,
+};
 
 /// Represents a vision sensor plugged into the vex.
 pub struct VisionSensor {
@@ -168,6 +171,27 @@ impl From<u32> for Rgb {
     }
 }
 
+impl From<Rgb> for LcdColor {
+    fn from(other: Rgb) -> Self {
+        Self(lv_color_t {
+            red: other.r,
+            green: other.g,
+            blue: other.b,
+            alpha: 0xFF,
+        })
+    }
+}
+
+impl From<LcdColor> for Rgb {
+    fn from(other: LcdColor) -> Self {
+        Self {
+            r: other.red,
+            g: other.green,
+            b: other.blue,
+        }
+    }
+}
+
 #[repr(u32)]
 pub enum VisionZeroPoint {
     TopLeft,

From 50c90aa8afe5f17c60d17a61f01d99e06c94a0ea Mon Sep 17 00:00:00 2001
From: doinkythederp <doinkythederp@icloud.com>
Date: Fri, 17 Nov 2023 17:14:28 -0800
Subject: [PATCH 3/6] feat(lcd): add methods for changing colors

---
 pros/Cargo.toml                  |  5 +---
 pros/src/lcd/mod.rs              | 16 ++++++++++-
 pros/src/lib.rs                  | 10 +------
 pros/src/{lcd => lvgl}/colors.rs |  0
 pros/src/lvgl/mod.rs             |  2 +-
 pros/src/sensors/vision.rs       | 47 +++++++++++++++-----------------
 6 files changed, 40 insertions(+), 40 deletions(-)
 rename pros/src/{lcd => lvgl}/colors.rs (100%)

diff --git a/pros/Cargo.toml b/pros/Cargo.toml
index e1e6fb27..3b9f4da3 100644
--- a/pros/Cargo.toml
+++ b/pros/Cargo.toml
@@ -14,7 +14,7 @@ readme = "../README.md"
 [dependencies]
 lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
 spin = "0.9.8"
-pros-sys = { version = "0.3.0", path = "../pros-sys" }
+pros-sys = { version = "0.3.0", path = "../pros-sys", features = ["xapi"] }
 snafu = { version = "0.7.5", default-features = false, features = [
     "rust_1_61",
 ] }
@@ -22,6 +22,3 @@ no_std_io = { version = "0.6.0", features = ["alloc"] }
 
 [target.'cfg(target_arch = "wasm32")'.dependencies]
 dlmalloc = { version = "0.2.4", features = ["global"] }
-
-[features]
-lvgl = ["pros-sys/xapi"]
diff --git a/pros/src/lcd/mod.rs b/pros/src/lcd/mod.rs
index 2bf46cff..8b7d3f14 100644
--- a/pros/src/lcd/mod.rs
+++ b/pros/src/lcd/mod.rs
@@ -1,14 +1,28 @@
 use snafu::Snafu;
 
+use crate::lvgl::colors::LcdColor;
 use crate::sync::Mutex;
 
 #[macro_use]
 pub mod macros;
 pub mod buttons;
-pub mod colors;
 
 pub(crate) mod writer;
 
+pub fn set_background_color(color: LcdColor) {
+    unsafe {
+        pros_sys::lcd_initialize();
+        pros_sys::lcd_set_background_color(*color);
+    }
+}
+
+pub fn set_text_color(color: LcdColor) {
+    unsafe {
+        pros_sys::lcd_initialize();
+        pros_sys::lcd_set_background_color(*color);
+    }
+}
+
 lazy_static::lazy_static! {
     pub(crate) static ref WRITER: Mutex<writer::ConsoleLcd> = {
         Mutex::new(writer::ConsoleLcd::new())
diff --git a/pros/src/lib.rs b/pros/src/lib.rs
index 9e2598e4..700715f3 100644
--- a/pros/src/lib.rs
+++ b/pros/src/lib.rs
@@ -11,25 +11,17 @@ pub mod position;
 pub mod sensors;
 pub mod sync;
 pub mod task;
-
 #[doc(hidden)]
 pub use pros_sys as __pros_sys;
-
 #[cfg(target_os = "vexos")]
 mod vexos_env;
 #[cfg(target_arch = "wasm32")]
 mod wasm_env;
-
-#[cfg(not(feature = "lvgl"))]
 #[macro_use]
 pub mod lcd;
-
-#[cfg(feature = "lvgl")]
-#[macro_use]
-pub mod lvgl;
-
 pub mod adi;
 pub mod link;
+pub mod lvgl;
 
 pub type Result<T = ()> = core::result::Result<T, alloc::boxed::Box<dyn core::error::Error>>;
 
diff --git a/pros/src/lcd/colors.rs b/pros/src/lvgl/colors.rs
similarity index 100%
rename from pros/src/lcd/colors.rs
rename to pros/src/lvgl/colors.rs
diff --git a/pros/src/lvgl/mod.rs b/pros/src/lvgl/mod.rs
index 8b137891..40fd5c10 100644
--- a/pros/src/lvgl/mod.rs
+++ b/pros/src/lvgl/mod.rs
@@ -1 +1 @@
-
+pub mod colors;
diff --git a/pros/src/sensors/vision.rs b/pros/src/sensors/vision.rs
index 9b9a2791..5bbd9163 100644
--- a/pros/src/sensors/vision.rs
+++ b/pros/src/sensors/vision.rs
@@ -1,12 +1,9 @@
 extern crate alloc;
 use alloc::vec::Vec;
-use pros_sys::{lv_color_t, PROS_ERR, VISION_OBJECT_ERR_SIG};
+use pros_sys::{PROS_ERR, VISION_OBJECT_ERR_SIG};
 use snafu::Snafu;
 
-use crate::{
-    error::{bail_errno, bail_on, map_errno, PortError},
-    lcd::colors::LcdColor,
-};
+use crate::error::{bail_errno, bail_on, map_errno, PortError};
 
 /// Represents a vision sensor plugged into the vex.
 pub struct VisionSensor {
@@ -171,26 +168,26 @@ impl From<u32> for Rgb {
     }
 }
 
-impl From<Rgb> for LcdColor {
-    fn from(other: Rgb) -> Self {
-        Self(lv_color_t {
-            red: other.r,
-            green: other.g,
-            blue: other.b,
-            alpha: 0xFF,
-        })
-    }
-}
-
-impl From<LcdColor> for Rgb {
-    fn from(other: LcdColor) -> Self {
-        Self {
-            r: other.red,
-            g: other.green,
-            b: other.blue,
-        }
-    }
-}
+// impl From<Rgb> for LcdColor {
+//     fn from(other: Rgb) -> Self {
+//         Self(lv_color_t {
+//             red: other.r,
+//             green: other.g,
+//             blue: other.b,
+//             alpha: 0xFF,
+//         })
+//     }
+// }
+
+// impl From<LcdColor> for Rgb {
+//     fn from(other: LcdColor) -> Self {
+//         Self {
+//             r: other.red,
+//             g: other.green,
+//             b: other.blue,
+//         }
+//     }
+// }
 
 #[repr(u32)]
 pub enum VisionZeroPoint {

From ee27548ce203f1eb836b4d42708e3649669aaf29 Mon Sep 17 00:00:00 2001
From: doinkythederp <doinkythederp@icloud.com>
Date: Fri, 17 Nov 2023 17:30:40 -0800
Subject: [PATCH 4/6] docs(lcd): add basic docs for colors

---
 pros/src/lcd/mod.rs     | 3 +++
 pros/src/lvgl/colors.rs | 5 +++++
 2 files changed, 8 insertions(+)

diff --git a/pros/src/lcd/mod.rs b/pros/src/lcd/mod.rs
index 8b7d3f14..182b665f 100644
--- a/pros/src/lcd/mod.rs
+++ b/pros/src/lcd/mod.rs
@@ -1,3 +1,4 @@
+//! Print to and handle button presses on the V5 touchscreen.
 use snafu::Snafu;
 
 use crate::lvgl::colors::LcdColor;
@@ -9,6 +10,7 @@ pub mod buttons;
 
 pub(crate) mod writer;
 
+/// Sets the background color of the LCD.
 pub fn set_background_color(color: LcdColor) {
     unsafe {
         pros_sys::lcd_initialize();
@@ -16,6 +18,7 @@ pub fn set_background_color(color: LcdColor) {
     }
 }
 
+/// Sets the text color of the LCD.
 pub fn set_text_color(color: LcdColor) {
     unsafe {
         pros_sys::lcd_initialize();
diff --git a/pros/src/lvgl/colors.rs b/pros/src/lvgl/colors.rs
index eb84a638..c60358d5 100644
--- a/pros/src/lvgl/colors.rs
+++ b/pros/src/lvgl/colors.rs
@@ -1,10 +1,14 @@
+//! LVGL colors and presets.
+
 use core::ops::{Deref, DerefMut};
 use pros_sys::lv_color_t;
 
+/// A color that can be used on the LCD.
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
 pub struct LcdColor(pub lv_color_t);
 
 impl LcdColor {
+    /// Create an RGB color without any transparency.
     pub const fn new_rgb(red: u8, green: u8, blue: u8) -> Self {
         Self(lv_color_t {
             red,
@@ -13,6 +17,7 @@ impl LcdColor {
             alpha: 0xFF,
         })
     }
+    /// Create an RGBA color with a certain opacity.
     pub const fn new_rgba(red: u8, green: u8, blue: u8, alpha: u8) -> Self {
         Self(lv_color_t {
             red,

From f4a8f23b16b2b9066284b4fc6ee422df1303a809 Mon Sep 17 00:00:00 2001
From: Gavin-Niederman <gavinniederman@gmail.com>
Date: Fri, 17 Nov 2023 21:30:03 -0800
Subject: [PATCH 5/6] fix: uncomment conversion implementations

---
 pros/src/lvgl/colors.rs    |  1 +
 pros/src/sensors/vision.rs | 42 +++++++++++++++++++-------------------
 2 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/pros/src/lvgl/colors.rs b/pros/src/lvgl/colors.rs
index c60358d5..243e9fce 100644
--- a/pros/src/lvgl/colors.rs
+++ b/pros/src/lvgl/colors.rs
@@ -4,6 +4,7 @@ use core::ops::{Deref, DerefMut};
 use pros_sys::lv_color_t;
 
 /// A color that can be used on the LCD.
+/// The color space is dependent on the LCD driver.
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
 pub struct LcdColor(pub lv_color_t);
 
diff --git a/pros/src/sensors/vision.rs b/pros/src/sensors/vision.rs
index 5bbd9163..ad9646cb 100644
--- a/pros/src/sensors/vision.rs
+++ b/pros/src/sensors/vision.rs
@@ -3,7 +3,7 @@ use alloc::vec::Vec;
 use pros_sys::{PROS_ERR, VISION_OBJECT_ERR_SIG};
 use snafu::Snafu;
 
-use crate::error::{bail_errno, bail_on, map_errno, PortError};
+use crate::{error::{bail_errno, bail_on, map_errno, PortError}, lvgl::colors::LcdColor};
 
 /// Represents a vision sensor plugged into the vex.
 pub struct VisionSensor {
@@ -168,26 +168,26 @@ impl From<u32> for Rgb {
     }
 }
 
-// impl From<Rgb> for LcdColor {
-//     fn from(other: Rgb) -> Self {
-//         Self(lv_color_t {
-//             red: other.r,
-//             green: other.g,
-//             blue: other.b,
-//             alpha: 0xFF,
-//         })
-//     }
-// }
-
-// impl From<LcdColor> for Rgb {
-//     fn from(other: LcdColor) -> Self {
-//         Self {
-//             r: other.red,
-//             g: other.green,
-//             b: other.blue,
-//         }
-//     }
-// }
+impl From<Rgb> for LcdColor {
+    fn from(other: Rgb) -> Self {
+        Self(pros_sys::lv_color_t {
+            red: other.r,
+            green: other.g,
+            blue: other.b,
+            alpha: 0xFF,
+        })
+    }
+}
+
+impl From<LcdColor> for Rgb {
+    fn from(other: LcdColor) -> Self {
+        Self {
+            r: other.red,
+            g: other.green,
+            b: other.blue,
+        }
+    }
+}
 
 #[repr(u32)]
 pub enum VisionZeroPoint {

From c3b18d93a784723be78c21e76ad4b1b5cb350d02 Mon Sep 17 00:00:00 2001
From: Gavin-Niederman <gavinniederman@gmail.com>
Date: Fri, 17 Nov 2023 21:33:10 -0800
Subject: [PATCH 6/6] chore: formatting

---
 pros/src/sensors/vision.rs | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/pros/src/sensors/vision.rs b/pros/src/sensors/vision.rs
index ad9646cb..e12d05ba 100644
--- a/pros/src/sensors/vision.rs
+++ b/pros/src/sensors/vision.rs
@@ -3,7 +3,10 @@ use alloc::vec::Vec;
 use pros_sys::{PROS_ERR, VISION_OBJECT_ERR_SIG};
 use snafu::Snafu;
 
-use crate::{error::{bail_errno, bail_on, map_errno, PortError}, lvgl::colors::LcdColor};
+use crate::{
+    error::{bail_errno, bail_on, map_errno, PortError},
+    lvgl::colors::LcdColor,
+};
 
 /// Represents a vision sensor plugged into the vex.
 pub struct VisionSensor {