@@ -332,6 +332,123 @@ impl<USART, PINS, WORD> AsMut<Rx<USART, WORD>> for Serial<USART, PINS, WORD> {
332332 }
333333}
334334
335+ /// Serial receiver containing RX pin
336+ pub struct URx < USART , RX , WORD = u8 > {
337+ _usart : PhantomData < USART > ,
338+ pin : RX ,
339+ _word : PhantomData < WORD > ,
340+ }
341+
342+ /// Serial transmitter containing TX pin
343+ pub struct UTx < USART , TX , WORD = u8 > {
344+ usart : USART ,
345+ pin : TX ,
346+ _word : PhantomData < WORD > ,
347+ }
348+
349+ impl < USART : Instance , RX , WORD > URx < USART , RX , WORD > {
350+ fn new ( pin : RX ) -> Self {
351+ Self {
352+ _usart : PhantomData ,
353+ pin,
354+ _word : PhantomData ,
355+ }
356+ }
357+
358+ pub fn erase ( self ) -> Rx < USART , WORD > {
359+ Rx :: new ( )
360+ }
361+
362+ /// Start listening for an rx not empty interrupt event
363+ ///
364+ /// Note, you will also have to enable the corresponding interrupt
365+ /// in the NVIC to start receiving events.
366+ pub fn listen ( & mut self ) {
367+ unsafe { ( * USART :: ptr ( ) ) . cr1 . modify ( |_, w| w. rxneie ( ) . set_bit ( ) ) }
368+ }
369+
370+ /// Stop listening for the rx not empty interrupt event
371+ pub fn unlisten ( & mut self ) {
372+ unsafe { ( * USART :: ptr ( ) ) . cr1 . modify ( |_, w| w. rxneie ( ) . clear_bit ( ) ) }
373+ }
374+
375+ /// Start listening for a line idle interrupt event
376+ ///
377+ /// Note, you will also have to enable the corresponding interrupt
378+ /// in the NVIC to start receiving events.
379+ pub fn listen_idle ( & mut self ) {
380+ unsafe { ( * USART :: ptr ( ) ) . cr1 . modify ( |_, w| w. idleie ( ) . set_bit ( ) ) }
381+ }
382+
383+ /// Stop listening for the line idle interrupt event
384+ pub fn unlisten_idle ( & mut self ) {
385+ unsafe { ( * USART :: ptr ( ) ) . cr1 . modify ( |_, w| w. idleie ( ) . clear_bit ( ) ) }
386+ }
387+
388+ /// Return true if the line idle status is set
389+ pub fn is_idle ( & self ) -> bool {
390+ unsafe { ( * USART :: ptr ( ) ) . sr . read ( ) . idle ( ) . bit_is_set ( ) }
391+ }
392+
393+ /// Return true if the rx register is not empty (and can be read)
394+ pub fn is_rx_not_empty ( & self ) -> bool {
395+ unsafe { ( * USART :: ptr ( ) ) . sr . read ( ) . rxne ( ) . bit_is_set ( ) }
396+ }
397+
398+ /// Clear idle line interrupt flag
399+ pub fn clear_idle_interrupt ( & self ) {
400+ unsafe {
401+ let _ = ( * USART :: ptr ( ) ) . sr . read ( ) ;
402+ let _ = ( * USART :: ptr ( ) ) . dr . read ( ) ;
403+ }
404+ }
405+ }
406+
407+ impl < USART : Instance , TX , WORD > UTx < USART , TX , WORD > {
408+ fn new ( usart : USART , pin : TX ) -> Self {
409+ Self {
410+ usart,
411+ pin,
412+ _word : PhantomData ,
413+ }
414+ }
415+
416+ pub fn erase ( self ) -> Tx < USART , WORD > {
417+ Tx :: new ( )
418+ }
419+
420+ pub fn join < RX > ( self , rx : URx < USART , RX , WORD > ) -> Serial < USART , ( TX , RX ) , WORD >
421+ where
422+ ( TX , RX ) : Pins < USART > ,
423+ {
424+ Serial {
425+ usart : self . usart ,
426+ pins : ( self . pin , rx. pin ) ,
427+ tx : Tx :: new ( ) ,
428+ rx : Rx :: new ( ) ,
429+ }
430+ }
431+
432+ /// Start listening for a tx empty interrupt event
433+ ///
434+ /// Note, you will also have to enable the corresponding interrupt
435+ /// in the NVIC to start receiving events.
436+ // TODO: replace with "self.usart"
437+ pub fn listen ( & mut self ) {
438+ unsafe { ( * USART :: ptr ( ) ) . cr1 . modify ( |_, w| w. txeie ( ) . set_bit ( ) ) }
439+ }
440+
441+ /// Stop listening for the tx empty interrupt event
442+ pub fn unlisten ( & mut self ) {
443+ unsafe { ( * USART :: ptr ( ) ) . cr1 . modify ( |_, w| w. txeie ( ) . clear_bit ( ) ) }
444+ }
445+
446+ /// Return true if the tx register is empty (and can accept data)
447+ pub fn is_tx_empty ( & self ) -> bool {
448+ unsafe { ( * USART :: ptr ( ) ) . sr . read ( ) . txe ( ) . bit_is_set ( ) }
449+ }
450+ }
451+
335452pub trait SerialExt : Sized + Instance {
336453 fn serial < TX , RX , WORD > (
337454 self ,
@@ -614,6 +731,12 @@ impl<USART: Instance, PINS, WORD> Serial<USART, PINS, WORD> {
614731 }
615732}
616733
734+ impl < USART : Instance , TX , RX , WORD > Serial < USART , ( TX , RX ) , WORD > {
735+ pub fn split_nondestructive ( self ) -> ( UTx < USART , TX , WORD > , URx < USART , RX , WORD > ) {
736+ ( UTx :: new ( self . usart , self . pins . 0 ) , URx :: new ( self . pins . 1 ) )
737+ }
738+ }
739+
617740impl < USART : Instance , PINS > Serial < USART , PINS , u8 > {
618741 /// Converts this Serial into a version that can read and write `u16` values instead of `u8`s
619742 ///
@@ -912,3 +1035,109 @@ impl<USART: Instance> Tx<USART, u16> {
9121035 nb:: block!( self . flush( ) )
9131036 }
9141037}
1038+
1039+ impl < USART : Instance , TX > fmt:: Write for UTx < USART , TX > {
1040+ fn write_str ( & mut self , s : & str ) -> fmt:: Result {
1041+ s. bytes ( )
1042+ . try_for_each ( |c| block ! ( self . write( c) ) )
1043+ . map_err ( |_| fmt:: Error )
1044+ }
1045+ }
1046+
1047+ impl < USART : Instance , RX > URx < USART , RX , u8 > {
1048+ fn read ( & mut self ) -> nb:: Result < u8 , Error > {
1049+ // Delegate to the Read<u16> implementation, then truncate to 8 bits
1050+ Rx :: < USART , u16 > :: new ( ) . read ( ) . map ( |word16| word16 as u8 )
1051+ }
1052+ }
1053+
1054+ impl < USART : Instance , RX > URx < USART , RX , u16 > {
1055+ fn read ( & mut self ) -> nb:: Result < u16 , Error > {
1056+ // NOTE(unsafe) atomic read with no side effects
1057+ let sr = unsafe { ( * USART :: ptr ( ) ) . sr . read ( ) } ;
1058+
1059+ // Any error requires the dr to be read to clear
1060+ if sr. pe ( ) . bit_is_set ( )
1061+ || sr. fe ( ) . bit_is_set ( )
1062+ || sr. nf ( ) . bit_is_set ( )
1063+ || sr. ore ( ) . bit_is_set ( )
1064+ {
1065+ unsafe { ( * USART :: ptr ( ) ) . dr . read ( ) } ;
1066+ }
1067+
1068+ Err ( if sr. pe ( ) . bit_is_set ( ) {
1069+ Error :: Parity . into ( )
1070+ } else if sr. fe ( ) . bit_is_set ( ) {
1071+ Error :: FrameFormat . into ( )
1072+ } else if sr. nf ( ) . bit_is_set ( ) {
1073+ Error :: Noise . into ( )
1074+ } else if sr. ore ( ) . bit_is_set ( ) {
1075+ Error :: Overrun . into ( )
1076+ } else if sr. rxne ( ) . bit_is_set ( ) {
1077+ // NOTE(unsafe) atomic read from stateless register
1078+ return Ok ( unsafe { & * USART :: ptr ( ) } . dr . read ( ) . dr ( ) . bits ( ) ) ;
1079+ } else {
1080+ nb:: Error :: WouldBlock
1081+ } )
1082+ }
1083+ }
1084+
1085+ impl < USART : Instance , TX > UTx < USART , TX , u8 > {
1086+ fn write ( & mut self , word : u8 ) -> nb:: Result < ( ) , Error > {
1087+ // Delegate to u16 version
1088+ Tx :: < USART , u16 > :: new ( ) . write ( u16:: from ( word) )
1089+ }
1090+
1091+ fn flush ( & mut self ) -> nb:: Result < ( ) , Error > {
1092+ // Delegate to u16 version
1093+ Tx :: < USART , u16 > :: new ( ) . flush ( )
1094+ }
1095+
1096+ fn bwrite_all ( & mut self , bytes : & [ u8 ] ) -> Result < ( ) , Error > {
1097+ for & b in bytes {
1098+ nb:: block!( self . write( b) ) ?;
1099+ }
1100+ Ok ( ( ) )
1101+ }
1102+
1103+ fn bflush ( & mut self ) -> Result < ( ) , Error > {
1104+ nb:: block!( self . flush( ) )
1105+ }
1106+ }
1107+
1108+ impl < USART : Instance , TX > UTx < USART , TX , u16 > {
1109+ fn write ( & mut self , word : u16 ) -> nb:: Result < ( ) , Error > {
1110+ // NOTE(unsafe) atomic read with no side effects
1111+ let sr = unsafe { ( * USART :: ptr ( ) ) . sr . read ( ) } ;
1112+
1113+ if sr. txe ( ) . bit_is_set ( ) {
1114+ // NOTE(unsafe) atomic write to stateless register
1115+ unsafe { & * USART :: ptr ( ) } . dr . write ( |w| w. dr ( ) . bits ( word) ) ;
1116+ Ok ( ( ) )
1117+ } else {
1118+ Err ( nb:: Error :: WouldBlock )
1119+ }
1120+ }
1121+
1122+ fn flush ( & mut self ) -> nb:: Result < ( ) , Error > {
1123+ // NOTE(unsafe) atomic read with no side effects
1124+ let sr = unsafe { ( * USART :: ptr ( ) ) . sr . read ( ) } ;
1125+
1126+ if sr. tc ( ) . bit_is_set ( ) {
1127+ Ok ( ( ) )
1128+ } else {
1129+ Err ( nb:: Error :: WouldBlock )
1130+ }
1131+ }
1132+
1133+ fn bwrite_all ( & mut self , buffer : & [ u16 ] ) -> Result < ( ) , Error > {
1134+ for & b in buffer {
1135+ nb:: block!( self . write( b) ) ?;
1136+ }
1137+ Ok ( ( ) )
1138+ }
1139+
1140+ fn bflush ( & mut self ) -> Result < ( ) , Error > {
1141+ nb:: block!( self . flush( ) )
1142+ }
1143+ }
0 commit comments