Merge branch 'master' of github.com:betrusted-io/xous-core

This commit is contained in:
Sean Cross 2020-11-23 14:20:27 +08:00
commit be1687ffdd
16 changed files with 1578 additions and 453 deletions

92
Cargo.lock generated
View file

@ -39,6 +39,18 @@ version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1fd36ffbb1fb7c834eac128ea8d0e310c5aeb635548f9d58861e1308d46e71c"
[[package]]
name = "as-slice"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb4d1c23475b74e3672afa8c2be22040b8b7783ad9b461021144ed10a46bb0e6"
dependencies = [
"generic-array 0.12.3",
"generic-array 0.13.2",
"generic-array 0.14.4",
"stable_deref_trait",
]
[[package]]
name = "atty"
version = "0.2.14"
@ -214,15 +226,6 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
[[package]]
name = "embedded-graphics"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40a69991ceb896bd4810a0cf2bcc46fc94b7860573c71f965d8e5b3d66942fed"
dependencies = [
"byteorder",
]
[[package]]
name = "env_logger"
version = "0.7.1"
@ -251,6 +254,34 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "generic-array"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
dependencies = [
"typenum",
]
[[package]]
name = "generic-array"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd"
dependencies = [
"typenum",
]
[[package]]
name = "generic-array"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.1.14"
@ -279,6 +310,27 @@ dependencies = [
"xous",
]
[[package]]
name = "hash32"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc"
dependencies = [
"byteorder",
]
[[package]]
name = "heapless"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74911a68a1658cfcfb61bc0ccfbd536e3b6e906f8c2f7883ee50157e3e2184f1"
dependencies = [
"as-slice",
"generic-array 0.13.2",
"hash32",
"stable_deref_trait",
]
[[package]]
name = "hermit-abi"
version = "0.1.15"
@ -819,6 +871,12 @@ version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252"
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "strsim"
version = "0.8.0"
@ -890,7 +948,9 @@ dependencies = [
name = "ticktimer-server"
version = "0.1.0"
dependencies = [
"embedded-graphics",
"heapless",
"log",
"log-server",
"utralib",
"xous",
]
@ -909,6 +969,12 @@ dependencies = [
"xmas-elf",
]
[[package]]
name = "typenum"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
[[package]]
name = "unicode-width"
version = "0.1.8"
@ -934,6 +1000,12 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
[[package]]
name = "void"
version = "1.0.2"

View file

@ -1,20 +1,61 @@
#!/bin/sh
#!/bin/bash
# argument 1 is the target for copy
set -e # exit on any error
if [ -z "$1" ]
then
echo "Usage: $0 ssh-target [privatekey]"
echo "Missing ssh-target argument."
echo "Assumes betrusted-scripts repo is cloned on ssh-target at ~/code/betrused-scripts/"
exit 0
fi
UPDATE_FPGA=1
UPDATE_KERNEL=1
USE_USB=1
FPGA_IMAGE=../betrusted-soc/build/gateware/encrypted.bin
KERNEL_IMAGE=target/riscv32imac-unknown-none-elf/release/xous.img
CSR_CSV=../betrusted-soc/build/csr.csv.1
USE_IDENITY=0
# notes:
# xous-stage1.bin written to 0x2050_0000 (64k erase block size)
# xous-kernel.bin written to 0x2051_0000 => passed as a0 arg to xous-stage1.bin
# This is handled in part by betrusted-scripts, with provision-xous.sh
# stage1 and kernel are merged into xous.img by this script.
POSITIONAL=()
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
-k|--kernel-skip)
UPDATE_KERNEL=0
shift
;;
-f|--fpga-skip)
UPDATE_FPGA=0
shift
;;
-c|--copy-to)
DEST_HOST=$2
USE_USB=0
shift
shift
;;
-i|--identity)
USE_IDENTITY=1
IDENTITY=$2
shift
shift
;;
--current-csr)
CSR_CSV=../betrusted-soc/build/csr.csv
shift
;;
-h|--help)
echo "$0 provisions betrusted. --kernel-skip skips the kernel, --fpga-skip skips the FPGA. --current-csr indicates to use the CSR for the new FPGA image to do the update (normally you want to use the one corresponding to the older, currently installed version)."
echo "Alternatively, using --copy-to <hostname> copies the files to a remote host and skips provisioning."
echo " --identity <id_file> supplies an identity file to the scp command."
echo " Copying assumes betrusted-scripts repo is cloned on ssh-target at ~/code/betrused-scripts/"
exit 0
;;
*)
POSITIONAL+=("$1")
shift
;;
esac
done
set -- "${POSITIONAL[@]}"
DESTDIR=code/precursors
cargo xtask hw-image ../betrusted-soc/build/software/soc.svd
@ -24,19 +65,29 @@ then
exit 1
fi
echo "Copying to target..."
if [ $# -gt 0 ]
# case of no private key specified
if [ $USE_USB -eq 1 ]
then
if [ -z "$2" ]
if [ $UPDATE_FPGA -eq 1 ]
then
scp target/riscv32imac-unknown-none-elf/release/xous.img $1:code/betrusted-scripts/
scp ../betrusted-soc/build/gateware/encrypted.bin $1:code/betrusted-scripts/
scp ../betrusted-soc/build/csr.csv $1:code/betrusted-scripts/soc-csr.csv
else
scp -i $2 target/riscv32imac-unknown-none-elf/release/xous.img $1:code/betrusted-scripts/
scp -i $2 ../betrusted-soc/build/gateware/encrypted.bin $1:code/betrusted-scripts/
scp -i $2 ../betrusted-soc/build/csr.csv $1:code/betrusted-scripts/soc-csr.csv
echo "Burning FPGA image"
sudo wishbone-tool --csr-csv $CSR_CSV --load-name $FPGA_IMAGE --load-address 0x0 --load-flash
echo "*** Manual power cycle required to reload SoC FPGA configuration ***"
echo " -> Either issue a power cycle command, or insert paper clip in the hole on the right hand side!"
fi
if [ $UPDATE_KERNEL -eq 1 ]
then
echo "Burning firmware"
sudo wishbone-tool --csr-csv $CSR_CSV --load-name $KERNEL_IMAGE --load-address 0x500000 --load-flash
fi
else
echo "Copy to target with $0 <user@host> <ssh-id>"
if [ $USE_IDENTITY -eq 1 ]
then
# there is a private key
scp -i $IDENTITY $KERNEL_IMAGE $FPGA_IMAGE $DEST_HOST:$DESTDIR/
scp -i $IDENTITY $CSR_CSV $DEST_HOST:$DESTDIR/soc-csr.csv
else
scp $KERNEL_IMAGE $FPGA_IMAGE $CSR_CSV $DEST_HOST:$DESTDIR/
scp $CSR_CSV $DEST_HOST:$DESTDIR/soc-csr.csv
fi
fi

View file

@ -21,7 +21,8 @@ riscv = "0.5.6"
debug-print = []
print-panics = []
report-memory = ["stats_alloc"]
default = ["print-panics", "debug-print"]
#default = ["print-panics", "debug-print"]
default = []
[target.'cfg(any(windows, unix))'.dependencies]
lazy_static = "1.4"

View file

@ -51,7 +51,7 @@ impl Uart {
#[allow(dead_code)]
pub fn enable_rx(self) {
let mut uart_csr = CSR::new(self.base as *mut u32);
uart_csr.wfo(utra::uart::EV_ENABLE_ENABLE, uart_csr.rf(utra::uart::EV_ENABLE_ENABLE) | 2);
uart_csr.rmwf(utra::uart::EV_ENABLE_RX, 1);
}
pub fn putc(&self, c: u8) {
@ -68,7 +68,7 @@ impl Uart {
let mut uart_csr = CSR::new(self.base as *mut u32);
// If EV_PENDING_RX is 1, return the pending character.
// Otherwise, return None.
match uart_csr.r(utra::uart::EV_PENDING) & 2 {
match uart_csr.rf(utra::uart::EV_PENDING_RX) {
0 => None,
ack => {
let c = Some(uart_csr.r(utra::uart::RXTX) as u8);

View file

@ -14,7 +14,8 @@ rand = "0.7.3"
[features]
debug-print = []
earlyprintk = []
default = ["debug-print"]
#default = ["debug-print"]
default = []
[profile.release]
codegen-units = 1 # 1 better optimizations

View file

@ -1,15 +1,497 @@
use crate::op::PixelColor;
use xous::{Message, ScalarMessage};
use core::ops::{Add, AddAssign, Index, Neg, Sub, SubAssign};
#[derive(Copy, Clone, Debug)]
/// 2D size.
///
/// `Size` is used to define the width and height of an object.
///
/// [Nalgebra] support can be enabled with the `nalgebra_support` feature. This implements
/// `From<Vector2<N>>` and `From<&Vector2<N>>` where `N` is `Scalar + Into<u16>`. This allows use
/// of Nalgebra's [`Vector2`] with embedded-graphics where `u16`, `u16` or `u8` is used for value
/// storage.
///
/// # Examples
///
/// ## Create a `Size` from two integers
///
///
/// ```rust
/// use embedded_graphics::geometry::Size;
///
/// // Create a size using the `new` constructor method
/// let s = Size::new(10, 20);
/// ```
///
/// ## Create a `Size` from a Nalgebra `Vector2`
///
/// _Be sure to enable the `nalgebra_support` feature to get [Nalgebra] integration._
///
/// Any `Vector2<N>` can be used where `N: Into<u16> + nalgebra::Scalar`. This includes the primitive types `u16`, `u16` and `u8`.
///
/// ```rust
/// # #[cfg(feature = "nalgebra_support")] {
/// use nalgebra::Vector2;
/// use embedded_graphics::geometry::Size;
///
/// assert_eq!(Size::from(Vector2::new(10u16, 20)), Size::new(10u16, 20));
/// assert_eq!(Size::from(Vector2::new(10u16, 20)), Size::new(10u16, 20));
/// assert_eq!(Size::from(Vector2::new(10u8, 20)), Size::new(10u16, 20));
/// # }
/// ```
///
/// `.into()` can also be used, but may require more type annotations:
///
/// ```rust
/// # #[cfg(feature = "nalgebra_support")] {
/// use nalgebra::Vector2;
/// use embedded_graphics::geometry::Size;
///
/// let c: Size = Vector2::new(10u16, 20).into();
///
/// assert_eq!(c, Size::new(10u16, 20));
/// # }
/// ```
///
/// [`Drawable`]: ../drawable/trait.Drawable.html
/// [`Point`]: struct.Point.html
/// [`Vector2<N>`]: https://docs.rs/nalgebra/0.18.0/nalgebra/base/type.Vector2.html
/// [`Vector2`]: https://docs.rs/nalgebra/0.18.0/nalgebra/base/type.Vector2.html
/// [Nalgebra]: https://docs.rs/nalgebra
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
pub struct Size {
/// The width.
pub width: u16,
/// The height.
pub height: u16,
}
impl Size {
/// Creates a size from a width and a height.
pub const fn new(width: u16, height: u16) -> Self {
Size { width, height }
}
/// Creates a size with width and height equal to zero.
pub const fn zero() -> Self {
Size {
width: 0,
height: 0,
}
}
/// Creates a size from two corner points of a bounding box.
pub(crate) fn from_bounding_box(corner_1: Point, corner_2: Point) -> Self {
let width = (corner_1.x - corner_2.x).abs() as u16;
let height = (corner_1.y - corner_2.y).abs() as u16;
Self { width, height }
}
}
impl Add for Size {
type Output = Size;
fn add(self, other: Size) -> Size {
Size::new(self.width + other.width, self.height + other.height)
}
}
impl AddAssign for Size {
fn add_assign(&mut self, other: Size) {
self.width += other.width;
self.height += other.height;
}
}
impl Sub for Size {
type Output = Size;
fn sub(self, other: Size) -> Size {
Size::new(self.width - other.width, self.height - other.height)
}
}
impl SubAssign for Size {
fn sub_assign(&mut self, other: Size) {
self.width -= other.width;
self.height -= other.height;
}
}
impl Index<usize> for Size {
type Output = u16;
fn index(&self, idx: usize) -> &u16 {
match idx {
0 => &self.width,
1 => &self.height,
_ => panic!("index out of bounds: the len is 2 but the index is {}", idx),
}
}
}
impl From<(u16, u16)> for Size {
fn from(other: (u16, u16)) -> Self {
Size::new(other.0, other.1)
}
}
impl From<[u16; 2]> for Size {
fn from(other: [u16; 2]) -> Self {
Size::new(other[0], other[1])
}
}
impl From<&[u16; 2]> for Size {
fn from(other: &[u16; 2]) -> Self {
Size::new(other[0], other[1])
}
}
impl From<Size> for (u16, u16) {
fn from(other: Size) -> (u16, u16) {
(other.width, other.height)
}
}
impl From<&Size> for (u16, u16) {
fn from(other: &Size) -> (u16, u16) {
(other.width, other.height)
}
}
#[cfg(feature = "nalgebra_support")]
use nalgebra::{base::Scalar, Vector2};
#[cfg(feature = "nalgebra_support")]
impl<N> From<Vector2<N>> for Size
where
N: Into<u16> + Scalar,
{
fn from(other: Vector2<N>) -> Self {
Self::new(other[0].into(), other[1].into())
}
}
#[cfg(feature = "nalgebra_support")]
impl<N> From<&Vector2<N>> for Size
where
N: Into<u16> + Scalar,
{
fn from(other: &Vector2<N>) -> Self {
Self::new(other[0].into(), other[1].into())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sizes_can_be_added() {
let left = Size::new(10, 20);
let right = Size::new(30, 40);
assert_eq!(left + right, Size::new(40, 60));
}
#[test]
fn sizes_can_be_subtracted() {
let left = Size::new(30, 40);
let right = Size::new(10, 20);
assert_eq!(left - right, Size::new(20, 20));
}
#[test]
fn from_tuple() {
assert_eq!(Size::from((20, 30)), Size::new(20, 30));
}
#[test]
fn from_array() {
assert_eq!(Size::from([20, 30]), Size::new(20, 30));
}
#[test]
fn from_array_ref() {
assert_eq!(Size::from(&[20, 30]), Size::new(20, 30));
}
#[test]
fn index() {
let size = Size::new(1, 2);
assert_eq!(size.width, size[0]);
assert_eq!(size.height, size[1]);
}
#[test]
#[should_panic]
fn index_out_of_bounds() {
let size = Size::new(1, 2);
let _ = size[2];
}
#[test]
#[cfg(feature = "nalgebra_support")]
fn nalgebra_support() {
let left = nalgebra::Vector2::new(30u16, 40);
let right = nalgebra::Vector2::new(10, 20);
assert_eq!(Size::from(left - right), Size::new(20, 20));
}
}
/// Style properties for an object
#[derive(Debug, Copy, Clone)]
pub struct Style {
/// Fill colour of the object
///
/// For fonts, this is the background colour of the text
pub fill_color: Option<PixelColor>,
/// Stroke (border/line) color of the object
///
/// For fonts, this is the foreground colour of the text
pub stroke_color: Option<PixelColor>,
/// Stroke width
///
/// Set the stroke width for an object. Has no effect on fonts.
pub stroke_width: i16,
}
impl Style
{
/// Create a new style with a given stroke value and defaults for everything else
pub fn stroke_color(stroke_color: PixelColor) -> Self {
Self {
stroke_color: Some(stroke_color),
..Style::default()
}
}
/// Returns the stroke width as an `i16`.
///
/// If the stroke width is too large to fit into an `i16` the maximum value
/// for an `i16` is returned instead.
pub(crate) fn stroke_width_i16(&self) -> i16 {
self.stroke_width
}
}
impl Default for Style
{
fn default() -> Self {
Self {
fill_color: None,
stroke_color: None,
stroke_width: 1,
}
}
}
/// Add a style to an object
pub trait WithStyle
{
/// Add a complete style to the object
fn style(self, style: Style) -> Self;
/// Set the stroke colour for the object
///
/// This can be a noop
fn stroke_color(self, color: Option<PixelColor>) -> Self;
/// Set the stroke width for the object
///
/// A stroke with a width of zero will not be rendered
fn stroke_width(self, width: u16) -> Self;
/// Set the fill property of the object's style
///
/// This can be a noop
fn fill_color(self, color: Option<PixelColor>) -> Self;
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Point {
pub x: u16,
pub y: u16,
pub x: i16,
pub y: i16,
}
impl Point {
pub fn new(x: u16, y: u16) -> Point {
pub fn new(x: i16, y: i16) -> Point {
Point { x, y }
}
/// Creates a point with X and Y equal to zero.
pub const fn zero() -> Self {
Point { x: 0, y: 0 }
}
}
impl Add for Point {
type Output = Point;
fn add(self, other: Point) -> Point {
Point::new(self.x + other.x, self.y + other.y)
}
}
impl Add<Size> for Point {
type Output = Point;
/// Offsets a point by adding a size.
///
/// # Panics
///
/// This function will panic if `width` or `height` are too large to be represented as an `i16`
/// and debug assertions are enabled.
fn add(self, other: Size) -> Point {
let width = other.width as i16;
let height = other.height as i16;
debug_assert!(width >= 0, "width is too large");
debug_assert!(height >= 0, "height is too large");
Point::new(self.x + width, self.y + height)
}
}
impl AddAssign for Point {
fn add_assign(&mut self, other: Point) {
self.x += other.x;
self.y += other.y;
}
}
impl AddAssign<Size> for Point {
/// Offsets a point by adding a size.
///
/// # Panics
///
/// This function will panic if `width` or `height` are too large to be represented as an `i16`
/// and debug assertions are enabled.
fn add_assign(&mut self, other: Size) {
let width = other.width as i16;
let height = other.height as i16;
debug_assert!(width >= 0, "width is too large");
debug_assert!(height >= 0, "height is too large");
self.x += width;
self.y += height;
}
}
impl Sub for Point {
type Output = Point;
fn sub(self, other: Point) -> Point {
Point::new(self.x - other.x, self.y - other.y)
}
}
impl Sub<Size> for Point {
type Output = Point;
/// Offsets a point by subtracting a size.
///
/// # Panics
///
/// This function will panic if `width` or `height` are too large to be represented as an `i16`
/// and debug assertions are enabled.
fn sub(self, other: Size) -> Point {
let width = other.width as i16;
let height = other.height as i16;
debug_assert!(width >= 0, "width is too large");
debug_assert!(height >= 0, "height is too large");
Point::new(self.x - width, self.y - height)
}
}
impl SubAssign for Point {
fn sub_assign(&mut self, other: Point) {
self.x -= other.x;
self.y -= other.y;
}
}
impl SubAssign<Size> for Point {
/// Offsets a point by subtracting a size.
///
/// # Panics
///
/// This function will panic if `width` or `height` are too large to be represented as an `i16`
/// and debug assertions are enabled.
fn sub_assign(&mut self, other: Size) {
let width = other.width as i16;
let height = other.height as i16;
debug_assert!(width >= 0, "width is too large");
debug_assert!(height >= 0, "height is too large");
self.x -= width;
self.y -= height;
}
}
impl Index<usize> for Point {
type Output = i16;
fn index(&self, idx: usize) -> &i16 {
match idx {
0 => &self.x,
1 => &self.y,
_ => panic!("index out of bounds: the len is 2 but the index is {}", idx),
}
}
}
impl Neg for Point {
type Output = Point;
fn neg(self) -> Self::Output {
Point::new(-self.x, -self.y)
}
}
impl From<(i16, i16)> for Point {
fn from(other: (i16, i16)) -> Self {
Point::new(other.0, other.1)
}
}
impl From<[i16; 2]> for Point {
fn from(other: [i16; 2]) -> Self {
Point::new(other[0], other[1])
}
}
impl From<&[i16; 2]> for Point {
fn from(other: &[i16; 2]) -> Self {
Point::new(other[0], other[1])
}
}
impl From<Point> for (i16, i16) {
fn from(other: Point) -> (i16, i16) {
(other.x, other.y)
}
}
impl From<&Point> for (i16, i16) {
fn from(other: &Point) -> (i16, i16) {
(other.x, other.y)
}
}
impl Into<usize> for Point {
@ -18,16 +500,20 @@ impl Into<usize> for Point {
}
}
/// A single pixel
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Pixel(pub Point, pub PixelColor);
#[derive(Copy, Clone, Debug)]
pub struct Rect {
pub x0: u16,
pub y0: u16,
pub x1: u16,
pub y1: u16,
pub x0: i16,
pub y0: i16,
pub x1: i16,
pub y1: i16,
}
impl Rect {
pub fn new(x0: u16, y0: u16, x1: u16, y1: u16) -> Self {
pub fn new(x0: i16, y0: i16, x1: i16, y1: i16) -> Self {
Self { x0, y0, x1, y1 }
}
}
@ -49,7 +535,7 @@ impl From<usize> for Point {
#[derive(Copy, Clone, Debug)]
pub struct Color {
pub color: u32,
pub color: u16,
}
impl From<usize> for Color {
@ -58,6 +544,18 @@ impl From<usize> for Color {
}
}
#[derive(Debug, Clone, Copy)]
pub struct Rectangle {
/// Top left point of the rect
pub top_left: Point,
/// Bottom right point of the rect
pub bottom_right: Point,
/// Object style
pub style: PixelColor,
}
#[derive(Debug)]
pub enum Opcode<'a> {
/// Flush the buffer to the screen
@ -73,11 +571,11 @@ pub enum Opcode<'a> {
Rectangle(Point /* upper-left */, Point /* lower-right */),
/// Draw a circle with a specified radius
Circle(Point, u32 /* radius */),
Circle(Point, u16 /* radius */),
/// Change the style of the current pen
Style(
u32, /* stroke width */
u16, /* stroke width */
Color, /* stroke color */
Color, /* fill color */
),

View file

@ -79,7 +79,7 @@ impl Uart {
pub fn enable_rx(&self) {
if cfg!(feature = "debugprint") {
let mut uart_csr = CSR::new(unsafe{DEFAULT_UART_ADDR as *mut u32});
uart_csr.wfo(utra::uart::EV_ENABLE_ENABLE, uart_csr.rf(utra::uart::EV_ENABLE_ENABLE) | 2 );
uart_csr.rmwf(utra::uart::EV_ENABLE_RX, 1);
}
}
@ -89,7 +89,7 @@ impl Uart {
self.map_uart();
}
let mut uart_csr = CSR::new(unsafe{DEFAULT_UART_ADDR as *mut u32});
match uart_csr.rf(utra::uart::EV_PENDING_PENDING) & 2 {
match uart_csr.rf(utra::uart::EV_PENDING_RX) {
0 => None,
ack => {
let c = Some(uart_csr.rf(utra::uart::RXTX_RXTX) as u8);

View file

@ -1,8 +1,11 @@
#![cfg_attr(target_os = "none", no_std)]
// pub mod size;
pub mod api;
pub use api::{Point, Color, Rect};
use xous::String;
pub mod op;
pub mod fonts;
use xous::{send_message, CID};
@ -10,7 +13,7 @@ pub fn draw_line(cid: CID, start: Point, end: Point) -> Result<(), xous::Error>
send_message(cid, api::Opcode::Line(start, end).into()).map(|_| ())
}
pub fn draw_circle(cid: CID, center: Point, radius: u32) -> Result<(), xous::Error> {
pub fn draw_circle(cid: CID, center: Point, radius: u16) -> Result<(), xous::Error> {
send_message(cid, api::Opcode::Circle(center, radius).into()).map(|_| ())
}
@ -18,7 +21,7 @@ pub fn draw_rectangle(cid: CID, start: Point, end: Point) -> Result<(), xous::Er
send_message(cid, api::Opcode::Rectangle(start, end).into()).map(|_| ())
}
pub fn set_style(cid: CID, width: u32, stroke: Color, fill: Color) -> Result<(), xous::Error> {
pub fn set_style(cid: CID, width: u16, stroke: Color, fill: Color) -> Result<(), xous::Error> {
send_message(cid, api::Opcode::Style(width, stroke, fill).into()).map(|_| ())
}

View file

@ -56,7 +56,6 @@ fn xmain() -> ! {
Opcode::Line(start, end) => {
info!("GFX: Drawing line from {:?} to {:?}", start, end);
op::line(display.native_buffer(), start.x as _, start.y as _, end.x as _, end.y as _, if current_color.color == 0 { op::PixelColor::Off } else {op::PixelColor::On });
// todo!();
}
Opcode::Rectangle(start, end) => {
todo!();
@ -66,11 +65,8 @@ fn xmain() -> ! {
// .ok();
}
Opcode::Circle(mid, radius) => {
todo!();
// Circle::new(mid.into(), radius)
// .into_styled(current_style)
// .draw(&mut display)
// .unwrap();
info!("GFX: Drawing cicrle at {:?} radius {:?}", mid, radius);
op::circle(display.native_buffer(), mid.x as _, mid.y as _, radius as _, 0, op::PixelColor::On);
}
Opcode::Style(stroke_width, stroke_color, fill_color) => {
current_color = stroke_color;

View file

@ -1,5 +1,6 @@
use super::fonts;
use super::fonts::{Font, GlyphHeader};
use crate::api::{Point, Style, Pixel};
/// LCD Frame buffer bounds
pub const LCD_WORDS_PER_LINE: usize = 11;
@ -10,7 +11,7 @@ pub const LCD_FRAME_BUF_SIZE: usize = LCD_WORDS_PER_LINE * LCD_LINES;
const WIDTH: usize = 336;
const HEIGHT: usize = 536;
#[derive(Copy, Clone, PartialEq)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum PixelColor {
On,
Off,
@ -338,6 +339,86 @@ pub fn line(fb: &mut LcdFB, x0: usize, y0: usize, x1: usize, y1: usize, color: P
}
}
/// Pixel iterator for each pixel in the circle border
#[derive(Debug, Copy, Clone)]
pub struct CircleIterator {
center: Point,
radius: u16,
style: Style,
p: Point,
}
impl Iterator for CircleIterator
{
type Item = Pixel;
// https://stackoverflow.com/questions/1201200/fast-algorithm-for-drawing-filled-circles
fn next(&mut self) -> Option<Self::Item> {
// If border or stroke colour is `None`, treat entire object as transparent and exit early
if self.style.stroke_color.is_none() && self.style.fill_color.is_none() {
return None;
}
let radius = self.radius as i16 - self.style.stroke_width_i16() + 1;
let outer_radius = self.radius as i16;
let radius_sq = radius * radius;
let outer_radius_sq = outer_radius * outer_radius;
loop {
let t = self.p;
let len = t.x * t.x + t.y * t.y;
let is_border = len > radius_sq - radius && len < outer_radius_sq + radius;
let is_fill = len <= outer_radius_sq + 1;
let item = if is_border && self.style.stroke_color.is_some() {
Some(Pixel(
self.center + t,
self.style.stroke_color.expect("Border color not defined"),
))
} else if is_fill && self.style.fill_color.is_some() {
Some(Pixel(
self.center + t,
self.style.fill_color.expect("Fill color not defined"),
))
} else {
None
};
self.p.x += 1;
if self.p.x > self.radius as i16 {
self.p.x = -(self.radius as i16);
self.p.y += 1;
}
if self.p.y > self.radius as i16 {
break None;
}
if item.is_some() {
break item;
}
}
}
}
pub fn circle(fb: &mut LcdFB, x: usize, y: usize, r: usize, stroke_width: usize, color: PixelColor) {
let c = CircleIterator {
center: Point{x: x as i16, y: y as i16},
radius: r as u16,
style: Style{ fill_color: Some(color), stroke_color: Some(color), stroke_width: stroke_width as i16},
p: Point::new(-(r as i16), -(r as i16)),
};
for pixel in c {
put_pixel(fb, pixel.0.x as usize, pixel.0.y as usize, pixel.1);
}
}
#[cfg(test)]
mod tests {
use super::fonts;

View file

@ -76,7 +76,7 @@ impl Uart {
pub fn enable_rx(&self) {
let mut uart_csr = CSR::new(unsafe{DEFAULT_UART_ADDR as *mut u32});
uart_csr.wfo(utra::uart::EV_ENABLE_ENABLE, uart_csr.rf(utra::uart::EV_ENABLE_ENABLE) | 2 );
uart_csr.rmwf(utra::uart::EV_ENABLE_RX, 1 );
}
pub fn getc(&self) -> Option<u8> {
@ -84,7 +84,7 @@ impl Uart {
self.map_uart();
}
let mut uart_csr = CSR::new(unsafe{DEFAULT_UART_ADDR as *mut u32});
match uart_csr.rf(utra::uart::EV_PENDING_PENDING) & 2 {
match uart_csr.rf(utra::uart::EV_PENDING_RX) {
0 => None,
ack => {
let c = Some(uart_csr.rf(utra::uart::RXTX_RXTX) as u8);

View file

@ -79,7 +79,7 @@ impl Uart {
pub fn enable_rx(&self) {
if cfg!(feature = "debugprint") {
let mut uart_csr = CSR::new(unsafe{DEFAULT_UART_ADDR as *mut u32});
uart_csr.wfo(utra::uart::EV_ENABLE_ENABLE, uart_csr.rf(utra::uart::EV_ENABLE_ENABLE) | 2 );
uart_csr.rmwf(utra::uart::EV_ENABLE_RX, 1 );
}
}
@ -89,7 +89,7 @@ impl Uart {
self.map_uart();
}
let mut uart_csr = CSR::new(unsafe{DEFAULT_UART_ADDR as *mut u32});
match uart_csr.rf(utra::uart::EV_PENDING_PENDING) & 2 {
match uart_csr.rf(utra::uart::EV_PENDING_RX) {
0 => None,
ack => {
let c = Some(uart_csr.rf(utra::uart::RXTX_RXTX) as u8);

View file

@ -10,6 +10,7 @@ mod timer;
use core::fmt::Write;
use log::{error, info};
use xous::String;
use graphics_server::Point;
// fn print_and_yield(index: *mut usize) -> ! {
// let num = index as usize;
@ -19,6 +20,29 @@ use xous::String;
// }
// }
#[derive(Debug, Clone, Copy)]
pub struct Rectangle {
/// Top left point of the rect
pub top_left: Point,
/// Bottom right point of the rect
pub bottom_right: Point,
}
impl Rectangle {
pub fn top_left(&self) -> Point {
self.top_left
}
pub fn bottom_right(&self) -> Point {
self.bottom_right
}
pub fn new(top_left: Point, bottom_right: Point) -> Self {
Rectangle {
top_left,
bottom_right,
}
}
}
#[cfg(baremetal)]
use utralib::generated::*;
@ -38,11 +62,72 @@ fn ensure_connection(server: xous::SID) -> xous::CID {
}
}
pub struct Bounce {
vector: Point,
radius: u16,
bounds: Rectangle,
loc: Point,
lfsr: u32,
}
impl Bounce {
pub fn new(radius: u16, bounds: Rectangle) -> Bounce {
Bounce {
vector: Point::new(2,3),
radius: radius,
bounds: bounds,
loc: Point::new((bounds.bottom_right.x - bounds.top_left.x)/2, (bounds.bottom_right.y - bounds.top_left.y)/2),
lfsr: 0xace1u32,
}
}
pub fn next_rand(&mut self) -> i16 {
let ret = move_lfsr(self.lfsr);
self.lfsr = ret;
(ret % 8) as i16
}
pub fn update(&mut self) -> &mut Self {
let mut x: i16;
let mut y: i16;
// update the new ball location
x = self.loc.x + self.vector.x; y = self.loc.y + self.vector.y;
let r: i16 = self.radius as i16;
if (x >= (self.bounds.bottom_right().x - r)) ||
(x <= (self.bounds.top_left().x + r)) ||
(y >= (self.bounds.bottom_right().y - r)) ||
(y <= (self.bounds.top_left().y + r)) {
if x >= (self.bounds.bottom_right().x - r - 1) {
self.vector.x = -self.next_rand();
x = self.bounds.bottom_right().x - r;
}
if x <= self.bounds.top_left().x + r + 1 {
self.vector.x = self.next_rand();
x = self.bounds.top_left().x + r;
}
if y >= (self.bounds.bottom_right().y - r - 1) {
self.vector.y = -self.next_rand();
y = self.bounds.bottom_right().y - r;
}
if y <= (self.bounds.top_left().y + r + 1) {
self.vector.y = self.next_rand();
y = self.bounds.top_left().y + r;
}
}
self.loc.x = x;
self.loc.y = y;
self
}
}
#[xous::xous_main]
fn shell_main() -> ! {
timer::init();
log_server::init_wait().unwrap();
let mut loops = 0;
// let log_server_id = xous::SID::from_bytes(b"xous-logs-output").unwrap();
let graphics_server_id = xous::SID::from_bytes(b"graphics-server ").unwrap();
@ -71,9 +156,12 @@ fn shell_main() -> ! {
// let mut counter: usize = 0;
let mut ls = logstr::LogStr::new();
let mut lfsr = 0xace1u32;
let dark = graphics_server::Color::from(0);
let light = graphics_server::Color::from(!0);
let mut bouncyball = Bounce::new(14,
Rectangle::new(Point::new(0, 18 * 21),
Point::new(336, 536-1))); // TODO: make API call to get screen size
bouncyball.update();
#[cfg(baremetal)]
{
@ -88,6 +176,14 @@ fn shell_main() -> ! {
gpio.wfo(utra::gpio::UARTSEL_UARTSEL, 2);
}
graphics_server::set_style(
graphics_conn,
1,
dark,
dark,
)
.expect("unable to draw to screen: {:?}");
let mut last_time: u64 = 0;
let mut string_buffer = String::new(4096);
loop {
@ -123,36 +219,28 @@ fn shell_main() -> ! {
error!("error requesting ticktimer!")
}
graphics_server::set_style(
graphics_conn,
5,
if lfsr & 1 == 0 { dark } else { light },
if lfsr & 1 == 0 { dark } else { light },
)
.expect("unable to draw to screen: {:?}");
let x1 = move_lfsr(lfsr);
let y1 = move_lfsr(x1);
let x2 = move_lfsr(y1);
let y2 = move_lfsr(x2);
lfsr = y2;
graphics_server::draw_line(
graphics_conn,
graphics_server::Point::new((x1 % 336) as _, (y1 % 536) as _),
graphics_server::Point::new((x2 % 336) as _, (y2 % 536) as _),
)
.expect("unable to draw to screen");
string_buffer.clear();
write!(&mut string_buffer, "Elapsed time: {}ms", last_time).expect("Can't write");
graphics_server::clear_region(graphics_conn, 0, 0, 300, 40)
.expect("unable to clear region");
info!("drawing string: {}", string_buffer);
graphics_server::draw_string(graphics_conn, &string_buffer).expect("unable to draw string");
graphics_server::flush(graphics_conn).expect("unable to draw to screen");
ticktimer_server::sleep_ms(ticktimer_conn, 2000 + loops).expect("couldn't sleep");
loops += 1;
// ticktimer_server::sleep_ms(ticktimer_conn, 2000).expect("couldn't sleep");
// draw the ball
bouncyball.update();
graphics_server::clear_region(graphics_conn,
bouncyball.bounds.top_left().x as _, bouncyball.bounds.top_left().y as _,
bouncyball.bounds.bottom_right().x as _, bouncyball.bounds.bottom_right().y as usize + 1)
.expect("unable to clear region");
graphics_server::draw_circle(
graphics_conn,
bouncyball.loc,
bouncyball.radius as u16,
)
.expect("unable to draw to screen");
graphics_server::flush(graphics_conn).expect("unable to draw to screen");
}
}

View file

@ -14,7 +14,7 @@ fn timer_tick(_irq_no: usize, _arg: *mut usize) {
xous::rsyscall(xous::SysCall::ReturnToParent(xous::PID::new(1).unwrap(), 0)).expect("couldn't return to parent");
// acknowledge the timer
timer.wfo(utra::timer0::EV_PENDING_PENDING, 0b1);
timer.wfo(utra::timer0::EV_PENDING_ZERO, 0b1);
//println!("<<< Returning from timer_tick()");
}
@ -45,7 +45,7 @@ pub fn init() {
// Set EV_ENABLE
let mut timer = CSR::new(TIMER_BASE as *mut u32);
timer.wfo(utra::timer0::EV_ENABLE_ENABLE, 0b1);
timer.wfo(utra::timer0::EV_ENABLE_ZERO, 0b1);
}
#[cfg(not(baremetal))]

View file

@ -79,7 +79,7 @@ impl Uart {
pub fn enable_rx(&self) {
if cfg!(feature = "debugprint") {
let mut uart_csr = CSR::new(unsafe{DEFAULT_UART_ADDR as *mut u32});
uart_csr.wfo(utra::uart::EV_ENABLE_ENABLE, uart_csr.rf(utra::uart::EV_ENABLE_ENABLE) | 2 );
uart_csr.rmwf(utra::uart::EV_ENABLE_RX, 1);
}
}
@ -89,7 +89,7 @@ impl Uart {
self.map_uart();
}
let mut uart_csr = CSR::new(unsafe{DEFAULT_UART_ADDR as *mut u32});
match uart_csr.rf(utra::uart::EV_PENDING_PENDING) & 2 {
match uart_csr.rf(utra::uart::EV_PENDING_RX) {
0 => None,
ack => {
let c = Some(uart_csr.rf(utra::uart::RXTX_RXTX) as u8);

File diff suppressed because it is too large Load diff