Skip to content

Commit 6252024

Browse files
committed
Add hexdump demo.
1 parent a680354 commit 6252024

File tree

6 files changed

+151
-3
lines changed

6 files changed

+151
-3
lines changed

samples/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
members = [
33
"fault",
44
"hello",
5+
"hexdump",
56
"input-test",
67
"panic",
78
]

samples/build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pushd asmhello
3232
./build.sh ${TARGET}
3333
popd
3434

35-
for program in panic hello fault input-test; do
35+
for program in panic hello fault input-test hexdump; do
3636
cp ./target/${TARGET}/release/${program} ./release/${program}.elf
3737
done
3838
cp ./asmhello/asmhello.elf ./release

samples/hexdump/Cargo.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "hexdump"
3+
version = "0.1.0"
4+
edition = "2021"
5+
license = "MIT OR Apache-2.0"
6+
authors = ["Jonathan 'theJPster' Pallant <[email protected]>"]
7+
description = "Prints information about files"
8+
9+
[dependencies]
10+
neotron-sdk = { path = "../.." }
11+
12+
# See workspace for profile settings

samples/hexdump/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Hexdump
2+
3+
A basic file printing tool for Neotron systems. This program takes an argument
4+
which is assumed to be a filename. That file is opened, and printed out as hex.
5+
The output is similar to the UNIX command `hexdump -C`.
6+
7+
See the general sample application [README](../README.md) for compilation instructions.
8+
9+
## Licence
10+
11+
Copyright (c) The Neotron Developers, 2024
12+
13+
Licensed under either [MIT](../../LICENSE-MIT) or [Apache-2.0](../../LICENSE-APACHE) at
14+
your option.
15+
16+
## Contribution
17+
18+
Unless you explicitly state otherwise, any contribution intentionally submitted
19+
for inclusion in the work by you shall be licensed as above, without any
20+
additional terms or conditions.

samples/hexdump/src/main.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#![cfg_attr(target_os = "none", no_std)]
2+
#![cfg_attr(target_os = "none", no_main)]
3+
4+
use core::fmt::Write;
5+
6+
#[cfg(not(target_os = "none"))]
7+
fn main() {
8+
neotron_sdk::init();
9+
}
10+
11+
#[no_mangle]
12+
extern "C" fn neotron_main() -> i32 {
13+
if let Err(e) = real_main() {
14+
let mut stdout = neotron_sdk::stdout();
15+
let _ = writeln!(stdout, "Error: {:?}", e);
16+
1
17+
} else {
18+
0
19+
}
20+
}
21+
22+
fn real_main() -> Result<(), neotron_sdk::Error> {
23+
let mut stdout = neotron_sdk::stdout();
24+
let Some(filename) = neotron_sdk::arg(0) else {
25+
return Err(neotron_sdk::Error::InvalidArg);
26+
};
27+
let _ = writeln!(stdout, "Dumping {:?}...", filename);
28+
let path = neotron_sdk::path::Path::new(&filename)?;
29+
let f = neotron_sdk::File::open(path, neotron_sdk::Flags::empty())?;
30+
let stat = f.stat()?;
31+
let mut bytes_remaining = stat.file_size;
32+
let _ = writeln!(stdout, "File is {} bytes", bytes_remaining);
33+
34+
let mut lines_remaining = 24;
35+
let mut buffer = [0u8; 16];
36+
let mut addr = 0;
37+
while bytes_remaining > 0 {
38+
let this_time = f.read(&mut buffer)?;
39+
let valid = &buffer[0..this_time];
40+
// print address
41+
let _ = write!(stdout, "{:08x}: ", addr);
42+
// print bytes (with padding)
43+
for b in valid {
44+
let _ = write!(stdout, "{:02x} ", b);
45+
}
46+
for _padding in 0..(buffer.len() - valid.len()) {
47+
let _ = write!(stdout, ".. ");
48+
}
49+
let _ = write!(stdout, "| ");
50+
// print ascii (with padding)
51+
for b in valid {
52+
let ch = *b as char;
53+
let _ = write!(stdout, "{}", if !ch.is_control() { ch } else { '?' });
54+
}
55+
for _padding in 0..(buffer.len() - valid.len()) {
56+
let _ = write!(stdout, ".");
57+
}
58+
let _ = writeln!(stdout, "|");
59+
addr += this_time;
60+
bytes_remaining = bytes_remaining.saturating_sub(this_time as u64);
61+
if lines_remaining == 0 {
62+
if neotron_sdk::wait_for_key() == neotron_sdk::WaitForKey::Quit {
63+
break;
64+
}
65+
lines_remaining = 25;
66+
} else {
67+
lines_remaining -= 1;
68+
}
69+
}
70+
71+
Ok(())
72+
}

src/lib.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use core::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
1212

1313
pub use neotron_ffi::{FfiBuffer, FfiByteSlice, FfiString};
1414

15-
pub use neotron_api::{path, Api, Error};
15+
pub use neotron_api::{file::Flags, path, Api, Error};
1616

1717
use neotron_api as api;
1818

@@ -216,7 +216,7 @@ impl Drop for File {
216216
// don't close
217217
} else {
218218
// close it
219-
let _ = (api.close)(self.0);
219+
let _ = (api.close)(self.0);
220220
}
221221
}
222222
}
@@ -372,6 +372,49 @@ pub fn delay(period: core::time::Duration) {
372372
std::thread::sleep(period);
373373
}
374374

375+
/// The result of a *Wait for Key* operation.
376+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
377+
pub enum WaitForKey {
378+
/// User wants more data
379+
More,
380+
/// User wants to quit
381+
Quit,
382+
}
383+
384+
/// Wait for a key
385+
pub fn wait_for_key() -> WaitForKey {
386+
use core::fmt::Write;
387+
let mut ticker = "|/-\\".chars().cycle();
388+
let stdin = stdin();
389+
let mut stdout = stdout();
390+
let result = loop {
391+
let _ = write!(
392+
stdout,
393+
"\rPress Space for more, 'q' to quit... {}",
394+
ticker.next().unwrap()
395+
);
396+
let mut buffer = [0u8; 1];
397+
match stdin.read(&mut buffer) {
398+
Ok(0) => {
399+
// No data
400+
}
401+
Ok(_n) => {
402+
if buffer[0] == b' ' {
403+
break WaitForKey::More;
404+
} else if buffer[0] == b'q' || buffer[0] == b'Q' {
405+
break WaitForKey::Quit;
406+
}
407+
}
408+
Err(e) => {
409+
let _ = writeln!(stdout, "Error {:?}", e);
410+
break WaitForKey::Quit;
411+
}
412+
}
413+
};
414+
let _ = write!(stdout, "\r \r");
415+
result
416+
}
417+
375418
static RAND_STATE: core::sync::atomic::AtomicU16 = core::sync::atomic::AtomicU16::new(0);
376419

377420
/// Seed the 16-bit psuedorandom number generator

0 commit comments

Comments
 (0)