VaBuffer Data Capture Example

I am looking for a demo/example of how to use VaBuffer to capture a data packet. The packet starts with the $ character and is 738 bytes long. I cannot use VaCapture as there are null values in the packet.
Below is the packet I want to capture.
Ray.
 
24 02 E2
20 55 73 65 72 20 44 65 66 69 6E 65 64 20 20 20 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 03 03 02 02 02 02 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 01 01 01 01 01 00 00 00 00 00 00 00 00
00 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 02 E4 7E
This is some sample code:

type
  TCapturestate = (csNone, csCaptureStart, csCaptureEnd);
var
  cs: TCaptureState;
  sig_start, sig_end: byte;
  b: byte;
  buffer: array[0..737] of byte;
  i: integer;
begin
  cs := csNone;
  sig_start := $24;
  sig_end := $7E;
  i := 0;

  while cs <>  csCaptureEnd do
  begin
    if vacomm1.ReadBufUsed > 0 then
    begin
      vacomm1.ReadBuf(b,1);

      case cs of
      csCaptureStart:
        begin
          if b = sig_end then
            cs := csCaptureEnd
          else
          begin
            buffer := b;
            inc(i);
          end;
        end;
      csNone:
        if (b = sig_Start) then
          cs := csCaptureStart;
      end;

      application.ProcessMessages;
    end;
  end;

  if i = 737 then
    // full packet was received
end;

I am missing something, as I am getting garbage. Also I get a lockup when disconnecting the VaComm

 
Ray.
 
type
  TCapturestate = (csNone, csCaptureStart, csCaptureEnd);
 
var     // Global varaialbes
  cs: TCaptureState;
  RxData: array[0..1000] of byte;
 
procedure TSymCommsDlg.VaComm1RxChar(Sender: TObject; Count: Integer);
 var
   sig_start, sig_end: byte;
   b: byte;
   i: integer;
begin
  cs := csNone;
  sig_start := $24;
  sig_end := $7E;
  i := 0;

  while cs <>  csCaptureEnd do begin
    if vacomm1.ReadBufUsed > 0 then  begin
      vacomm1.ReadBuf(b,1);
      case cs of
        csCaptureStart: begin
                          if b = sig_end then
                            cs := csCaptureEnd
                          else begin
                            RxData := b;
                            inc(i);
                          end;
                        end;
                csNone: if (b = sig_Start) then
                          cs := csCaptureStart;
      end;
      application.ProcessMessages;
      ProcessData;
    end;
  end;
end;
 
 
I have it working, but I am not getting all the bytes. I am missing the first byte ($02),
 
I get   E2 20 55 73 65 72 20 44 65 etc...
when it should be 02 E2 20 55 73 65 72 20 44 65 etc...
 
Below is the code used.
 
I wish TMS would add a capture VCL that would capture this type of data correctly. I just do not want to have to learn how to write my own comms code. I am happy to pay for you to do this.
 
Ray.
 
type
  TCapturestate = (csNone, csCaptureStart, csCaptureEnd);
 
var
   RxData: array[1..1000] of Byte;
 
procedure TSymCommsDlg.VaComm1RxChar(Sender: TObject; Count: Integer);
begin
   if Count >= 742 then begin
     GetData;
   end;
end;

procedure TSymCommsDlg.GetData;
var
  cs: TCaptureState;
  sig_start, sig_end: byte;
  b: byte;
  i: integer;
begin
   cs := csNone;
   sig_start := $24;
   sig_end := $7E;
   i := 0;

  while cs <>  csCaptureEnd do begin
    if vacomm1.ReadBufUsed > 0 then begin
      vacomm1.ReadBuf(b,1);

      case cs of
      csCaptureStart: begin
                        if b = sig_end then
                           cs := csCaptureEnd
                        else begin
                           RxData := b;
                           inc(i);
                        end;
                      end;

              csNone: if (b = sig_Start) then
                        cs := csCaptureStart;

      end;
      application.ProcessMessages;
    end;
  end;
  ProcessData;
end;

First of all, I don't understand if this code would compile at all. An assignment like 

 RxData := b;
should certainly fail. I see your array starts from index 1, i starts from index 0. If your array starts from index 1 you should set the first byte in RxData[1]

Bruno,

 
That was just a typo on this forum..
 
It is now working after I changed i:= 0 to I:=1

Bruno,

 
Is there a better way to check the data is in the buffer, then counting using the RxChar event.
 
Ray.
 
procedure TSymCommsDlg.VaComm1RxChar(Sender: TObject; Count: Integer);
begin
   if Count >= 742 then begin
     GetData;
   end;
end;

You can also use vacomm.ReadBufUsed > 0 to check if data is present

I am trying to use the following code in C++ Builder. I get a program crash. The error I get is "Invalid Access to Memory Location"
The problem relates to  the buffer value in ReadBuf. The Delphi version of this code worked without problem.
 
Ray.
 
enum TCaptureState {csNone, csCaptureStart, csCaptureEnd};


void TForm1::GetRXData(void)
{
  TCaptureState cs;
  uint8_t sig_start, sig_end;
  uint8_t *b;
  uint16_t i;
   cs = csNone;
   sig_start = 0x24;
   sig_end = 0x7E;
   i = 1;
   while ( cs !=  csCaptureEnd)
   {
       if (VaComm1->ReadBufUsed() > 0 )
      {
           VaComm1->ReadBuf(b,1);
           switch (cs)
          {
                case csCaptureStart: if (b[1] == sig_end)
                                                       {
                                                           cs = csCaptureEnd;
                                                       }
                                                       else
                                                       {
                                                            RTdata[i++] = b[1];
                                                       }
                                                        break;
                            case csNone: if (b[1] == sig_start)
                                                       {      
                                                        cs  = csCaptureStart;
                                                        {
                                                        break;
            }
           Application->ProcessMessages();
        }
   }
  VaComm1->PurgeRead();
}


Where exactly is the error happening?
Where is RTData declared? Are you sure you do not cause an access out of the boundaries of RTData[]?

Bruno,

The problem is the VaComm1->ReadBuf(b,1);

There are no problems if I use VaComm1->ReadChar(b);  

How do I get ReadBuf to work.

Ray. 

I see that in your code you declare a pointer to b and nowhere you allocate memory for this pointer. That will of course cause that ReadBuf() fails writing to a memory address that is not allocated.

Bruno,

 
This........
 
uint8_t b;
VaComm1->ReadBuf(b,1);
 
gives this complile error.........

Cannot convert 'int' to 'void *'
Type mismatch in parameter 'Buf' (wanted 'void *', got 'unsigned char')
 
 
This......
 
uint8_t *b;
VaComm1->ReadBuf(b,1);
 
gives no complie errors, but when the program is run it crashes with the previously mentioned memory error.
 
I do not know how to allocate memory. How do I get ReadBuf to work.
 
Ray.