diff options
author | Joe Zhao <ztuowen@gmail.com> | 2014-05-16 20:16:33 +0800 |
---|---|---|
committer | Joe Zhao <ztuowen@gmail.com> | 2014-05-16 20:16:33 +0800 |
commit | 859179718904a1824082fdbbf77192bd1ce762e7 (patch) | |
tree | 2869db33b8c21416676d6fc01eb65a079c318f83 /rsbusserv.erl | |
download | local-859179718904a1824082fdbbf77192bd1ce762e7.tar.gz local-859179718904a1824082fdbbf77192bd1ce762e7.tar.bz2 local-859179718904a1824082fdbbf77192bd1ce762e7.zip |
First commit
Diffstat (limited to 'rsbusserv.erl')
-rw-r--r-- | rsbusserv.erl | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/rsbusserv.erl b/rsbusserv.erl new file mode 100644 index 0000000..997e590 --- /dev/null +++ b/rsbusserv.erl @@ -0,0 +1,119 @@ +%%%------------------------------------------------------------------- +%%% @author Joe Zhao +%%% @copyright (C) 2014, <COMPANY> +%%% @doc +%%% This server monitors behaviors on the serial bus. +%%% Whose duty includes serialize queries, message encoding, +%%% and response handling(only when slave request repitition of the previous command) +%%% The returns of the command are sent back to its origins(first parameter of the tuple, can also be someone else). +%%% @end +%%% Created : 27. 四月 2014 16:52 +%%%------------------------------------------------------------------- +-module(rsbusserv). +-author("Joe Zhao"). + +-compile([debug_info,export_all]). + +%% API +%% -export([start/0]). + +-define(DEVICE,"/dev/ttyUSB0"). +-define(SPEED,19200). +-define(TIMEOUT,40). % Timeout in milisec +-define(REQTIMEOUT,200). + +-define(STARTBIT,[16#5B,16#AD]). +-define(STOPBIT,[16#A4,16#52]). +-define(REP,16#FF). + +rsbuslistener(Pid) -> + SerialPort = serial:start([{speed,?SPEED},{open,?DEVICE}]), + register(?MODULE,self()), + rsbus_listner(Pid,SerialPort). + +rsbus_parity(Msg) -> + lists:foldl(fun (X,P) -> X bxor P end,0,Msg). + +rsbus_rec([],ok,Msg,[]) -> + {stat,lists:reverse(tl(Msg)),hd(Msg)}; +rsbus_rec([H1,H2|Tail],read,Msg,[H1,H2]) -> + rsbus_rec([],ok,Msg,[]); +rsbus_rec([H1,H2,H3|Tail],read,Msg,Cmp) -> + rsbus_rec([H2,H3|Tail],read,[H1|Msg],Cmp); +rsbus_rec([H1,H2,H3,H4|Tail1],wait,[],[H1,H2,H3,H4]) -> + rsbus_rec(Tail1,read,[],?STOPBIT); +rsbus_rec([H|Tail],wait,[],Cmp) -> + rsbus_rec(Tail,wait,[],Cmp); +rsbus_rec(Rec,State,Msg,Cmp) -> + receive + {data, Bytes} -> + erlang:display(binary_to_list(Bytes)), + rsbus_rec(Rec++binary_to_list(Bytes),State,Msg,Cmp) + after ?TIMEOUT -> + {error,timeout} + end. + +rsbus_send(SerialPort,Addr,Msg) -> + %% Return {stat,Type,Stat} upon success + %% else return {error,timeout|parse} + SerialPort ! {send,?STARTBIT}, + SerialPort ! {send,[Addr]}, + SerialPort ! {send,Msg}, + P=rsbus_parity(Msg) bxor Addr, + SerialPort ! {send,[P]}, + SerialPort ! {send,?STOPBIT}, + io:format("Send Complete!\n"), + case rsbus_rec([],wait,[],?STARTBIT++[0,Addr]) of + {stat,[?REP],RP} -> rsbus_send(SerialPort,Addr,Msg); % Will resend no matter what + {stat,Stat,RP} -> + erlang:display(RP), + TestP =rsbus_parity([RP|Stat]), + if + TestP /= Addr -> {err,parse}; + true -> {stat,hd(Stat),tl(Stat)} + end; + {error,timeout} -> {error,timeout} + end. + + +%% This function can effectively serialize access +rsbus_listner(Pid,SerialPort) -> + erlang:display(self()), + receive + {data, _Bytes} -> + %% This shouldn't happen, no process should initiate comm + %% Discard everything + rsbus_listner(Pid,SerialPort); + {PPid,comm,Addr,Msg} -> + io:format("RSBus sending..."), + PPid ! {self(),device,Addr,rsbus_send(SerialPort,Addr,Msg)}, % Process and return + rsbus_listner(Pid,SerialPort); + {Pid,shutdown} -> + SerialPort ! stop, + ok + end. + +rsbusloop(Pid) -> + receive + {'EXIT',Pid,Cond} when Cond == normal; Cond==shutdown -> rsbusloop(spawn_link(?MODULE,rsbuslistener,[self()])); + {PPid,shutdown} -> Pid ! {self(),shutdown} + end. + +rsbusmon() -> + process_flag(trap_exit,true), + Pid = spawn_link(?MODULE,rsbuslistener,[self()]), + rsbusloop(Pid). + +rsbusreq(Addr,Msg) -> + rsbusserv ! {self(),comm,Addr,Msg}, + receive + {PPid,device,Addr,{error,Reason}} -> + {error,Reason}; + {PPid,device,Addr,{stat,Type,Msg}} -> + {stat,Type,Msg} + after ?REQTIMEOUT -> + {error,timeout} + end. + +start() -> + spawn(?MODULE,rsbusmon,[]).
\ No newline at end of file |