X-Git-Url: http://git.code-monkey.de/?a=blobdiff_plain;f=src%2Fcommon%2Flogger.rs;h=2154a01b7fd901fb24e2d68e900d3d44099449b2;hb=9b597c27de391182ec515bc125451933d5340067;hp=be0632792af1177fab3c40993f1228486cd5ce61;hpb=9bc6fc2996255514e0d49e3da0655e2f93f14d8c;p=gps-watch.git diff --git a/src/common/logger.rs b/src/common/logger.rs index be06327..2154a01 100644 --- a/src/common/logger.rs +++ b/src/common/logger.rs @@ -25,12 +25,20 @@ use gps::TimeAndPos; use storage::Storage; use varint; use systick::elapsed_ms; +use buffer::Buffer; +use yencode::Yencode; +use fmt::*; pub const MEMORY_SIZE: usize = 2 << 20; const SECTOR_SIZE: usize = 4 << 10; const NUM_SECTORS: usize = MEMORY_SIZE / SECTOR_SIZE; +#[derive(Clone, Copy, PartialEq, Debug)] +pub enum Error { + NoSuchRecording, +} + enum SectorFlag { InUse = 1 << 0, DataRecord = 1 << 1, @@ -72,6 +80,10 @@ impl SectorHeader { (self.flags & mask) == value } + + fn belongs_to(&self, recording_id: u16) -> bool { + self.is_in_use() && self.recording_id == recording_id + } } #[derive(Clone, Copy)] @@ -92,7 +104,7 @@ impl InFlight { } pub struct Logger<'a> { - storage: &'a mut dyn Storage, + pub storage: &'a mut dyn Storage, recording_id: u16, // Zero is considered invalid. @@ -323,19 +335,23 @@ impl<'a> Logger<'a> { // Reading the directory entries one by one means // we won't need an as large buffer on the stack. for i in 0..NUM_SECTORS { - let address = i * SECTOR_SIZE; - let mut chunk = [0u8; 4]; + self.read_sector_header(i); + } + } - self.storage.read(address, &mut chunk); + fn read_sector_header(&mut self, sector_index: usize) { + let address = sector_index * SECTOR_SIZE; + let mut chunk = [0u8; 4]; - let sector_header_ptr: *mut SectorHeader = - &mut self.sector_header[i]; + self.storage.read(address, &mut chunk); - unsafe { - core::ptr::copy(chunk.as_ptr(), - sector_header_ptr as *mut u8, - chunk.len()); - } + let sector_header_ptr: *mut SectorHeader = + &mut self.sector_header[sector_index]; + + unsafe { + core::ptr::copy(chunk.as_ptr(), + sector_header_ptr as *mut u8, + chunk.len()); } } @@ -417,7 +433,13 @@ impl<'a> Logger<'a> { self.storage.write(this_sector as usize * SECTOR_SIZE, &self.write_buffer); - self.sectors_written + 1 + self.sectors_written += 1; + + for i in 0..self.sectors_written { + self.read_sector_header((self.first_sector + i) as usize); + } + + self.sectors_written } fn sector_header_iter(&self) -> SectorHeaderIter { @@ -547,4 +569,61 @@ impl<'a> Logger<'a> { self.write_buffer_offset += num_bytes_written; } + + /// + /// Retrieve recording @p recording_id and + /// write it to @p tx_buf in yencoded form. + pub fn get_recording(&mut self, recording_id: u16, + tx_buf: &mut Buffer) -> Result<(), Error> { + if recording_id == 0 { + return Err(Error::NoSuchRecording); + } + + if let Some(found_index) = self.sector_header_iter().find(|&index| { + let sector_header = &self.sector_header[index as usize]; + + sector_header.recording_id == recording_id && + sector_header.starts_recording() + }) { + let mut filename = [b' '; 29]; + + filename[0..].copy_from_slice(b"gps-watch-recording-XXXXX.bin"); + + fmt_u32_pad(&mut filename[20..], recording_id as u32, 5, b'0'); + + let mut yenc = Yencode::new(tx_buf); + + yenc.start(&filename); + + let format_version = 1u8; + yenc.data(&[format_version]); + + let mut next_sector = found_index as usize; + + for _ in 0..NUM_SECTORS { + let address = next_sector * SECTOR_SIZE; + let mut buf = [0u8; SECTOR_SIZE]; + + self.storage.read(address, &mut buf); + + // Skip flags and recording ID. + yenc.data(&buf[4..]); + + next_sector += 1; + next_sector &= NUM_SECTORS - 1; + + if !self.sector_header[next_sector].belongs_to(recording_id) { + break; + } + } + + yenc.finish(); + + tx_buf.flush(); + + Ok(()) + } else { + Err(Error::NoSuchRecording) + } + } }