@@ -87,6 +87,51 @@ impl<REG: Resettable + Writable> Reg<REG> {
8787 . bits ,
8888 ) ;
8989 }
90+
91+ /// Writes bits to a `Writable` register and produce a value.
92+ ///
93+ /// You can write raw bits into a register:
94+ /// ```ignore
95+ /// periph.reg.write_and(|w| unsafe { w.bits(rawbits); });
96+ /// ```
97+ /// or write only the fields you need:
98+ /// ```ignore
99+ /// periph.reg.write_and(|w| {
100+ /// w.field1().bits(newfield1bits)
101+ /// .field2().set_bit()
102+ /// .field3().variant(VARIANT);
103+ /// });
104+ /// ```
105+ /// or an alternative way of saying the same:
106+ /// ```ignore
107+ /// periph.reg.write_and(|w| {
108+ /// w.field1().bits(newfield1bits);
109+ /// w.field2().set_bit();
110+ /// w.field3().variant(VARIANT);
111+ /// });
112+ /// ```
113+ /// In the latter case, other fields will be set to their reset value.
114+ ///
115+ /// Values can be returned from the closure:
116+ /// ```ignore
117+ /// let state = periph.reg.write_and(|w| State::set(w.field1()));
118+ /// ```
119+ #[ inline( always) ]
120+ pub fn write_and < F , T > ( & self , f : F ) -> T
121+ where
122+ F : FnOnce ( & mut W < REG > ) -> T ,
123+ {
124+ let mut writer = W {
125+ bits : REG :: RESET_VALUE & !REG :: ONE_TO_MODIFY_FIELDS_BITMAP
126+ | REG :: ZERO_TO_MODIFY_FIELDS_BITMAP ,
127+ _reg : marker:: PhantomData ,
128+ } ;
129+ let result = f ( & mut writer) ;
130+
131+ self . register . set ( writer. bits ) ;
132+
133+ result
134+ }
90135}
91136
92137impl < REG : Writable > Reg < REG > {
@@ -110,6 +155,30 @@ impl<REG: Writable> Reg<REG> {
110155 . bits ,
111156 ) ;
112157 }
158+
159+ /// Writes 0 to a `Writable` register and produces a value.
160+ ///
161+ /// Similar to `write`, but unused bits will contain 0.
162+ ///
163+ /// # Safety
164+ ///
165+ /// Unsafe to use with registers which don't allow to write 0.
166+ #[ inline( always) ]
167+ pub unsafe fn write_with_zero < F , T > ( & self , f : F ) -> T
168+ where
169+ F : FnOnce ( & mut W < REG > ) -> T ,
170+ {
171+ let mut writer = W {
172+ bits : REG :: Ux :: default ( ) ,
173+ _reg : marker:: PhantomData ,
174+ } ;
175+
176+ let result = f ( & mut writer) ;
177+
178+ self . register . set ( writer. bits ) ;
179+
180+ result
181+ }
113182}
114183
115184impl < REG : Readable + Writable > Reg < REG > {
@@ -159,11 +228,67 @@ impl<REG: Readable + Writable> Reg<REG> {
159228 . bits ,
160229 ) ;
161230 }
231+
232+ /// Modifies the contents of the register by reading and then writing it
233+ /// and produces a value.
234+ ///
235+ /// E.g. to do a read-modify-write sequence to change parts of a register:
236+ /// ```ignore
237+ /// let bits = periph.reg.modify(|r, w| {
238+ /// let new_bits = r.bits() | 3;
239+ /// unsafe {
240+ /// w.bits(new_bits);
241+ /// }
242+ ///
243+ /// new_bits
244+ /// });
245+ /// ```
246+ /// or
247+ /// ```ignore
248+ /// periph.reg.modify(|_, w| {
249+ /// w.field1().bits(newfield1bits)
250+ /// .field2().set_bit()
251+ /// .field3().variant(VARIANT);
252+ /// });
253+ /// ```
254+ /// or an alternative way of saying the same:
255+ /// ```ignore
256+ /// periph.reg.modify(|_, w| {
257+ /// w.field1().bits(newfield1bits);
258+ /// w.field2().set_bit();
259+ /// w.field3().variant(VARIANT);
260+ /// });
261+ /// ```
262+ /// Other fields will have the value they had before the call to `modify`.
263+ #[ inline( always) ]
264+ pub fn modify_and < F , T > ( & self , f : F ) -> T
265+ where
266+ for < ' w > F : FnOnce ( & R < REG > , & ' w mut W < REG > ) -> T ,
267+ {
268+ let bits = self . register . get ( ) ;
269+
270+ let mut writer = W {
271+ bits : bits & !REG :: ONE_TO_MODIFY_FIELDS_BITMAP | REG :: ZERO_TO_MODIFY_FIELDS_BITMAP ,
272+ _reg : marker:: PhantomData ,
273+ } ;
274+
275+ let result = f (
276+ & R {
277+ bits,
278+ _reg : marker:: PhantomData ,
279+ } ,
280+ & mut writer,
281+ ) ;
282+
283+ self . register . set ( writer. bits ) ;
284+
285+ result
286+ }
162287}
163288
164289impl < REG : Readable > core:: fmt:: Debug for crate :: generic:: Reg < REG >
165290where
166- R < REG > : core:: fmt:: Debug
291+ R < REG > : core:: fmt:: Debug ,
167292{
168293 fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
169294 core:: fmt:: Debug :: fmt ( & self . read ( ) , f)
0 commit comments