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)
}
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");
struct termios tio;
......@@ -149,18 +149,23 @@ void ttyopen(CleanString fn, int baudrate, int bytesize, int parity,
//Set
tio.c_oflag = 0;
tio.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
// tio.c_lflag |= ICANON;
#ifdef __APPLE__
tio.c_cflag |= CLOCAL;
#endif
tio.c_cc[VMIN]=5;
tio.c_cc[VMIN]=1;
tio.c_cc[VTIME]=0;
tcsetattr(*fd, TCSANOW, &tio);
*status = 1;
error = strerror(errno);
}
if(sleepTime > 0){
sleep(sleepTime);
tcflush(*fd, TCIOFLUSH);
}
free(cs_fn);
debug("ttyopen-done");
}
......@@ -191,18 +196,29 @@ void ttyread(int fd, int *ch, int *fdo)
debug("ttyread done");
}
void ttyavailable(int fd, int *r, int *fdo)
void ttyavailable(int fd, int *r, int *e, int *fdo)
{
// debug("ttyavailable");
fd_set fds;
fd_set rfds, efds;
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(fd, &fds);
FD_ZERO(&rfds);
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)
die("select");
*fdo = fd;
......@@ -215,7 +231,7 @@ int ttywrite(CleanString s, int fd)
int i;
for(i = 0; i< CleanStringLength(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));
tcdrain(fd);
......
......@@ -16,18 +16,99 @@ from StdClass import class zero
bytesize :: ByteSize,
parity :: Parity,
stop2bits :: Bool,
xonxoff :: Bool
xonxoff :: Bool,
//Set this to 2 if you want to connect to a borked arduino
sleepTime :: Int
}
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)
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)
/**
* Reads the error from the tty library
*
* @param world
* @result Error
* @result new world
*/
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)
/**
* Read a byte from a tty
*
* @param tty handle
* @param world
* @result byte
* @result new tty handle
*/
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)
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
......@@ -21,7 +21,8 @@ instance zero TTYSettings where
bytesize = BytesizeEight,
parity = ParityNone,
stop2bits = False,
xonxoff = False}
xonxoff = False,
sleepTime = 0}
instance toInt BaudRate where
toInt b = case b of
......@@ -49,9 +50,9 @@ getTTYDevices w
where
isTTY s = not (isEmpty (filter (flip startsWith s) ["tty", "rfcomm"]))
makeTTYSettings :: String BaudRate ByteSize Parity Bool Bool -> TTYSettings
makeTTYSettings dp br bs pr sb xx = {TTYSettings | devicePath=dp, baudrate=br,
bytesize=bs, parity=pr, stop2bits=sb, xonxoff=xx}
makeTTYSettings :: String BaudRate ByteSize Parity Bool Bool Int -> TTYSettings
makeTTYSettings dp br bs pr sb xx st = {TTYSettings | devicePath=dp, baudrate=br,
bytesize=bs, parity=pr, stop2bits=sb, xonxoff=xx, sleepTime=st}
TTYopen :: !TTYSettings !*env -> (!Bool, !*TTY, !*env)
TTYopen ts w = TTYopen2
......@@ -61,11 +62,12 @@ TTYopen ts w = TTYopen2
(toInt ts.parity)
ts.stop2bits
ts.xonxoff
ts.sleepTime
w
where
TTYopen2 :: !String !Int !Int !Int !Bool !Bool !*env -> (!Bool, !*TTY, !*env)
TTYopen2 _ _ _ _ _ _ _ = code {
ccall ttyopen "SIIIII:VII:A"
TTYopen2 :: !String !Int !Int !Int !Bool !Bool !Int !*env -> (!Bool, !*TTY, !*env)
TTYopen2 _ _ _ _ _ _ _ _ = code {
ccall ttyopen "SIIIIII:VII:A"
}
TTYclose :: !*TTY !*env -> (!Bool, !*env)
......@@ -90,9 +92,9 @@ TTYwrite _ _ = code {
ccall ttywrite "SI:I"
}
TTYavailable :: !*TTY -> (!Bool, !*TTY)
TTYavailable :: !*TTY -> (!Bool, !Bool, !*TTY)
TTYavailable _ = code {
ccall ttyavailable "I:VII"
ccall ttyavailable "I:VIII"
}
TTYerror :: !*env -> (!String, !*env)
......
......@@ -102,7 +102,7 @@ static char *error = "";
//}
//
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
* @result Task that stops when the stop flag is set
* @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
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 opts enc dec rw = withShared "" \sh->Task $ eval sh
syncSerialChannel :: Timespec TTYSettings (b -> String) (String -> (Either String [a], String)) (Shared ([a],[b],Bool)) -> Task () | iTask a & iTask b
syncSerialChannel poll opts enc dec rw = Task eval
where
eval sh event evalOpts tree=:(TCInit taskId ts) iworld
eval event evalOpts tree=:(TCInit taskId ts) iworld
# (mtty, iworld=:{world,resources}) = getResource iworld
= case mtty of
[] = case TTYopen opts iworld.world of
......@@ -47,11 +47,11 @@ where
NoValue
{TaskEvalInfo|lastEvent=ts,removedTasks=[],refreshSensitive=True}
rep
(TCBasic taskId ts (JSONString "") False)
(TCBasic taskId ts (DeferredJSONNode $ JSONString "") False)
, 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
= case mtty of
[] = (exc"TTY resource lost", iworld)
......@@ -72,9 +72,10 @@ where
, {iworld & resources=[TTYd dp tty:resources]})
(r,s,ss)
# 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]}
= case dec (acc +++ toString newdata) of
= case dec (acc +++ toString (fromOk merr)) of
(Left err, newacc) = (exc "Error while parsing", iworld)
(Right msgs, newacc)
# (merr, iworld) = if (msgs =: [] && s =: [])
......@@ -85,10 +86,10 @@ where
NoValue
{TaskEvalInfo|lastEvent=ts,removedTasks=[],refreshSensitive=True}
rep
(TCBasic taskId ts (JSONString newacc) False)
(TCBasic taskId ts (DeferredJSONNode $ JSONString newacc) False)
, iworld)
eval _ event evalOpts tree=:(TCDestroy _) iworld=:{IWorld|resources,world}
eval event evalOpts tree=:(TCDestroy _) iworld=:{IWorld|resources,world}
# (mtty, iworld) = getResource iworld
= case mtty of
[] = (exc "This tty was already closed", iworld)
......@@ -100,14 +101,18 @@ where
= (DestroyedResult, iworld)
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))
exc = ExceptionResult o exception
readWhileAvailable :: !*TTY -> ([Char], !*TTY)
import StdMisc, StdDebug
readWhileAvailable :: !*TTY -> (MaybeError String [Char], !*TTY)
readWhileAvailable tty
# (available, tty) = TTYavailable tty
| not available = ([], tty)
# (available, error, tty) = TTYavailable tty
| error = (Error "TTY device disconnected", tty)
| not available = (Ok [], tty)
# (c, tty) = TTYread tty
# (cs, tty) = readWhileAvailable tty
= ([toChar c:cs], tty)
| not (trace_tn ("Read: " +++ toString c)) = undef
# (merr, tty) = readWhileAvailable tty
| isError merr = (merr, tty)
= (Ok [toChar c:fromOk merr], tty)
......@@ -17,7 +17,7 @@ Start w
# (ok, tty, w) = TTYopen {zero & devicePath="/dev/ttyUSB0"} w
| not ok = TTYerrorclose io w
#! tty = TTYwrite "echo123\n" tty
#! (av, tty) = TTYavailable tty
#! (av, e, tty) = TTYavailable tty
# io = io <<< ("Bytes available: " +++ toString av +++ "\n")
#! (l, tty) = TTYreadline tty
# 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