diff options
author | Oxore <oxore@protonmail.com> | 2020-03-04 03:17:25 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2020-03-04 03:19:16 +0300 |
commit | 7d4dfd8af842796c4eb8a88df0cc5ab30f99232d (patch) | |
tree | 826f7b9453aa30ab18de73f97b18a6bb83b70734 /src/progmem.rs | |
parent | 0a6fad82f83d7a79aa7eadf73a21e6e80c8e810d (diff) |
Rename Core to Cpu8051 and Ram to ProgramMemory, etc.
Adjust Readme.md
Diffstat (limited to 'src/progmem.rs')
-rw-r--r-- | src/progmem.rs | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/progmem.rs b/src/progmem.rs new file mode 100644 index 0000000..325eab1 --- /dev/null +++ b/src/progmem.rs @@ -0,0 +1,136 @@ +use crate::memory::Memory; +use std::fmt; + +pub struct ProgramMemory { + array: [u8; u16::max_value() as usize + 1], +} + +impl fmt::Debug for ProgramMemory { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut v: Vec<char> = vec![]; + for (c, x) in self.array.iter().enumerate() { + for hex_char in format!("{:02X}", *x).chars() { + v.push(hex_char); + } + v.push(' '); + if c % 8 == 7 { + v.push('\n'); + } + } + write!(f, "{}", v.iter().collect::<String>()) + } +} + +enum Rectyp { + Data, + EndOfFile, + //ExtendedSegAddr, + //StartSegAddr, + //ExtendedLinearAddr, + //StartLinearAddr, +} + +struct HexLine { + rectyp: Rectyp, + offset: u16, + data: Vec<u8>, +} + +impl HexLine { + fn from(s: &str) -> Result<Self, usize> { + // The shortest possible sequence is EOF (:00000001FF) + if s.len() < 11 { + return Err(usize::max_value()); + } + if &s[0..1] != ":" { + return Err(0); + } + let offset = match u16::from_str_radix(&s[3..7], 16) { + Ok(value) => value, + Err(_) => return Err(3), + }; + let bytecount = match usize::from_str_radix(&s[1..3], 16) { + Ok(value) => value, + Err(_) => return Err(1), + }; + + // If EOF reached + if &s[7..9] == "01" { + return Ok(HexLine { + rectyp: Rectyp::EndOfFile, + offset, + data: vec![0], + }); + } else if &s[7..9] == "00" { + let mut counter = 9; + let mut data = vec![]; + while counter < s.len() - 2 && counter < (9 + bytecount * 2) { + data.push(match u8::from_str_radix(&s[counter..counter + 2], 16) { + Ok(value) => value, + Err(_) => return Err(counter), + }); + counter += 2; + } + // TODO: check checksum + return Ok(HexLine { + rectyp: Rectyp::Data, + offset, + data, + }); + } + + Err(3) + } +} + +impl ProgramMemory { + /// Empty constructor + pub fn new() -> Self { + Self { + array: [0; u16::max_value() as usize + 1], + } + } + + /// Constructor from hex + pub fn from_hex(hex: String) -> Result<Self, String> { + Self::new().hex(hex) + } + + /// Method for sequential consuming building + pub fn hex(mut self, hex: String) -> Result<Self, String> { + match self.load_hex(hex) { + Ok(_) => Ok(self), + Err(string) => Err(string), + } + } + + /// Method for occasional incremental hex loading + pub fn load_hex(&mut self, hex: String) -> Result<(), String> { + for (linenum, line) in hex.lines().enumerate() { + let hex_line = match HexLine::from(line) { + Ok(value) => value, + Err(charnum) => return Err(format!("ihex parsing error {}:{}", linenum, charnum)), + }; + let offset = hex_line.offset; + match hex_line.rectyp { + Rectyp::Data => { + for (ptr, byte) in hex_line.data.iter().enumerate() { + self.array[ptr + offset as usize] = *byte; + } + } + Rectyp::EndOfFile => {} + } + } + Ok(()) + } +} + +impl Memory<u16> for ProgramMemory { + fn get(&self, a: u16) -> u8 { + self.array[a as usize] + } + + fn set(&mut self, a: u16, v: u8) { + self.array[a as usize] = v; + } +} |