1use std::{collections::BTreeMap, sync::Mutex};
5
6use xous::MemoryRange;
7
8use crate::{CAMERA_BYTES_PER_PX, CAMERA_FB_SIZE_BYTES, CAMERA_HEIGHT, CAMERA_MARGIN, CAMERA_WIDTH};
9
10pub struct Frame {
11 id: u32,
12}
13
14static SHMEM_CACHE: Mutex<BTreeMap<u32, MemoryRange>> = Mutex::new(BTreeMap::new());
15
16impl Frame {
17 pub fn allocate() -> (Self, &'static mut [u8]) {
18 for _ in 0..10 {
19 let id = rand::random::<u32>();
20 if let Ok(shmem) =
21 shared_memory::ShmemConf::new().size(CAMERA_FB_SIZE_BYTES).os_id(Self::os_id(id)).create()
22 {
23 let shmem = Box::leak(Box::new(shmem));
24 let slice = unsafe { shmem.as_slice_mut() };
25 for pixel in slice.chunks_mut(4) {
26 pixel[3] = 255;
28 }
29 return (Self { id }, slice);
30 }
31 }
32 panic!("Could not create shmem for camera");
33 }
34
35 fn os_id(id: u32) -> String { format!("/xous_cam_buf_{id}") }
36
37 pub fn padded_range(&self) -> xous::MemoryRange {
38 if let Some(range) = SHMEM_CACHE.lock().unwrap().get(&self.id) {
39 return *range;
40 }
41 let shmem = shared_memory::ShmemConf::new()
42 .size(CAMERA_FB_SIZE_BYTES)
43 .os_id(Self::os_id(self.id))
44 .open()
45 .unwrap();
46 let shmem = Box::leak(Box::new(shmem));
47 let slice = unsafe { shmem.as_slice_mut() };
48 let range = unsafe { MemoryRange::new(slice.as_ptr() as usize, slice.len()).unwrap() };
49 SHMEM_CACHE.lock().unwrap().insert(self.id, range);
50 range
51 }
52
53 pub fn content(&self) -> xous::MemoryRange {
54 self.padded_range()
55 .subrange(
56 CAMERA_WIDTH * CAMERA_MARGIN * CAMERA_BYTES_PER_PX,
57 CAMERA_WIDTH * CAMERA_HEIGHT * CAMERA_BYTES_PER_PX,
58 )
59 .unwrap()
60 }
61}
62
63impl server::AsScalar<1> for Frame {
64 fn as_scalar(&self) -> [u32; 1] { [self.id] }
65}
66
67impl server::FromScalar<1> for Frame {
68 fn from_scalar([id]: [u32; 1]) -> Self { Self { id } }
69}