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