1#![no_std]
9#![no_main]
10
11use arbitrary_int::{u2, u5};
12use fugit::ExtU32;
13use miniconf::{Leaf, Tree};
14use rtic_monotonics::Monotonic;
15
16use stabilizer::{
17 hardware::{
18 self, hal, SerialTerminal, SystemTimer, Systick, Urukul, UsbDevice,
19 },
20 net::{NetworkState, NetworkUsers},
21 settings::NetSettings,
22};
23
24#[derive(Clone, Debug, Tree)]
25pub struct Settings {
26 urukul: App,
27 net: NetSettings,
28}
29
30impl stabilizer::settings::AppSettings for Settings {
31 fn new(net: NetSettings) -> Self {
32 Self {
33 net,
34 urukul: App::default(),
35 }
36 }
37
38 fn net(&self) -> &NetSettings {
39 &self.net
40 }
41}
42
43impl serial_settings::Settings for Settings {
44 fn reset(&mut self) {
45 *self = Self {
46 urukul: App::default(),
47 net: NetSettings::new(self.net.mac),
48 }
49 }
50}
51
52#[derive(Clone, Debug, Tree)]
53pub struct Channel {
54 pll_n: Leaf<Option<u5>>,
55 pll_doubler: Leaf<bool>,
56 frequency: Leaf<f64>,
57 phase: Leaf<f32>,
58 full_scale_current: Leaf<f32>,
59 attenuation: Leaf<f32>,
60 enable: Leaf<bool>,
61 update: Leaf<bool>,
62}
63
64impl Default for Channel {
65 fn default() -> Self {
66 Self {
67 frequency: 0.0.into(),
68 phase: 0.0.into(),
69 full_scale_current: 20e-3.into(),
70 attenuation: 31.5.into(),
71 enable: false.into(),
72 pll_n: Some(u5::new(3)).into(),
73 pll_doubler: false.into(),
74 update: true.into(),
75 }
76 }
77}
78
79#[derive(Clone, Debug, Tree)]
80pub struct App {
81 refclk: Leaf<f64>,
82 clk_sel: Leaf<urukul::ClkSel>,
83 div_sel: Leaf<urukul::DivSel>,
84 update: Leaf<bool>,
85 ch: [Channel; 4],
86}
87
88impl Default for App {
89 fn default() -> Self {
90 Self {
91 clk_sel: urukul::ClkSel::Osc.into(),
92 div_sel: urukul::DivSel::One.into(),
93 update: true.into(),
94 refclk: 100.0e6.into(),
95 ch: Default::default(),
96 }
97 }
98}
99
100#[rtic::app(device = stabilizer::hardware::hal::stm32, peripherals = true, dispatchers=[DCMI, JPEG, LTDC, SDMMC])]
101mod app {
102 use super::*;
103
104 #[shared]
105 struct Shared {
106 usb: UsbDevice,
107 network: NetworkUsers<App, 3>,
108 settings: Settings,
109 }
110
111 #[local]
112 struct Local {
113 urukul: Urukul,
114 usb_terminal: SerialTerminal<Settings, 4>,
115 }
116
117 #[init]
118 fn init(c: init::Context) -> (Shared, Local) {
119 let clock = SystemTimer::new(|| Systick::now().ticks());
120
121 let (stabilizer, _pounder) = hardware::setup::setup::<Settings, 4>(
122 c.core,
123 c.device,
124 clock,
125 8,
126 1 << 7,
127 );
128
129 let crate::hardware::Eem::Urukul(urukul) = stabilizer.eem else {
130 panic!("No Urukul detected.")
131 };
132
133 let network = NetworkUsers::new(
134 stabilizer.net.stack,
135 stabilizer.net.phy,
136 clock,
137 env!("CARGO_BIN_NAME"),
138 &stabilizer.settings.net,
139 stabilizer.metadata,
140 );
141
142 let shared = Shared {
143 usb: stabilizer.usb,
144 network,
145 settings: stabilizer.settings,
146 };
147
148 let local = Local {
149 urukul,
150 usb_terminal: stabilizer.usb_serial,
151 };
152
153 settings_update::spawn().unwrap();
155 ethernet_link::spawn().unwrap();
156 usb::spawn().unwrap();
157
158 (shared, local)
159 }
160
161 #[idle(shared=[network, settings, usb])]
162 fn idle(mut c: idle::Context) -> ! {
163 loop {
164 match (&mut c.shared.network, &mut c.shared.settings)
165 .lock(|net, settings| net.update(&mut settings.urukul))
166 {
167 NetworkState::SettingsChanged => {
168 settings_update::spawn().unwrap()
169 }
170 NetworkState::Updated => {}
171 NetworkState::NoChange => {
172 if c.shared.usb.lock(|usb| {
174 usb.state()
175 == usb_device::device::UsbDeviceState::Suspend
176 }) {
177 cortex_m::asm::wfi();
178 }
179 }
180 }
181 }
182 }
183
184 #[task(priority = 1, shared=[settings], local=[urukul])]
185 async fn settings_update(mut c: settings_update::Context) {
186 let u = c.local.urukul;
187 c.shared.settings.lock(|s| {
188 let s = &mut s.urukul;
189 if *s.update {
190 *s.update = false;
191 u.set_cfg(
192 u.cfg().with_clk_sel(*s.clk_sel).with_div_sel(*s.div_sel),
193 )
194 .unwrap();
195 }
196 let power = ad9912::Power::builder()
197 .with_digital_pd(false)
198 .with_full_pd(false)
199 .with_pll_pd(true)
200 .with_output_doubler_en(false)
201 .with_cmos_en(false)
202 .with_hstl_pd(true)
203 .build();
204 for (i, ch) in s.ch.iter_mut().enumerate() {
205 if *ch.update {
206 *ch.update = false;
207 let refclk = *s.refclk / s.div_sel.divider() as f64;
208 let i = u2::new(i as _);
209 let sysclk = if let Some(pll_n) = *ch.pll_n {
210 u.dds(i).set_power(power.with_pll_pd(false)).unwrap();
211 u.dds(i).set_ndiv(pll_n).unwrap();
212 let mut pll = ad9912::Pll::default()
213 .with_charge_pump(ad9912::ChargePump::Ua375)
214 .with_ref_doubler(*ch.pll_doubler);
215 let sysclk = pll.set_refclk(pll_n, refclk);
216 u.dds(i).set_pll(pll).unwrap();
217 sysclk
218 } else {
219 u.dds(i).set_power(power.with_pll_pd(true)).unwrap();
220 refclk
221 };
222 u.dds(i).set_frequency(*ch.frequency, sysclk).unwrap();
223 u.dds(i).set_phase(*ch.phase).unwrap();
224 u.io_update().unwrap();
225 u.dds(i)
226 .set_full_scale_current(*ch.full_scale_current, 10e3)
227 .unwrap();
228 u.set_att(i, urukul::att_to_mu(*ch.attenuation)).unwrap();
229 u.set_rf_sw(i, *ch.enable).unwrap();
230 }
231 }
232 });
233 }
234
235 #[task(priority = 1, shared=[usb, settings], local=[usb_terminal])]
236 async fn usb(mut c: usb::Context) {
237 loop {
238 c.shared.usb.lock(|usb| {
239 usb.poll(&mut [c
240 .local
241 .usb_terminal
242 .interface_mut()
243 .inner_mut()]);
244 });
245
246 c.shared.settings.lock(|settings| {
247 if c.local.usb_terminal.poll(settings).unwrap() {
248 settings_update::spawn().unwrap()
249 }
250 });
251
252 Systick::delay(10.millis()).await;
253 }
254 }
255
256 #[task(priority = 1, shared=[network])]
257 async fn ethernet_link(mut c: ethernet_link::Context) {
258 loop {
259 c.shared.network.lock(|net| net.processor.handle_link());
260 Systick::delay(1.secs()).await;
261 }
262 }
263
264 #[task(binds = ETH, priority = 1)]
265 fn eth(_: eth::Context) {
266 unsafe { hal::ethernet::interrupt_handler() }
267 }
268}