Chapter 5 WIP
authorGreg Burri <greg.burri@gmail.com>
Tue, 3 Aug 2021 09:16:21 +0000 (11:16 +0200)
committerGreg Burri <greg.burri@gmail.com>
Tue, 3 Aug 2021 09:16:21 +0000 (11:16 +0200)
ch3-cubsat-ground-station/src/main.rs
ch5-data-in-depth/Cargo.lock [new file with mode: 0644]
ch5-data-in-depth/Cargo.toml [new file with mode: 0644]
ch5-data-in-depth/src/chip8.rs [new file with mode: 0644]
ch5-data-in-depth/src/decode_f32.rs [new file with mode: 0644]
ch5-data-in-depth/src/main.rs [new file with mode: 0644]
ch5-data-in-depth/src/q7.rs [new file with mode: 0644]

index b456ff8..7334bf0 100644 (file)
@@ -1,32 +1,42 @@
 #![cfg_attr(debug_assertions, allow(unused_variables, dead_code))]
 
+use std::cell::RefCell;
+use std::rc::Rc;
+
+type Message = String;
+
 #[derive(Debug)]
 enum StatusMessage {
     Ok,
 }
 
+#[derive(Debug)]
+struct Mailbox {
+    messages: Vec<Message>,
+}
+
 #[derive(Debug)]
 struct CubeSat {
     id: u64,
+    mailbox: Mailbox,
 }
 
-fn check_status(sat_id: CubeSat) -> StatusMessage {
+#[derive(Debug)]
+struct GroundStation {
+    radio_freq: f64 // [MHz].
+}
+
+fn check_status(sat_id: &CubeSat) -> StatusMessage {
     StatusMessage::Ok
 }
 
 fn main() {
-    let sat_a = CubeSat { id: 0 };
-    let sat_b = CubeSat { id: 1 };
-    let sat_c = CubeSat { id: 2 };
-
-    let a_status = check_status(sat_a);
-    let b_status = check_status(sat_b);
-    let c_status = check_status(sat_c);
-    println!("a: {:?}, b: {:?}, c: {:?}", a_status, b_status, c_status);
-
+    let base: Rc<RefCell<GroundStation>> =
+        Rc::new(
+            RefCell::new(
+                GroundStation { radio_freq: 42.1 }
+            )
+        );
 
-    let a_status = check_status(sat_a);
-    let b_status = check_status(sat_b);
-    let c_status = check_status(sat_c);
-    println!("a: {:?}, b: {:?}, c: {:?}", a_status, b_status, c_status);
+    println!("base: {:?}", base);
 }
diff --git a/ch5-data-in-depth/Cargo.lock b/ch5-data-in-depth/Cargo.lock
new file mode 100644 (file)
index 0000000..33c8410
--- /dev/null
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "ch5-data-in-depth"
+version = "0.1.0"
diff --git a/ch5-data-in-depth/Cargo.toml b/ch5-data-in-depth/Cargo.toml
new file mode 100644 (file)
index 0000000..3d2628b
--- /dev/null
@@ -0,0 +1,8 @@
+[package]
+name = "ch5-data-in-depth"
+version = "0.1.0"
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/ch5-data-in-depth/src/chip8.rs b/ch5-data-in-depth/src/chip8.rs
new file mode 100644 (file)
index 0000000..0a36044
--- /dev/null
@@ -0,0 +1,7 @@
+
+
+struct CPU {
+    current_operation: u16,
+    registers: [u8; 2],
+}
+
diff --git a/ch5-data-in-depth/src/decode_f32.rs b/ch5-data-in-depth/src/decode_f32.rs
new file mode 100644 (file)
index 0000000..74bb478
--- /dev/null
@@ -0,0 +1,50 @@
+const BIAS: i32 = 127;
+const RADIX: f32 = 2.0;
+
+pub fn print_f32(n: f32) {
+    let (sign, exp, frac) = to_parts(n);
+    let (sign_, exp_, mant) = decode(sign, exp, frac);
+    let n_ = from_parts(sign_, exp_, mant);
+
+    println!("{} -> {}", n, n_);
+    println!("field    |  as bits | as real number");
+    println!("sign     |        {:01b} | {}", sign, sign_);
+    println!("exponent | {:08b} | {}", exp, exp_);
+    println!("mantissa | {:023b} | {}", frac, mant);
+}
+
+fn to_parts(n: f32) -> (u32, u32, u32) {
+    let bits = n.to_bits();
+
+    let sign = (bits >> 31) & 1;
+    let exponent = (bits >> 23) & 0xFF;
+    let fraction = bits & 0x7F_FF_FF;
+
+    (sign, exponent, fraction)
+}
+
+fn decode(sign: u32, exponent: u32, fraction: u32) -> (f32, f32, f32) {
+    let signed_1 = (-1.0f32).powf(sign as f32);
+
+    let exponent = RADIX.powf(((exponent as i32) - BIAS) as f32);
+
+    let mut mantissa: f32 = 1.0;
+
+    // Mantissa is a sum of 1 + 2^(-1) + 2^(-2) + .. + 2^(-23)
+    for i in 0..23 {
+        let mask = 1 << i;
+        let one_at_bit_i = fraction & mask;
+        if one_at_bit_i != 0 {
+            let i_ = i as f32;
+            let weight = 2_f32.powf(i_ - 23.0);
+            mantissa += weight;
+        }
+    }
+
+    (signed_1, exponent, mantissa)
+}
+
+fn from_parts(sign: f32, exponent: f32, mantissa: f32) -> f32 {
+    sign * exponent * mantissa
+}
+
diff --git a/ch5-data-in-depth/src/main.rs b/ch5-data-in-depth/src/main.rs
new file mode 100644 (file)
index 0000000..7f26aeb
--- /dev/null
@@ -0,0 +1,26 @@
+#![cfg_attr(debug_assertions, allow(dead_code, unused_imports))]
+
+mod decode_f32;
+mod q7;
+mod chip8;
+
+use q7::Q7;
+
+fn test_decode_f32() {
+    let n: f32 = 42.42;
+    decode_f32::print_f32(n);
+}
+
+fn test_q7() {
+    println!("{:?}", Q7::from(0.3))
+}
+
+fn test_chip() {
+
+}
+
+fn main() {
+    // test_decode_f32();
+    // test_q7();
+    test_chip();
+}
diff --git a/ch5-data-in-depth/src/q7.rs b/ch5-data-in-depth/src/q7.rs
new file mode 100644 (file)
index 0000000..63ad0dc
--- /dev/null
@@ -0,0 +1,43 @@
+/// A type to encode a range from -1 to 1 into 8 bits.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct Q7(i8);
+
+impl From<f64> for Q7 {
+    fn from(n: f64) -> Self {
+        if n >= 1.0 {
+            Q7(127)
+        } else if n <= -1.0 {
+            Q7(-128)
+        } else {
+            Q7((n * 128.0) as i8)
+        }
+    }
+}
+
+impl From<Q7> for f64 {
+    fn from(n: Q7) -> Self {
+        (n.0 as f64) * 2f64.powf(-7.0) // Same as / 128.0.
+    }
+}
+
+impl From<f32> for Q7 {
+    fn from(n: f32) -> Self {
+        Q7::from(n as f64)
+    }
+}
+
+impl From<Q7> for f32 {
+    fn from(n: Q7) -> Self {
+        f64::from(n) as f32
+    }
+}
+
+mod tests {
+    use super::*;
+
+    #[test]
+    fn simple_case() {
+        let a = 0.45;
+        assert_eq!(a, (f64::from(Q7::from(a)) * 100.0).round() / 100.0);
+    }
+}
\ No newline at end of file