@@ -753,10 +753,60 @@ if Code.ensure_loaded?(Circuits.UART) do
753753 GenServer . call ( transport , :disable_token_passing )
754754 end
755755
756+ @ doc """
757+ Configures the transport.
758+
759+ Only some of the available `t:open_options/0` can be configured,
760+ unsupported options can only be changed by re-starting the transport completely.
761+
762+ The following options are supported:
763+ - `baudrate`
764+ - `log_communication`
765+ - `log_communication_rcv`
766+ - `max_info_frames`
767+ - `max_master_address`
768+
769+ For a description of each option, see `open/2`.
770+
771+ Note that reconfiguring the baudrate on the fly MAY lead to invalid frames!
772+ May also lead to dropping token.
773+ """
774+ @ spec configure ( TransportBehaviour . transport ( ) , open_options ( ) ) :: :ok | { :error , term ( ) }
775+ def configure ( transport , opts ) when is_server ( transport ) and is_list ( opts ) do
776+ unless Keyword . keyword? ( opts ) do
777+ raise ArgumentError , "configure/2 expected a keyword list, got: #{ inspect ( opts ) } "
778+ end
779+
780+ Enum . each ( opts , fn
781+ { :baudrate , val } when is_integer ( val ) and val > 0 ->
782+ true
783+
784+ { :log_communication , val } when is_boolean ( val ) ->
785+ true
786+
787+ { :log_communication_rcv , val } when is_boolean ( val ) ->
788+ true
789+
790+ { :max_info_frames , val } when is_integer ( val ) and val > 0 ->
791+ true
792+
793+ { :max_master_address , val } when is_integer ( val ) and val > 0 ->
794+ true
795+
796+ { key , val } ->
797+ raise ArgumentError ,
798+ "configure/2 received unsupported combination - key: " <>
799+ inspect ( key ) <> ", value: " <> inspect ( val )
800+ end )
801+
802+ GenServer . call ( transport , { :configure , Map . new ( opts ) } )
803+ end
804+
756805 @ doc false
757806 def init ( { callback , opts } ) do
758807 new_opts =
759808 opts
809+ |> Map . put_new ( :baudrate , 38_400 )
760810 |> Map . put_new ( :log_communication , false )
761811 |> Map . put_new ( :max_info_frames , 1 )
762812 |> Map . put_new ( :max_master_address , @ max_master_addr )
@@ -766,7 +816,7 @@ if Code.ensure_loaded?(Circuits.UART) do
766816 with { :ok , uart_pid } <- UART . start_link ( ) do
767817 { UART . open ( uart_pid , Map . fetch! ( opts , :port_name ) ,
768818 active: true ,
769- speed: Map . get ( opts , : baudrate, 38_400 ) ,
819+ speed: new_opts . baudrate ,
770820 data_bits: 8 ,
771821 stop_bits: 1 ,
772822 parity: :none ,
@@ -1464,6 +1514,35 @@ if Code.ensure_loaded?(Circuits.UART) do
14641514 { :reply , { :error , :slave_mode } , state }
14651515 end
14661516
1517+ def handle_call ( { :configure , % { } = opts } , _from , % State { } = state ) do
1518+ log_debug ( fn -> "BacMstpTransport: Received configure request" end )
1519+
1520+ new_opts = Map . merge ( state . opts , opts )
1521+
1522+ reply =
1523+ case Map . fetch ( opts , :baudrate ) do
1524+ { :ok , baudrate } ->
1525+ with :ok <- UART . configure ( state . uart_pid , speed: baudrate ) do
1526+ ReceiveFSM . configure ( state . receive_fsm , % {
1527+ baudrate: baudrate ,
1528+ log_communication: new_opts . log_communication_rcv
1529+ } )
1530+ end
1531+
1532+ :error ->
1533+ :ok
1534+ end
1535+
1536+ case reply do
1537+ :ok ->
1538+ new_state = % { state | opts: new_opts }
1539+ { :reply , :ok , new_state }
1540+
1541+ _other ->
1542+ { :reply , reply , state }
1543+ end
1544+ end
1545+
14671546 def handle_call ( _call , _from , state ) do
14681547 { :noreply , state }
14691548 end
0 commit comments