|
19 | 19 | %
|
20 | 20 |
|
21 | 21 | -module(uart).
|
22 |
| --export([open/1, open/2, close/1, read/1, write/2]). |
| 22 | +-export([open/1, open/2, close/1, read/1, read/2, write/2]). |
23 | 23 |
|
| 24 | +-type peripheral() :: string() | binary(). |
| 25 | +% The peripheral `Name' may be one of: `"UART0"' | `"UART1"' | `"UART2"' | `<<"UART0">>' | `<<"UART1">>' | `<<"UART2">>'. |
| 26 | + |
| 27 | +-type uart_opts() :: [ |
| 28 | + {tx, Tx_pin :: integer()} |
| 29 | + | {rx, Rx_pin :: integer()} |
| 30 | + | {rts, Rts_pin :: integer()} |
| 31 | + | {cts, Cts_pin :: integer()} |
| 32 | + | {speed, Speed :: pos_integer()} |
| 33 | + | {data_bits, 5..8} |
| 34 | + | {stop_bits, 1 | 2} |
| 35 | + | {event_queue_len, Qlen :: pos_integer()} |
| 36 | + | {flow_control, none | hardware | software} |
| 37 | + | {parity, none | even | odd} |
| 38 | + | {peripheral, peripheral()} |
| 39 | + | [] |
| 40 | +]. |
| 41 | + |
| 42 | +%%----------------------------------------------------------------------------- |
| 43 | +%% @param Name the uart peripheral to be opened |
| 44 | +%% @param Opts uart configuration options |
| 45 | +%% @returns Pid of the driver. |
| 46 | +%% @doc Open a connection to the UART driver |
| 47 | +%% |
| 48 | +%% This function will open a connection to the UART driver. |
| 49 | +%% @end |
| 50 | +%%----------------------------------------------------------------------------- |
| 51 | +-spec open(Name :: peripheral(), Opts :: uart_opts()) -> Pid :: pid() | {error, _Reason :: term()}. |
24 | 52 | open(Name, Opts) ->
|
25 | 53 | open([{peripheral, Name} | Opts]).
|
26 | 54 |
|
| 55 | +%%----------------------------------------------------------------------------- |
| 56 | +%% @param Opts uart configuration options |
| 57 | +%% @returns Pid of the driver. |
| 58 | +%% @doc Open a connection to the UART driver default port |
| 59 | +%% |
| 60 | +%% This function will open a connection to the UART driver. |
| 61 | +%% @end |
| 62 | +%%----------------------------------------------------------------------------- |
| 63 | +-spec open(Opts :: uart_opts()) -> Pid :: pid() | {error, _Reason :: term()}. |
27 | 64 | open(Opts) ->
|
28 | 65 | open_port({spawn, "uart"}, migrate_config(Opts)).
|
29 | 66 |
|
30 |
| -close(Pid) -> |
| 67 | +%%----------------------------------------------------------------------------- |
| 68 | +%% @param Pid of the uart port to be closed |
| 69 | +%% @returns ok. |
| 70 | +%% @doc Close a port connection to the UART driver |
| 71 | +%% |
| 72 | +%% This function will close the given port connection to the UART driver. |
| 73 | +%% @end |
| 74 | +%%----------------------------------------------------------------------------- |
| 75 | +-spec close(Pid :: pid()) -> ok | {error, _Reason :: term()}. |
| 76 | +close(Pid) when is_pid(Pid) -> |
31 | 77 | port:call(Pid, close).
|
32 | 78 |
|
33 |
| -read(Pid) -> |
| 79 | +%%----------------------------------------------------------------------------- |
| 80 | +%% @param Pid of the uart port to be read |
| 81 | +%% @returns {ok, Data} or {error, Reason} |
| 82 | +%% @doc Read data from a UART port |
| 83 | +%% |
| 84 | +%% This function will return any data that is available, or return |
| 85 | +%% a `{error, timeout}' tuple. The driver will sent the next available |
| 86 | +%% data from the UART driver to the process that made the last read. |
| 87 | +%% Example: |
| 88 | +%% ``` |
| 89 | +%% Data = case uart:read(Uart) of |
| 90 | +%% {ok, Binary} -> Binary; |
| 91 | +%% {error, timeout} -> |
| 92 | +%% receive |
| 93 | +%% {ok, RecvBinary} -> RecvBinary; |
| 94 | +%% Error -> error(Error) |
| 95 | +%% end; |
| 96 | +%% Error -> error(Error) |
| 97 | +%% end, |
| 98 | +%% ''' |
| 99 | +%% Any attempt by another (or the same process) to read from uart before the |
| 100 | +%% next uart payload is sent by the driver will result in `{error, ealready}'. |
| 101 | +%% @end |
| 102 | +%%----------------------------------------------------------------------------- |
| 103 | +-spec read(Pid :: pid()) -> {ok, Data :: iodata()} | {error, _Reason :: term()}. |
| 104 | +read(Pid) when is_pid(Pid) -> |
34 | 105 | port:call(Pid, read).
|
35 | 106 |
|
36 |
| -write(Pid, B) -> |
37 |
| - case is_iolist(B) of |
| 107 | +%%----------------------------------------------------------------------------- |
| 108 | +%% @param Pid of the uart port to be read |
| 109 | +%% @param Timeout millisecond to wait for data to become available |
| 110 | +%% @returns `{ok, Data}', or `{error, Reason}' |
| 111 | +%% @doc Read data from a UART port |
| 112 | +%% |
| 113 | +%% This function will return any data that is available within the |
| 114 | +%% timeout period to the process. After the timeout has expired a new |
| 115 | +%% read command may be used regardless of whether the last read was |
| 116 | +%% sent a payload. |
| 117 | +%% Example: |
| 118 | +%% ``` |
| 119 | +%% Data = case uart:read(Uart, 3000) of |
| 120 | +%% {ok, Bin} -> Bin; |
| 121 | +%% {error, timeout} -> <<"">>; |
| 122 | +%% Error -> error_handler_fun(Uart, Error) |
| 123 | +%% end, |
| 124 | +%% ''' |
| 125 | +%% Any data sent to the esp32 over uart between reads with a timeout will |
| 126 | +%% be lost, so be sure this is what you want. Most applications will want |
| 127 | +%% a single process to read from UART and continue to listen until a payload |
| 128 | +%% is received, and likely pass the payload off for processing and |
| 129 | +%% immediately begin another read. |
| 130 | +%% @end |
| 131 | +%%----------------------------------------------------------------------------- |
| 132 | +-spec read(Pid :: pid(), Timeout :: pos_integer()) -> |
| 133 | + {ok, Data :: iodata()} | {error, _Reason :: term()}. |
| 134 | +read(Pid, Timeout) when is_pid(Pid) -> |
| 135 | + case port:call(Pid, read, Timeout) of |
| 136 | + {error, timeout} -> |
| 137 | + port:call(Pid, cancel_read), |
| 138 | + {error, timeout}; |
| 139 | + Result -> |
| 140 | + Result |
| 141 | + end. |
| 142 | + |
| 143 | +%%----------------------------------------------------------------------------- |
| 144 | +%% @param Pid of the uart port to be written to |
| 145 | +%% @param Data to be written to the given uart port |
| 146 | +%% @returns ok or {error, Reason} |
| 147 | +%% @doc Write data to a UART port |
| 148 | +%% |
| 149 | +%% This function will write the given data to the UART port. |
| 150 | +%% @end |
| 151 | +%%----------------------------------------------------------------------------- |
| 152 | +-spec write(Pid :: pid(), Data :: iodata()) -> ok | {error, _Reason :: term()}. |
| 153 | +write(Pid, Data) -> |
| 154 | + case is_iolist(Data) andalso is_pid(Pid) of |
38 | 155 | true ->
|
39 |
| - port:call(Pid, {write, B}); |
| 156 | + port:call(Pid, {write, Data}); |
40 | 157 | false ->
|
41 |
| - throw(badarg) |
| 158 | + error(badarg) |
42 | 159 | end.
|
43 | 160 |
|
44 | 161 | %% @private
|
|
0 commit comments