common: Make Gps::update() access UART0's receive buffer via a closure.
[gps-watch.git] / src / common / gps.rs
index b9fcbc3f23d9a732676082fbc3cccac4d2535310..178e55198879edffbd1fb2dec11947579320daa6 100644 (file)
@@ -21,7 +21,6 @@
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-use ringbuf::Ringbuf;
 use systick;
 
 enum ParseState {
@@ -63,20 +62,6 @@ fn to_lower(c: u8) -> u8 {
     c | 0x20
 }
 
-fn try_read() -> Option<u8> {
-    extern {
-        static mut uart0_rx_buf: Ringbuf;
-    }
-
-    unsafe {
-        if uart0_rx_buf.is_empty() {
-            None
-        } else {
-            Some(uart0_rx_buf.read())
-        }
-    }
-}
-
 fn parse_coordinate(s: &[u8]) -> i32 {
     // Find the position of the decimal separator for the minutes.
     let dot_position = s.iter().enumerate().find(|(_, &c)| {
@@ -205,17 +190,23 @@ impl Gps {
         }
     }
 
-    pub fn update(&mut self, tap: &mut TimeAndPos) -> bool {
+    pub fn update<F>(&mut self, tap: &mut TimeAndPos, mut read_func: F) -> bool
+                     where F: FnMut() -> Option<u8>
+    {
         let hexdigits = b"0123456789abcdef";
 
-        while let Some(received) = try_read() {
+        while let Some(received) = read_func() {
+            if received == b'$' {
+                self.state = ParseState::InPacket;
+                self.offset = 0;
+                self.checksum = 0x00;
+
+                continue;
+            }
+
             match self.state {
                 ParseState::Start => {
-                    if received == b'$' {
-                        self.state = ParseState::InPacket;
-                        self.offset = 0;
-                        self.checksum = 0x00;
-                    }
+                    // Empty.
                 },
                 ParseState::InPacket => {
                     if received == b'*' {
@@ -343,8 +334,16 @@ impl Gps {
                     return false;
                 }
 
-                if pos_fix_indicator != b"1" {
-                    return false;
+                match pos_fix_indicator {
+                    b"1" => {
+                        // Valid standard GPS fix (low resolution).
+                    },
+                    b"2" => {
+                        // Valid differential GPS fix (high resolution).
+                    },
+                    _ => {
+                        return false;
+                    }
                 }
 
                 if utc_time.len() < 6 {