The task of my project is manipulation of fanuc robot by voice...the problem is in my second code in karel on robot controller...first,after robot gets his command in the form of integer over tcp/ip,somehow it store it in a buffer,so next time i start program it run command from last session without worning..and that can be very dangerous...so i found in karel procedure BYTES_AHEAD and try to purge port,but it won't work.Next problem is in condition loop...i have tried to run more than one command as long there is server connection with loop REPEAT...UNTIL..but that won't work too.Please I need help..don't know what do next...thank you all in advance!Here is my code in karel...
PROGRAM nikola
%NOLOCKGROUP
%NOPAUSE = ERROR + COMMAND + TPENABLE
VAR
i,n,tmp_int,STATUS:INTEGER
file_var:FILE
vox_str:STRING[128]
stat,n_bytes,entry,prog_index:INTEGER
FINISHED:BOOLEAN
----------------------VANJSKE RUTINE-------------------------
ROUTINE OPEN_FILE_(FILE_ : FILE; TAG_ : STRING) FROM LIB_FILE
ROUTINE CLOSE_FILE_(FILE_ : FILE; TAG_ : STRING) FROM LIB_FILE
ROUTINE WRITE_(STRING_ : STRING) FROM LIB_FILE
ROUTINE HANDSHAKING_(ID_ : STRING; TIP_: STRING) FROM LIB_FILE
--------------------------------------------------------------
BEGIN
SET_FILE_ATR(file_var, ATR_IA)
--set the server port BEFORE doing a CONNECT
SET_VAR(entry, '*SYSTEM*','$HOSTS_CFG[5].$SERVER_PORT',12350,STATUS)
stat=SET_PORT_ATR (PORT_1, ATR_READAHD,1)
--Spajanje tag-a
WRITE TPDISPLAY('Uspostava veze sa R2...',CR)
CLOSE_FILE_(file_var,'S5:')
OPEN_FILE_(file_var,'S5:')
IF IO_STATUS(file_var)<>0--inpput,output,value have to be 0 if there is connection established
THEN FINISHED=TRUE
ENDIF
REPEAT
BYTES_AHEAD (file_var, n_bytes, STAT)--catching number of bytes ready to be read
IF (n_bytes >= 1) THEN --if there is byres to be read
READ file_var(vox_str::1) --read byte by byte
stat=IO_STATUS (file_var) --status of operation
ENDIF
UNTIL stat <> 0 --continue until there is no bytes
REPEAT
FINISHED=FALSE
--Reading Command "Robovox go up"
REPEAT
BYTES_AHEAD (file_var, n_bytes, STAT)--catching number of bytes ready to be read
IF (n_bytes >= 1) THEN --if there is byres to be read
READ file_var(vox_str::1) --read byte by byte
stat=IO_STATUS (file_var) --status of operation
ENDIF
UNTIL stat <> 0 --continue until there is no bytes
--
IF (n_bytes = 0) THEN --is there is no bytes
READ file_var(vox_str::3)
ENDIF
IF UNINIT(vox_str) THEN
vox_str=''
ENDIF
IF (vox_str='120') THEN
CALL_PROG('NIK_UP',prog_index)
ENDIF
--Reading command "Robovox go down"
REPEAT
BYTES_AHEAD (file_var, n_bytes, STAT)--catching number of bytes ready to be read
IF (n_bytes >= 1) THEN --if there is byres to be read
READ file_var(vox_str::1) --read byte by byte
stat=IO_STATUS (file_var) --status of operation
ENDIF
UNTIL stat <> 0 --continue until there is ni bytes
--
IF (n_bytes = 0) THEN --if there is no bytes
READ file_var(vox_str::3)
ENDIF
IF (vox_str='130') THEN
ENDIF
CALL_PROG('NIK_DOWN',prog_index)
ENDIF
UNTIL (FINISHED=TRUE)
END nikola
I use this routine for init the buffer:
ROUTINE init_buffer
BEGIN
WRITE('init buffer',CR)
n_bytes=0
REPEAT
BYTES_AHEAD (file_var, n_bytes, STATUS) --Get number of bytes ready to be read
WRITE('remaining byte:',n_bytes,' STATUS ',STATUS, CR)
IF (n_bytes >= 1) THEN --there are bytes to be read
IF n_bytes>128 THEN
READ file_var(init_bufs::128)
STATUS=IO_STATUS (rs232) --get the status of the read operation
else
READ file_var(init_bufs::n_bytes)
STATUS=IO_STATUS (rs232) --get the status of the read operation
ENDIF
ENDIF
UNTIL n_bytes = 0 --continue until no more bytes are left
END init_buffer
The code you posted is difficult to read (lack of indentation), and some looks
odd (e.g., near the end: if (vox_str = '130') then endif
So...this is a more generic reply.
Try adding code to initialize your variables at the start and see if the problem
disappears. If it does, that implies there's some path through the code that
wasn't setting one or more of them.
i := 0;
n := 0;
vox_str := '';
stat := 0;
n_bytes := 0;
entry := 0;
prog_index := 0;
You may also want to read http://www.allegro.com/papers/htpp.html
Related
I get the following when communicating with a custom client.
With custom client i mean a housemade PCB with a FPGA which runs the Triple-Speed Ethernet Intel FPGA IP. It does not make a difference if a switch is between the PC and the PCB.
Workflow seen from the Server(Windows PC) where i detect this behaviour with wireshark:
Connect to client (Syn - Syn/Ack - Ack) Winsock2.connect
Sending data > MTU with Winsock2.WSASend (4092 Bytes on a 4088 Bytes MTU)
Packet gets "fragmented" into 2 packets - do not fragment bit is set
A Retransmission happens (because the client answered too slow?)
I am using delphi 10.4 and use the Winsock2 functions. Bevore each send i check with select if fdwrite is set if FD_Isset. Nagle is deactivated.
The "retransmission" does not happen everytime and i could not detect any sort of pattern when they occur. Except most of the time it is when the client needs more than 30ms to send his ACK.
When the "retransmission" happens it is not packet 1 or two whicht is re-send, but packet 1 with an offset of 60 which is the payload of packet 2. The sequence number of packet 1 is incremented by 60 too. Even the data is correct, it's correctly incremented by 60.
When I send 6000 Bytes i get the same behaviour with an incremented seq of 1968 which is correct too.
What is happening here?
Can i detect this with winsock2? Can i set the RTO with winsock? Why is the sequence number incremented and not packet 1, as it is, retransmitted?
Source Code of the send function:
function TZWinTCPSock.SendData (out ErrMsg : TAPILogStruct; SendOffset :
Cardinal = 0) : Boolean;
var
WSABuff : WSABUF;
res : Integer;
IPFlags : Cardinal;
t : Cardinal;
WSAErr : Cardinal;
begin
Result := FALSE;
WSAErr := WSAGetLastError;
try
if not CheckSockValid(ErrMsg) then // checks if fd_write is set
begin
exit(false);
end;
try
WSABuff.len := FMem.SendLength; // 4092 at this time Cardinal
WSABuff.buf := #FMem.SendData[SendOffset]; // 8192 Bytes reserved TArray<Byte>
IPFlags := 0;
res := WSASend(FSocket,#WSABuff,1,FMem.sentBytes,IPFlags,nil,nil);
if Res <> SOCKET_ERROR then
begin
if FMem.SendLength <> FMem.SentBytes then
begin
exit(false);
end
else
begin
Result := TRUE;
if WSAGetLastError <> WSAErr then // unexpected WSA error
begin
exit(FALSE);
end;
end;
end
else
begin
FLastWSAErr := WSAGetLastError;
if FLastWSAErr = WSAECONNRESET then
begin
Disconnect(ErrMsg);
exit(false);
end;
end;
except
on E : Exception do
begin
// Some error handling
end;
end;
finally
end;
end;
Edit1
The packets have the don't fragment Bit set.
I tried to detect this "retransmission" with the windows admin center, but I don't see anything popping up.
Got an answer on Microsoft Q&A.
Looks like it was a tail loss probe problem where the destination host is at fault, because the reply took too long and srtt timed out.
I'm trying to read from a text file in my synthesis code. However, I get an error when I try to open a file that does exist.
I have tried placing the text file in various folders because I figured the problem was that the program is unable to find the text file. None of these different positions have worked.
type chunk is array (INPUTNUM downto 0) of std_logic_vector (WIDTH-1 downto 0);
impure function ReadfromFile (FileName: in string) return chunk is
FILE IN_FILE : text open read_mode is FileName;
variable BUFF : line;
variable val : chunk;
begin
for i in 0 to INPUTNUM loop
readline (IN_FILE, BUFF);
read (BUFF, val(i));
end loop;
return val;
end function;
signal w : chunk := ReadfromFile("neuron_text.txt");
I expected the file to be read and the values to be stored in the w signal. However, when I run the RTL analysis I get the error : "[Synth 8-3302] unable to open file 'neuron_text.txt' in 'r' mode" as well as "[Synth 8-421] mismatched array sizes in rhs and lhs of assignment". I assume the second error is a result of the first one though.
Vivado runs four, five or six levels of hierarchy lower down than you think (depending on the version you're running). Try:
signal w : chunk := ReadfromFile("../../../../neuron_text.txt");
or
signal w : chunk := ReadfromFile("../../../../../neuron_text.txt");
or even
signal w : chunk := ReadfromFile("../../../../../../neuron_text.txt");
If this still doesn't work, try opening a file for writing, seeing where it gets creating and using that information to your advantage.
I need to get the length of a text file in Vivado during simulation. I tried below piece of code but I got an error.
file my_input : TEXT open READ_MODE is "/home/sukru/MD5.dat";
variable my_line : LINE;
variable input_line : LINE;
variable length : integer;
readline(my_input, input_line);
read(input_line, length);
writeline(output, input_line); -- optional, write to std out
write(input_line, integer'(length));
writeline(output, input_line);
The error message is this.
Error: TEXTIO function READ: read a non-integer, an integer is expected
a
-2147483648
I can read text's index but the length is non-sense value. Someone direct me how can I get the length of any text file.
VHDL at present has no way of interfacing to the host operating system to determine a file length.
There's an equivalency between bytes and the VHDL type character (see IEEE Std 1076-2008).
Normative references
...
ISO/IEC 8859-1:1998, Information technology—8-bit single-byte coded graphic character sets—Part 1: Latin alphabet No. 1.
Also see 16.3 Package standard, type character where all 256 enumeration values for a single-byte character are included.
That means we can count characters in a file:
use std.textio.all;
entity length_in_bytes is
end entity;
architecture foo of length_in_bytes is
impure function file_length (file_name: string) return integer is
type char_file is file of character;
file file_in: char_file open read_mode is file_name;
variable char_buffer: character;
variable length: integer := 0;
begin
while not ENDFILE(file_in) loop
read(file_in, char_buffer);
length := length + 1;
end loop;
file_close(file_in);
-- report file_name & " length = " & integer'image(length);
return length;
end function;
signal filelength: natural;
begin
filelength <= file_length("md5.dat");
process
begin
wait for 0 ns; -- skip default signal value;
report "file md5.dat length = " & integer'image(filelength);
wait;
end process;
end architecture;
The length returned by the function call will match the length the host operating system provides.
The file_close leaves the file unlocked for further use and reads of an open file are sequential from file open.
This line reads a line from the file:
readline(my_input, input_line);
This line tries to read an integer (destructively) from the line:
read(input_line, length);
It doesn't return the length of the file (or the line). You don't supply the file you are trying to read (it would have been better had you done so - see this ), but my guess is that it doesn't contain an integer and hence your error message.
If you want to get the length of any text file, you need to read every line in the file, find each's length and add them. It is easy to find the length of each line, because type line does have a 'length attribute, so the length of each line will be:
input_line'length
(Though note that the 'length attribute does not include the end-of-line character.) By the way, this line won't display what you've just read, because the read (if successful) is destructive:
writeline(output, input_line); -- optional, write to std out
(A "destructive read" is a read which removes the data as well as reading it.)
Here is my eiffel program, which is basically doing space removal (remove the redundant spaces in a given text file) to follow the regular expresson: A+(SA+)*EOL, where for each line in the file, it must start with alphabets and only one spaces between alphabets.
My question is, base on this program, how can I extend it to make every other word to be uppercase? i.e. 2th, 4th, 6th, etc.
feature {NONE} -- Main routine
copy_file
-- Copy a file character by character from input to output
require
input_open: input.is_readable
output_open: output.is_writable
local flag: INTEGER
has_read_space: BOOLEAN
empty_line : BOOLEAN
do
empty_line: True
flag := 0 -- 0 for previous space, 1 for previous char
from read_char -- Must prime the pump by reading the first character
until ch = EOF
loop
from
ch := input.last_character
until
ch = EOL
loop
if ch = Space_char and flag = 0 then -- leading spaces
read_char
elseif ch /= Space_char and flag = 0 then -- see first charater after space
if has_read_space then -- this clause make sure the space will only place in between two words instead of end of lin
output.putchar (Space_char)
end
output.putchar (ch)
empty_line := False
flag := 1
read_char
elseif ch = Space_char and flag = 1 then -- see space after characters
has_read_space := True -- Don't output it right away
flag := 0
read_char
elseif ch /= Space_char and flag = 1 then -- see character after character
output.putchar (ch)
read_char
end
end
if empty_line = False then
output.putchar (EOL) -- if line is not empty, then we place EOL at the end of line
end
flag := 0 -- reset it to 0 to make sure the next follow the same routine
has_read_space := False -- reset it to avoid placing space in the beginning of line
empty_line := True -- reset to proceed to new line
read_char
end
-- At end of file, nothing to do in Eiffel except close the files
input.close
output.close
end
Just figured it out.
Simply set another flag, say evenWord, initialize it to be false.
and in the elseif ch = Space_char and flag = 1 clause flip the flag evenWord := not evenWord It works
I am working on a particular scenario, where I have to read from a Text File, parse it, extract meaningful information from it, perform SQL queries with the information and then produce a reponse, output file.
I have about 3000 lines of code. Everything is working as expected. However I have been thinking of a connendrum that could possibly dissrupt my project.
The text file being read (lets call it Text.txt) may consist of a single line or multiple lines.
In my case, a 'line' is identified by its segment name - say ISA, BHT, HB, NM1, etc... each segment ending is identified by a special character '~'.
Now if the file consists of multiple lines (such that each line corresponds to a single segment); say:-
ISA....... ~
NM1....... ~
DMG....... ~
SE........ ~
and so on.... then my code essentially reads each 'line' (i.e. each segment), one at a time and stores it into a temp buffer using the following command :-
ReadLn(myFile,buffer);
and then performs evaluations based on each line. Produces the desired output. No problems.
However the issue is... what if the file consists of only a single line (consisting of multiple segments), represented as:-
ISA....... ~NM1....... ~DMG....... ~SE........ ~
then with my ReadLine command I read the entire line instead of each segment, one at a time. This doesn't work for my code.
I was thinking about creating an if, else statement pair...which is based on how many lines my Txt.txt file consists of..such as:-
if line = 1:-
then extract each segment at a time...seperated by the special character '~'
perform necessary tasks (3000 lines of code)
else if line > 1:-
then extract each line at a time (corresponding to each segment)
perform necessary tasks (3000 lines of code).
now the 3000 lines of code is repeated twice and I don't find it elegant to copy and paste all of that code twice.
I would appreciate if I could get some feedback on how to possibly solve this issue, such that, regardless of a one-line file or multiple-line file...when i proceed to evaluate, i only use one segment at a time.
There are many possible ways of doing this. Which is best for you might depend on how long these files are and how important performance is.
A simple solution is to just read characters one at a time until you hit your tilde delimiter.
The routine ReadOneItem below shows how this can be done.
procedure TForm1.Button1Click(Sender: TObject);
const
FileName = 'c:\kuiper\test2.txt';
var
MyFile : textfile;
Buffer : string;
// Read one item from text file MyFile.
// Load characters one at a time.
// Ignore CR and LF characters
// Stop reading at end-of-file, or when a '~' is read
function ReadOneItem : string;
var
C : char;
begin
Result := '';
// loop continues until break
while true do
begin
// are we at the end-of-file? If so we're done
if eof(MyFile) then
break;
// read in the next character
read ( MyFile, C );
// ignore CR and LF
if ( C = #13 ) or ( C = #10 ) then
{do nothing}
else
begin
// add the character to the end
Result := Result + C;
// if this is the delimiter then stop reading
if C = '~' then
break;
end;
end;
end;
begin
assignfile ( MyFile, FileName );
reset ( MyFile );
try
while not EOF(MyFile) do
begin
Buffer := ReadOneItem;
Memo1 . Lines . Add ( Buffer );
end;
finally
closefile ( MyFile );
end;
end;
I would use a file mapping via the Win32 API CreateFileMapping() and MapViewOfFile() functions, and then just parse the raw data as-is, scanning for ~ characters and ignoring any line breaks you might encounter in between each segment. For example:
var
hFile: THandle;
hMapping: THandle;
pView: Pointer;
FileSize, I: DWORD;
pSegmentStart, pSegmentEnd: PAnsiChar;
sSegment: AnsiString;
begin
hFile := CreateFile('Path\To\Text.txt', GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
if hFile = INVALID_HANDLE_VALUE then RaiseLastOSError;
try
FileSize := GetFileSize(hFile, nil);
if FileSize = INVALID_FILE_SIZE then RaiseLastOSError;
if FileSize > 0 then
begin
hMapping := CreateFileMapping(hFile, nil, PAGE_READONLY, 0, FileSize, nil);
if hMapping = 0 then RaiseLastOSError;
try
pView := MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, FileSize);
if pView = nil then RaiseLastOSError;
try
pSegmentStart := PAnsiChar(pView);
pSegmentEnd := pSegmentStart;
I := 0;
while I < FileSize do
begin
if pSegmentEnd^ = '~' then
begin
SetString(sSegment, pSegmentStart, Integer(pSegmentEnd-pSegmentStart));
// use sSegment as needed...
pSegmentStart := pSegmentEnd + 1;
Inc(I);
while (I < FileSize) and (pSegmentStart^ in [#13, #10]) do
begin
Inc(pSegmentStart);
Inc(I);
end;
pSegmentEnd := pSegmentStart;
end else
begin
Inc(pSegmentEnd);
Inc(I);
end;
end;
if pSegmentEnd > pSegmentStart then
begin
SetString(sSegment, pSegmentStart, Integer(pSegmentEnd-pSegmentStart));
// use sSegment as needed...
end;
finally
UnmapViewOfFile(pView);
end;
finally
CloseHandle(hMapping);
end;
end;
finally
CloseHandle(hFile);
end;