1use proc_macro::TokenStream;
15use quote::quote;
16
17#[proc_macro_derive(Modulation)]
18pub fn modulation_derive(input: TokenStream) -> TokenStream {
19 let ast = syn::parse(input).unwrap();
20 impl_modulation_macro(&ast)
21}
22
23fn impl_modulation_macro(ast: &syn::DeriveInput) -> TokenStream {
24 let name = &ast.ident;
25 let generics = &ast.generics;
26 let linetimes_prop = generics.lifetimes();
27 let linetimes_impl = generics.lifetimes();
28 let linetimes_datagram = generics.lifetimes();
29 let type_params_prop = generics.type_params();
30 let type_params_impl = generics.type_params();
31 let type_params_datagram = generics.type_params();
32 let (_, ty_generics, where_clause) = generics.split_for_impl();
33 let gen = quote! {
34 impl <#(#linetimes_prop,)* #(#type_params_prop,)*> autd3_core::modulation::ModulationProperty for #name #ty_generics #where_clause {
35 fn sampling_frequency_division(&self) -> u32 {
36 self.freq_div
37 }
38
39 fn sampling_frequency(&self) -> autd3_core::float {
40 autd3_core::FPGA_SUB_CLK_FREQ as autd3_core::float / self.freq_div as autd3_core::float
41 }
42 }
43
44 impl <#(#linetimes_impl,)* #(#type_params_impl,)*> #name #ty_generics #where_clause {
45 #[allow(clippy::needless_update)]
52 pub fn with_sampling_frequency_division(self, freq_div: u32) -> Self {
53 Self {freq_div, ..self}
54 }
55
56 #[allow(clippy::needless_update)]
63 pub fn with_sampling_frequency(self, freq: autd3_core::float) -> Self {
64 let freq_div = autd3_core::FPGA_SUB_CLK_FREQ as autd3_core::float / freq;
65 self.with_sampling_frequency_division(freq_div as _)
66 }
67
68 #[allow(clippy::needless_update)]
75 pub fn with_sampling_period(self, period: std::time::Duration) -> Self {
76 let freq_div = autd3_core::FPGA_SUB_CLK_FREQ as autd3_core::float / 1000000000. * period.as_nanos() as autd3_core::float;
77 self.with_sampling_frequency_division(freq_div as _)
78 }
79 }
80
81 impl <#(#linetimes_datagram,)* #(#type_params_datagram,)* T: autd3_core::geometry::Transducer> autd3_core::datagram::Datagram<T> for #name #ty_generics #where_clause {
82 type H = autd3_core::Modulation;
83 type B = autd3_core::NullBody;
84
85 fn operation(
86 &self,
87 _geometry: &autd3_core::geometry::Geometry<T>,
88 ) -> Result<(Self::H, Self::B), autd3_core::error::AUTDInternalError> {
89 let freq_div = self.freq_div;
90 Ok((Self::H::new(self.calc()?, freq_div), Self::B::default()))
91 }
92 }
93 };
94 gen.into()
95}
96
97#[proc_macro_derive(Gain)]
98pub fn gain_derive(input: TokenStream) -> TokenStream {
99 let ast = syn::parse(input).unwrap();
100 impl_gain_macro(ast)
101}
102
103fn impl_gain_macro(ast: syn::DeriveInput) -> TokenStream {
104 let name = &ast.ident;
105 let generics = &ast.generics;
106 let linetimes_for_any = generics.lifetimes();
107 let linetimes = generics.lifetimes();
108 let type_params_for_any = generics.type_params();
109 let type_params = generics.type_params();
110 let (_, ty_generics, where_clause) = generics.split_for_impl();
111 if generics.type_params().any(|ty| ty.ident == "T") {
112 let gen = quote! {
113 impl <#(#linetimes_for_any,)* #(#type_params_for_any,)*> autd3_core::gain::GainAsAny for #name #ty_generics #where_clause {
114 fn as_any(&self) -> &dyn std::any::Any {
115 self
116 }
117 }
118
119 impl <#(#linetimes,)* #(#type_params,)*> autd3_core::datagram::Datagram<T> for #name #ty_generics #where_clause {
120 type H = autd3_core::NullHeader;
121 type B = T::Gain;
122
123 fn operation(
124 &self,
125 geometry: &Geometry<T>,
126 ) -> Result<(Self::H, Self::B), autd3_core::error::AUTDInternalError> {
127 Ok((Self::H::default(), <Self::B as autd3_core::GainOp>::new(self.calc(geometry)?, || {
128 geometry.transducers().map(|tr| tr.cycle()).collect()
129 })))
130 }
131 }
132 };
133 gen.into()
134 } else {
135 let gen = quote! {
136 impl <#(#linetimes_for_any,)* #(#type_params_for_any,)*> autd3_core::gain::GainAsAny for #name #ty_generics #where_clause {
137 fn as_any(&self) -> &dyn std::any::Any {
138 self
139 }
140 }
141
142 impl <#(#linetimes,)* #(#type_params,)* T: autd3_core::geometry::Transducer> autd3_core::datagram::Datagram<T> for #name #ty_generics #where_clause {
143 type H = autd3_core::NullHeader;
144 type B = T::Gain;
145
146 fn operation(
147 &self,
148 geometry: &Geometry<T>,
149 ) -> Result<(Self::H, Self::B), autd3_core::error::AUTDInternalError> {
150 Ok((Self::H::default(), <Self::B as autd3_core::GainOp>::new(self.calc(geometry)?, || {
151 geometry.transducers().map(|tr| tr.cycle()).collect()
152 })))
153 }
154 }
155 };
156 gen.into()
157 }
158}