Commit 641acfba authored by Mart Lubbers's avatar Mart Lubbers

documentation and sleep time for arduino's

parent 61f95c21
...@@ -102,7 +102,7 @@ static void addTermios(int fd, struct termios *t) ...@@ -102,7 +102,7 @@ static void addTermios(int fd, struct termios *t)
} }
void ttyopen(CleanString fn, int baudrate, int bytesize, int parity, void ttyopen(CleanString fn, int baudrate, int bytesize, int parity,
int stopbits, int xonoff, int *status, int *fd) int stopbits, int xonoff, int sleepTime, int *status, int *fd)
{ {
debug("ttyopen"); debug("ttyopen");
struct termios tio; struct termios tio;
...@@ -149,18 +149,23 @@ void ttyopen(CleanString fn, int baudrate, int bytesize, int parity, ...@@ -149,18 +149,23 @@ void ttyopen(CleanString fn, int baudrate, int bytesize, int parity,
//Set //Set
tio.c_oflag = 0; tio.c_oflag = 0;
tio.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG); tio.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
// tio.c_lflag |= ICANON;
#ifdef __APPLE__ #ifdef __APPLE__
tio.c_cflag |= CLOCAL; tio.c_cflag |= CLOCAL;
#endif #endif
tio.c_cc[VMIN]=5; tio.c_cc[VMIN]=1;
tio.c_cc[VTIME]=0; tio.c_cc[VTIME]=0;
tcsetattr(*fd, TCSANOW, &tio); tcsetattr(*fd, TCSANOW, &tio);
*status = 1; *status = 1;
error = strerror(errno); error = strerror(errno);
} }
if(sleepTime > 0){
sleep(sleepTime);
tcflush(*fd, TCIOFLUSH);
}
free(cs_fn); free(cs_fn);
debug("ttyopen-done"); debug("ttyopen-done");
} }
...@@ -191,18 +196,29 @@ void ttyread(int fd, int *ch, int *fdo) ...@@ -191,18 +196,29 @@ void ttyread(int fd, int *ch, int *fdo)
debug("ttyread done"); debug("ttyread done");
} }
void ttyavailable(int fd, int *r, int *fdo) void ttyavailable(int fd, int *r, int *e, int *fdo)
{ {
// debug("ttyavailable"); // debug("ttyavailable");
fd_set fds; fd_set rfds, efds;
struct timeval tv; struct timeval tv;
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 0; tv.tv_usec = 0;
FD_ZERO(&fds); FD_ZERO(&rfds);
FD_SET(fd, &fds); FD_SET(fd, &rfds);
FD_ZERO(&efds);
FD_SET(fd, &efds);
*e = 0;
*r = select(fd+1, &rfds, NULL, &efds, &tv);
if (FD_ISSET(fd, &efds)){
*e = 1;
*fdo = fd;
return;
}
*r = select(fd+1, &fds, NULL, NULL, &tv);
if(*r == -1) if(*r == -1)
die("select"); die("select");
*fdo = fd; *fdo = fd;
...@@ -215,7 +231,7 @@ int ttywrite(CleanString s, int fd) ...@@ -215,7 +231,7 @@ int ttywrite(CleanString s, int fd)
int i; int i;
for(i = 0; i< CleanStringLength(s); i++){ for(i = 0; i< CleanStringLength(s); i++){
unsigned char c = ((unsigned char*)CleanStringCharacters(s))[i]; unsigned char c = ((unsigned char*)CleanStringCharacters(s))[i];
printf("%02x(%u) ", c, c); // printf("%02x(%u) ", c, c);
} }
write(fd, (void *)CleanStringCharacters(s), CleanStringLength(s)); write(fd, (void *)CleanStringCharacters(s), CleanStringLength(s));
tcdrain(fd); tcdrain(fd);
......
...@@ -16,18 +16,99 @@ from StdClass import class zero ...@@ -16,18 +16,99 @@ from StdClass import class zero
bytesize :: ByteSize, bytesize :: ByteSize,
parity :: Parity, parity :: Parity,
stop2bits :: Bool, stop2bits :: Bool,
xonxoff :: Bool xonxoff :: Bool,
//Set this to 2 if you want to connect to a borked arduino
sleepTime :: Int
} }
instance zero TTYSettings instance zero TTYSettings
/**
* Returns a list of tty devices. This list is not conclusive but just checks familiar names.
*
* @param The world
* @result The list of detected devices
* @result The updated world
*/
getTTYDevices :: !*World -> *(![String], !*World) getTTYDevices :: !*World -> *(![String], !*World)
makeTTYSettings :: String BaudRate ByteSize Parity Bool Bool -> TTYSettings
/**
* Smart constructor for {{`TTYSettings`}}
*
* @param devicePath
* @param baudrate
* @param parity
* @param stop2bits
* @param xonxoff
* @param sleepTime
*/
makeTTYSettings :: String BaudRate ByteSize Parity Bool Bool Int -> TTYSettings
/**
* Closes a TTY
*
* @param tty handle
* @param world
* @result Ok flag
* @result new world
*/
TTYclose :: !*TTY !*env -> (!Bool, !*env) TTYclose :: !*TTY !*env -> (!Bool, !*env)
/**
* Reads the error from the tty library
*
* @param world
* @result Error
* @result new world
*/
TTYerror :: !*env -> (!String, !*env) TTYerror :: !*env -> (!String, !*env)
/**
* Open a tty
*
* @param tty settings
* @param world
* @result Ok flag
* @result TTY handle
* @result new world
*/
TTYopen :: !TTYSettings !*env -> (!Bool,!*TTY,!*env) TTYopen :: !TTYSettings !*env -> (!Bool,!*TTY,!*env)
/**
* Read a byte from a tty
*
* @param tty handle
* @param world
* @result byte
* @result new tty handle
*/
TTYread :: !*TTY -> (!Int, !*TTY) TTYread :: !*TTY -> (!Int, !*TTY)
/**
* Read a line from the tty (up until '\n' or EOF)
*
* @param tty handle
* @param world
* @result line
* @result new tty handle
*/
TTYreadline :: !*TTY -> (!String, !*TTY) TTYreadline :: !*TTY -> (!String, !*TTY)
TTYavailable :: !*TTY -> (!Bool, !*TTY)
/**
* Checks if the TTY device is available for reading
*
* @param tty handle
* @result Data available
* @result Ok flag
* @result new tty handle
*/
TTYavailable :: !*TTY -> (!Bool, !Bool, !*TTY)
/**
* Write bytes to a TTY
*
* @param The bytes to write
* @param The tty handle
* @result new tty handle
*/
TTYwrite :: !String !*TTY -> *TTY TTYwrite :: !String !*TTY -> *TTY
...@@ -21,7 +21,8 @@ instance zero TTYSettings where ...@@ -21,7 +21,8 @@ instance zero TTYSettings where
bytesize = BytesizeEight, bytesize = BytesizeEight,
parity = ParityNone, parity = ParityNone,
stop2bits = False, stop2bits = False,
xonxoff = False} xonxoff = False,
sleepTime = 0}
instance toInt BaudRate where instance toInt BaudRate where
toInt b = case b of toInt b = case b of
...@@ -49,9 +50,9 @@ getTTYDevices w ...@@ -49,9 +50,9 @@ getTTYDevices w
where where
isTTY s = not (isEmpty (filter (flip startsWith s) ["tty", "rfcomm"])) isTTY s = not (isEmpty (filter (flip startsWith s) ["tty", "rfcomm"]))
makeTTYSettings :: String BaudRate ByteSize Parity Bool Bool -> TTYSettings makeTTYSettings :: String BaudRate ByteSize Parity Bool Bool Int -> TTYSettings
makeTTYSettings dp br bs pr sb xx = {TTYSettings | devicePath=dp, baudrate=br, makeTTYSettings dp br bs pr sb xx st = {TTYSettings | devicePath=dp, baudrate=br,
bytesize=bs, parity=pr, stop2bits=sb, xonxoff=xx} bytesize=bs, parity=pr, stop2bits=sb, xonxoff=xx, sleepTime=st}
TTYopen :: !TTYSettings !*env -> (!Bool, !*TTY, !*env) TTYopen :: !TTYSettings !*env -> (!Bool, !*TTY, !*env)
TTYopen ts w = TTYopen2 TTYopen ts w = TTYopen2
...@@ -61,11 +62,12 @@ TTYopen ts w = TTYopen2 ...@@ -61,11 +62,12 @@ TTYopen ts w = TTYopen2
(toInt ts.parity) (toInt ts.parity)
ts.stop2bits ts.stop2bits
ts.xonxoff ts.xonxoff
ts.sleepTime
w w
where where
TTYopen2 :: !String !Int !Int !Int !Bool !Bool !*env -> (!Bool, !*TTY, !*env) TTYopen2 :: !String !Int !Int !Int !Bool !Bool !Int !*env -> (!Bool, !*TTY, !*env)
TTYopen2 _ _ _ _ _ _ _ = code { TTYopen2 _ _ _ _ _ _ _ _ = code {
ccall ttyopen "SIIIII:VII:A" ccall ttyopen "SIIIIII:VII:A"
} }
TTYclose :: !*TTY !*env -> (!Bool, !*env) TTYclose :: !*TTY !*env -> (!Bool, !*env)
...@@ -90,9 +92,9 @@ TTYwrite _ _ = code { ...@@ -90,9 +92,9 @@ TTYwrite _ _ = code {
ccall ttywrite "SI:I" ccall ttywrite "SI:I"
} }
TTYavailable :: !*TTY -> (!Bool, !*TTY) TTYavailable :: !*TTY -> (!Bool, !Bool, !*TTY)
TTYavailable _ = code { TTYavailable _ = code {
ccall ttyavailable "I:VII" ccall ttyavailable "I:VIII"
} }
TTYerror :: !*env -> (!String, !*env) TTYerror :: !*env -> (!String, !*env)
......
...@@ -102,7 +102,7 @@ static char *error = ""; ...@@ -102,7 +102,7 @@ static char *error = "";
//} //}
// //
void ttyopen(CleanString fn, int baudrate, int bytesize, int parity, void ttyopen(CleanString fn, int baudrate, int bytesize, int parity,
int stopbits, int xonoff, int *status, int *fd) int stopbits, int xonoff, int sleepTime, int *status, int *fd)
{ {
} }
......
...@@ -17,4 +17,4 @@ derive class iTask TTYSettings ...@@ -17,4 +17,4 @@ derive class iTask TTYSettings
* @result Task that stops when the stop flag is set * @result Task that stops when the stop flag is set
* @throws TTYException * @throws TTYException
*/ */
syncSerialChannel :: TTYSettings (b -> String) (String -> (Either String [a], String)) (Shared ([a],[b],Bool)) -> Task () | iTask a & iTask b syncSerialChannel :: Timespec TTYSettings (b -> String) (String -> (Either String [a], String)) (Shared ([a],[b],Bool)) -> Task () | iTask a & iTask b
...@@ -30,10 +30,10 @@ import iTasks.Internal.TaskEval ...@@ -30,10 +30,10 @@ import iTasks.Internal.TaskEval
derive class iTask TTYSettings, Parity, BaudRate, ByteSize derive class iTask TTYSettings, Parity, BaudRate, ByteSize
syncSerialChannel :: TTYSettings (b -> String) (String -> (Either String [a], String)) (Shared ([a],[b],Bool)) -> Task () | iTask a & iTask b syncSerialChannel :: Timespec TTYSettings (b -> String) (String -> (Either String [a], String)) (Shared ([a],[b],Bool)) -> Task () | iTask a & iTask b
syncSerialChannel opts enc dec rw = withShared "" \sh->Task $ eval sh syncSerialChannel poll opts enc dec rw = Task eval
where where
eval sh event evalOpts tree=:(TCInit taskId ts) iworld eval event evalOpts tree=:(TCInit taskId ts) iworld
# (mtty, iworld=:{world,resources}) = getResource iworld # (mtty, iworld=:{world,resources}) = getResource iworld
= case mtty of = case mtty of
[] = case TTYopen opts iworld.world of [] = case TTYopen opts iworld.world of
...@@ -47,11 +47,11 @@ where ...@@ -47,11 +47,11 @@ where
NoValue NoValue
{TaskEvalInfo|lastEvent=ts,removedTasks=[],refreshSensitive=True} {TaskEvalInfo|lastEvent=ts,removedTasks=[],refreshSensitive=True}
rep rep
(TCBasic taskId ts (JSONString "") False) (TCBasic taskId ts (DeferredJSONNode $ JSONString "") False)
, iworld) , iworld)
_ = (exc "This tty was already open", iworld) _ = (exc "This tty was already open", iworld)
eval _ _ _ tree=:(TCBasic taskId ts (JSONString acc) _) iworld eval _ _ tree=:(TCBasic taskId ts (DeferredJSONNode (JSONString acc)) _) iworld
# (mtty, iworld) = getResource iworld # (mtty, iworld) = getResource iworld
= case mtty of = case mtty of
[] = (exc"TTY resource lost", iworld) [] = (exc"TTY resource lost", iworld)
...@@ -72,9 +72,10 @@ where ...@@ -72,9 +72,10 @@ where
, {iworld & resources=[TTYd dp tty:resources]}) , {iworld & resources=[TTYd dp tty:resources]})
(r,s,ss) (r,s,ss)
# tty = foldr TTYwrite tty $ reverse $ map enc s # tty = foldr TTYwrite tty $ reverse $ map enc s
# (newdata, tty) = readWhileAvailable tty # (merr, tty) = readWhileAvailable tty
| isError merr = (exc (fromError merr), iworld)
# iworld = {iworld & resources=[TTYd dp tty:iworld.resources]} # iworld = {iworld & resources=[TTYd dp tty:iworld.resources]}
= case dec (acc +++ toString newdata) of = case dec (acc +++ toString (fromOk merr)) of
(Left err, newacc) = (exc "Error while parsing", iworld) (Left err, newacc) = (exc "Error while parsing", iworld)
(Right msgs, newacc) (Right msgs, newacc)
# (merr, iworld) = if (msgs =: [] && s =: []) # (merr, iworld) = if (msgs =: [] && s =: [])
...@@ -85,10 +86,10 @@ where ...@@ -85,10 +86,10 @@ where
NoValue NoValue
{TaskEvalInfo|lastEvent=ts,removedTasks=[],refreshSensitive=True} {TaskEvalInfo|lastEvent=ts,removedTasks=[],refreshSensitive=True}
rep rep
(TCBasic taskId ts (JSONString newacc) False) (TCBasic taskId ts (DeferredJSONNode $ JSONString newacc) False)
, iworld) , iworld)
eval _ event evalOpts tree=:(TCDestroy _) iworld=:{IWorld|resources,world} eval event evalOpts tree=:(TCDestroy _) iworld=:{IWorld|resources,world}
# (mtty, iworld) = getResource iworld # (mtty, iworld) = getResource iworld
= case mtty of = case mtty of
[] = (exc "This tty was already closed", iworld) [] = (exc "This tty was already closed", iworld)
...@@ -100,14 +101,18 @@ where ...@@ -100,14 +101,18 @@ where
= (DestroyedResult, iworld) = (DestroyedResult, iworld)
rep = ReplaceUI $ stringDisplay $ "Serial client " <+++ opts.devicePath rep = ReplaceUI $ stringDisplay $ "Serial client " <+++ opts.devicePath
ticker = sdsFocus {start=zero,interval=zero} iworldTimespec ticker = sdsFocus {start=zero,interval=poll} iworldTimespec
getResource = iworldResource (\t=:(TTYd p _)->(p == opts.devicePath, t)) getResource = iworldResource (\t=:(TTYd p _)->(p == opts.devicePath, t))
exc = ExceptionResult o exception exc = ExceptionResult o exception
readWhileAvailable :: !*TTY -> ([Char], !*TTY) import StdMisc, StdDebug
readWhileAvailable :: !*TTY -> (MaybeError String [Char], !*TTY)
readWhileAvailable tty readWhileAvailable tty
# (available, tty) = TTYavailable tty # (available, error, tty) = TTYavailable tty
| not available = ([], tty) | error = (Error "TTY device disconnected", tty)
| not available = (Ok [], tty)
# (c, tty) = TTYread tty # (c, tty) = TTYread tty
# (cs, tty) = readWhileAvailable tty | not (trace_tn ("Read: " +++ toString c)) = undef
= ([toChar c:cs], tty) # (merr, tty) = readWhileAvailable tty
| isError merr = (merr, tty)
= (Ok [toChar c:fromOk merr], tty)
...@@ -17,7 +17,7 @@ Start w ...@@ -17,7 +17,7 @@ Start w
# (ok, tty, w) = TTYopen {zero & devicePath="/dev/ttyUSB0"} w # (ok, tty, w) = TTYopen {zero & devicePath="/dev/ttyUSB0"} w
| not ok = TTYerrorclose io w | not ok = TTYerrorclose io w
#! tty = TTYwrite "echo123\n" tty #! tty = TTYwrite "echo123\n" tty
#! (av, tty) = TTYavailable tty #! (av, e, tty) = TTYavailable tty
# io = io <<< ("Bytes available: " +++ toString av +++ "\n") # io = io <<< ("Bytes available: " +++ toString av +++ "\n")
#! (l, tty) = TTYreadline tty #! (l, tty) = TTYreadline tty
# io = io <<< ("Line read: " +++ l) # io = io <<< ("Line read: " +++ l)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment