| 1 | //! I/O ports: the latch each instruction writes, and the pins the program |
| 2 | //! reads. Click a pin to hold it low from outside, like a button. |
| 3 | |
| 4 | use bench51_core::session::Session; |
| 5 | use bench51_core::sfr::P0; |
| 6 | use eframe::egui::{self, Ui}; |
| 7 | |
| 8 | use crate::theme::palette; |
| 9 | use crate::widgets::{self, Dot}; |
| 10 | |
| 11 | pub fn show(ui: &mut Ui, s: &mut Session) { |
| 12 | let p = palette(ui.ctx()); |
| 13 | egui::ScrollArea::vertical() |
| 14 | .auto_shrink([false; 2]) |
| 15 | .show(ui, |ui| { |
| 16 | egui::Grid::new("ports") |
| 17 | .num_columns(11) |
| 18 | .spacing([2.0, 4.0]) |
| 19 | .show(ui, |ui| { |
| 20 | ui.label(""); |
| 21 | ui.label(""); |
| 22 | for bit in (0..8).rev() { |
| 23 | ui.vertical_centered(|ui| { |
| 24 | ui.label(p.label(bit.to_string()).color(p.text_disabled)); |
| 25 | }); |
| 26 | } |
| 27 | ui.label(""); |
| 28 | ui.end_row(); |
| 29 | for port in 0..4usize { |
| 30 | let addr = P0 + 0x10 * port as u8; |
| 31 | let latch = s.sim.sfr(addr); |
| 32 | let pins = s.sim.port_pins(port); |
| 33 | ui.label(p.label(format!("P{port}")).color(p.text_primary)); |
| 34 | ui.label(p.label("latch").color(p.text_disabled)); |
| 35 | for bit in (0..8u8).rev() { |
| 36 | let m = 1 << bit; |
| 37 | let dot = if latch & m != 0 { Dot::High } else { Dot::Low }; |
| 38 | let r = widgets::pin_dot(ui, dot) |
| 39 | .on_hover_text(format!("P{port}.{bit} latch — click to toggle")); |
| 40 | if r.clicked() { |
| 41 | s.sim.set_sfr(addr, latch ^ m); |
| 42 | } |
| 43 | } |
| 44 | ui.label(p.data(format!("{latch:02X}")).color(p.text_secondary)); |
| 45 | ui.end_row(); |
| 46 | |
| 47 | ui.label(""); |
| 48 | ui.label(p.label("pins").color(p.text_disabled)); |
| 49 | for bit in (0..8u8).rev() { |
| 50 | let m = 1 << bit; |
| 51 | let dot = if s.sim.pins[port] & m == 0 { |
| 52 | Dot::PulledLow |
| 53 | } else if pins & m != 0 { |
| 54 | Dot::High |
| 55 | } else { |
| 56 | Dot::Low |
| 57 | }; |
| 58 | let r = widgets::pin_dot(ui, dot).on_hover_text(format!( |
| 59 | "P{port}.{bit} pin — click to pull low from outside" |
| 60 | )); |
| 61 | if r.clicked() { |
| 62 | s.sim.pins[port] ^= m; |
| 63 | } |
| 64 | } |
| 65 | ui.label(p.data(format!("{pins:02X}"))); |
| 66 | ui.end_row(); |
| 67 | ui.add_space(6.0); |
| 68 | ui.end_row(); |
| 69 | } |
| 70 | }); |
| 71 | ui.add_space(4.0); |
| 72 | ui.label( |
| 73 | p.label("● 1 ○ 0 red: held low outside") |
| 74 | .color(p.text_disabled), |
| 75 | ); |
| 76 | }); |
| 77 | } |