Witam. Mam problem tego typu, że w projekcie C++ muszę wykorzystać kod z delphi, ale potrafię w całości tego przetłumaczyć :-( Czy ktoś by mógł podjąć wyzwanie i przetłumaczyć na C++??
Załączam kod
unit sbus;
interface
//{$DEFINE DUMP_DATA}
uses cport,sysutils
{$IFDEF DUMP_DATA}
,tapp1
{$ENDIF}
;
const
{########################## PCD CONSTANTS ####################################}
PCD_HISTORY_TIME_SHIFT = $3f000000; // time field of history record from PCD has this shift
{###### PCD COMMANDS CODES #####}
PCD_CMD_SET_TIME = 1; //unconditional set time
PCD_CMD_GET_ERRORS = 3;
PCD_CMD_DELETE_ERRORS = 4;
PCD_CMD_SYNC_TIME = 5;
PCD_CMD_SET_SYNC_TIME_MODE = 6;
PCD_CMD_SET_SYNC_TIME_MODE_0 = 0; //time sync disabled
PCD_CMD_SET_SYNC_TIME_MODE_1 = 1; //pulse on PCD input
PCD_CMD_SET_SYNC_TIME_MODE_2 = 2; //SBUS command
PCD_CMD_GET_HDATA = 9;
PCD_CMD_DELETE_HDATA = 10;
PCD_CMD_ERASE_ALL_DATA = 11;
PCD_CMD_GET_ACTDIGDATA = 12;
PCD_CMD_GET_ACTANADATA = 13;
PCD_CMD_GET_ACTANADATA2 = 14;
PCD_CMD_GET_ACTANADATA3 = 15;
//PCD configuration constants
PCD_CONF_INT = 5; //small data scan interval value in [s]
//addresses of registers in PCD
PCD_CMD_REG = 3325;
PCD_CMD_ACK_REG = 3324;
PCD_CMD_DATA_BASE = 3326;
PCD_TIME_REG = 1;
PCD_CONF_BASE = 100; //base address of configuration data
PCD_CONF_DIGCNTRS_BASE = PCD_CONF_BASE;
PCD_CONF_ANAL_BASE = PCD_CONF_DIGCNTRS_BASE + 1025;
PCD_CONF_DIGINPUTS_BASE = PCD_CONF_ANAL_BASE +1025;
PCD_DATA_OFFSET = 3;
//offsets from base PCD_CONF_BASE
PCD_CONF_ADDR = 0;
PCD_CONF_INTS = 2;
PCD_CONF_INTB = 1;
PCD_CONF_DESC1= 12;
PCD_CONF_DESC2= 13;
PCD_CONF_DESC3= 14;
PCD_CONF_DESC4= 15;
PCD_CONF_MASK = 1; //mask for digital inputs
//base PCD_CONF_BASE + PCD_DATA_OFFSET
//for digital counters
PCD_DATA_PULSES_S = 1;
PCD_DATA_PULSES_B = 0;
//for analog inputs
PCD_DATA_A_VAL = 1;
PCD_DATA_A_AVG = 0;
PCD_DATA_A_MIN_A = 2;
PCD_DATA_A_MAX_A = 3;
PCD_DATA_A_MIN_P = 4;
PCD_DATA_A_MAX_P = 5;
{########################## SBUS CONSTANTS ####################################}
SBUS_RETRY_CNT = 3; //number of retransmission retries
SBUS_MAX_INTRAFRAME_BREAK = 5; //maximum break length in the middle of the frame
//SBUS functions CODES
SBUS_READ_DATA_BLOCK = $96;
SBUS_READ_REGISTER = $06;
SBUS_WRITE_REGISTER = $0E;
//getFrame results
GFR_TIMEOUT = $8000; //transmission timeout
GFR_CRC_ERR = $8001;
GFR_RETRY = $8002;
GFR_COM_PORT_CLOSED = $8003;
GFR_COM_WRITE_ERROR = $8004;
GFR_COM_CLEAR_ERROR = $8005;
GFR_COM_ERROR = $8006;
GFR_COM_READ_ERROR = $8004;
GFR_OK = $0001; //command executed OK
GFR_COMMAND_REJECTED = $0002; //transmission OK, command rejected by PCD
GFR_WAIT = $0003;
//DUMP_DATA params
DD_WR = 1; //dump WRITE-to-COM data
DD_RD = 2;
DD_ERROR = 3;
DD_DEBUG = 4; //dump data readen from COM
DD_RETRY = 5;
DD_TOUT = 6;
//single gate structure
type
stGate = record
Station:BYTE; // station number
Func:BYTE; // READ_REGISTER etc.
Address:WORD; // of register/data block
DBNumber:WORD; // DATABLOCK commands
DBElement:WORD;
Count:WORD; // no of elements (base 1)
RXTimeout:integer; // timeout for first rx char in 20 ms units
value:array [0..31] of integer; //output data
//internal data
wait_for: BYTE ;
ReplySize:WORD; // expected reply size
end;
{**************************************************************************
* PUT SBUS COMMAND
* ========================
* INPUT -> comPort - properly opened serial port
* G - properly filled command structure
* respBuff - buffer for incoming reply
* OUTPUT -> result code one of:
* GFR_TIMEOUT , GFR_OK , GFR_COMMAND_REJECTED
* GFR_COM_WRITE_ERROR , GFR_COM_CLEAR_ERROR , GFR_COM_READ_ERROR
***************************************************************************}
function SBUSPut(comPort:TcomPort;var G:stGate;RespBuff:PByteArray):WORD;
{**************************************************************************
* CONVERT INTEL TO MOTOROLA ENDIAN (AND VICE VERSA)
***************************************************************************}
function intI2intM(intel:integer):longword;
//###############################################################################
implementation
const
SBUS_RX_Sync =0;
SBUS_RX_Attrib =1;
SBUS_RX_Data =2;
function intI2intM(intel:integer):longword;
var
x:longword;
begin
x:=intel;
intel:= (x shr 24) or (x shl 24) or ((x and $00FF0000) shr 8) or ((x and $0000FF00) shl 8);
result:=intel;
end;
//calculate CRC en-block
function SBUS_CountCRC16(Buff: PByteArray ;DataLen: BYTE) : WORD ;
var
CRC: WORD;
i,j: BYTE;
begin
CRC:=0;
j:=0;
while j<DataLen do begin
CRC := CRC xor WORD(Buff[j] shl 8);
inc(j);
for i:=0 to 7 do begin
if (CRC and $8000) = $8000 then CRC:= (CRC shl 1) xor $1021
else CRC:= (CRC shl 1);
end;
end;
//swap bytes to motorola
result:= ((CRC shl 8)and $ffff) or (CRC shr 8);
end;
//crc calculation byte by byte
function addCRC(b:BYTE;CRC:WORD):WORD;
var
i:integer;
begin
CRC := CRC xor WORD(b shl 8);
for i:=0 to 7 do begin
if (CRC and $8000) = $8000 then CRC:= (CRC shl 1) xor $1021
else CRC:= (CRC shl 1);
end;
result:=CRC;
end;
function SBUSSendFrame(comPort:TcomPort; buffer:PByteArray; message_length:BYTE):boolean;
var
i:BYTE ;
Buff:array [0..255] of BYTE;
pBuff,pCRC:^BYTE;
buff_len:BYTE;
CRC:WORD;
begin
result:=true;
buff_len:=2; //for $B5 $00
pBuff:=@Buff;
pBuff^:=$b5; inc(pBuff);
pBuff^:=$00; inc(pBuff); //telegram
buff_len:=buff_len + message_length;
for i:=0 to message_length-1 do
begin
case buffer[i] of
$b5: begin
pBuff^:=$c5; inc(pBuff);
pBuff^:=$00; inc(pBuff);
inc(buff_len);
end;
$c5: begin
pBuff^:=$c5; inc(pBuff);
pBuff^:=$01; inc(pBuff);
inc(buff_len);
end;
else begin
pBuff^:=buffer[i]; inc(pBuff);
end;
end;
end;
CRC:=SBUS_CountCRC16(@Buff,buff_len); //calculate CRC from encoded message
pCRC:=@CRC;
for i:=0 to 1 do begin//encode CRC itself too
case pCRC^ of
$b5: begin
pBuff^:=$c5; inc(pBuff);
pBuff^:=$00; inc(pBuff);
buff_len:=buff_len+2;
end;
$c5: begin
pBuff^:=$c5; inc(pBuff);
pBuff^:=$01; inc(pBuff);
buff_len:=buff_len+2;
end;
else begin
pBuff^:=pCRC^; inc(pBuff);
inc(buff_len);
end;
end; //case
inc(pCRC);
end;
try
comPort.Write(Buff,buff_len); // Send it out...
except
on EComPort do result:=false;
end;
{$ifdef DUMP_DATA}
dumpData(@Buff,buff_len,DD_WR);
{$endif}
end;
function ComMakeQuery(comPort:TcomPort;var G:stGate):boolean;
var
Frame:array [0..255] of BYTE;
toSend:integer;
begin
toSend:=0; //for unknown commands
Frame[0]:=G.Station;
Frame[1]:=G.Func; //Command
case G.Func of
SBUS_READ_DATA_BLOCK :
begin
toSend:=7;
Frame[2]:=G.count-1;
Frame[3]:=BYTE(G.DBNumber shr 8);
Frame[4]:=BYTE(G.DBNumber);
Frame[5]:=BYTE(G.DBElement shr 8);
Frame[6]:=BYTE(G.DBElement);
G.ReplySize:= (G.count)*4;
end;
SBUS_READ_REGISTER:
begin
toSend:=5;
Frame[2]:=G.count-1;
Frame[3]:=BYTE(G.Address shr 8);
Frame[4]:=BYTE(G.Address);
G.ReplySize:= (G.count)*4;
end;
SBUS_WRITE_REGISTER:
begin
Frame[2]:=G.count*4+1;
toSend:=5+(g.count*4);
Frame[3]:=BYTE(G.Address shr 8);
Frame[4]:=BYTE(G.Address);
move(G.value[0],Frame[5],g.count*4);
G.ReplySize:= 2;
end;
end; //case
result:=SBUSSendFrame(comPort, @Frame,toSend);
end;
//---------------------------------------------------------------------------
// expCnt - expected answer length
// nReceived - length of received chars buffer
function SBUSGetFrame(var expCnt:BYTE; BuffOut:PByteArray ;var FramePos: BYTE ;
BuffIn:PBYTEArray ;nReceived :BYTE; var CRC:WORD;
var huntMode:boolean;var wait_for:BYTE): integer ;
var
i,rx_char:BYTE;
inCRC:boolean;
begin
i:=0;
inCRC:=false;
result:=GFR_Wait;
while(i<nReceived) do begin
rx_char:=BuffIn[i];
case (wait_for) of
SBUS_RX_Sync: begin
if (rx_char=$b5) then begin
FramePos:=0; CRC:=0; huntMode:= FALSE;
CRC:=addCRC(rx_char,CRC);
BuffOut[FramePos]:=rx_char; inc(FramePos);
wait_for:=SBUS_RX_Attrib;
end;
end;
SBUS_RX_Attrib: begin
BuffOut[FramePos]:=rx_char; inc(FramePos);
CRC:=addCRC(rx_char,CRC);
case (rx_char) of
1: begin //response
wait_for:=SBUS_RX_Data;
end;
2: begin //ack
expCnt:=2+2;
wait_for:=SBUS_RX_Data;
end;
else wait_for:=SBUS_RX_Sync;
end;
end;
SBUS_RX_Data: begin
if (expCnt<=2) then inCRC:=TRUE;
if (rx_char<>$c5) then begin
if huntMode then begin
case rx_char of
$00: BuffOut[FramePos]:=$b5;
$01: BuffOut[FramePos]:=$c5;
else begin//error in data stream
result:=GFR_Crc_Err;
break;
end;
end; //case
dec(expCnt);
inc(FramePos); huntMode:=FALSE;
end else begin
dec(expCnt); //ESC char
BuffOut[FramePos]:=rx_char; inc(FramePos);
end
end else huntMode:=TRUE;
if inCRC then begin
if not huntMode then CRC:=addCRC(BuffOut[FramePos-1],CRC);
end else begin
CRC:=addCRC(rx_char,CRC);
end;
if (expCnt=0) then begin
if CRC <> $0000 then begin
result:=GFR_Crc_Err;
break;
end;
wait_for:=SBUS_RX_Sync;
result:=GFR_OK;
break;
end;
end;
end; //end switch
inc(i);
end; //while
end;
function ComGetResponse(comPort:TcomPort;G:stGate;RespBuff:PByteArray):integer;
var
len,lenx:integer;
Pos,RecCnt,no_rx,got:BYTE;
BuffIn: array [0..255] of BYTE;
stat,CRC:WORD;
Events:TComEvents;
huntMode:boolean;
begin
try
Pos:=0;
no_rx:=g.RXTimeout; //in 20ms increments, wait for first rx char
stat:= GFR_Wait;
RecCnt:=G.ReplySize+2;//include CRC
G.wait_for:=SBUS_RX_Sync;
repeat
Events:=[evRxChar];
comPort.WaitForEvent(Events,20);
if (Events=[evRxChar]) then begin
len:=comPort.InputCount();
no_rx:=SBUS_MAX_INTRAFRAME_BREAK; //reload timer, allow short break in transmission
while (len>0) do begin
if len>255 then lenx:=255 else lenx:=len; // don't overflow
len:=len-lenx;
got:=comPort.Read(BuffIn,lenx);
{$ifdef DUMP_DATA}
dumpData(@BuffIn,got,DD_DEBUG);
{$endif}
stat:=SBUSGetFrame(RecCnt,RespBuff, Pos, @BuffIn, got,CRC,huntMode,G.wait_For);
end;
end else dec(no_rx);
until ((stat=GFR_OK) or (stat=GFR_Crc_Err) or (no_rx=0));
if (no_rx=0) then stat:=GFR_TimeOut;
{$ifdef DUMP_DATA}
if (stat=GFR_Crc_Err) then dumpData(RespBuff,Pos,DD_ERROR)
else if (stat=GFR_OK) then dumpData(RespBuff,Pos,DD_RD)
else if (stat=GFR_TimeOut) then dumpData(RespBuff,Pos,DD_TOUT);
{$endif}
if (RespBuff[1]=$02) and (RespBuff[3]=$01) then stat:= GFR_COMMAND_REJECTED;
result:= stat;
except
on EComPort do result:= GFR_COM_READ_ERROR;
end;
end;
function SBUSPut(comPort:TcomPort;var G:stGate;RespBuff:PByteArray):WORD;
var
RetryCnt:integer;
stat:WORD;
begin
if comPort.Connected then begin
RetryCnt:=SBUS_RETRY_CNT;
stat:=GFR_COM_ERROR;
repeat
dec(RetryCnt);
try
comPort.clearbuffer(TRUE,TRUE);
except
on EComPort do begin
stat:= GFR_COM_CLEAR_ERROR;
break;
end;
end;
if not ComMakeQuery(comPort,G) then begin
stat:= GFR_COM_WRITE_ERROR;
break;
end;
stat:=ComGetResponse(comPort,G,RespBuff);
{$ifdef DUMP_DATA}
if (stat<>GFR_OK) then dumpData(nil,1,DD_RETRY);
{$endif}
until ((stat=GFR_OK) or (stat=GFR_COMMAND_REJECTED) or (RetryCnt=0));
if ((RetryCnt=0) and (stat<>GFR_OK) and (stat<>GFR_COMMAND_REJECTED)) then stat:=GFR_TimeOut;
end else stat:= GFR_COM_PORT_CLOSED;
result:=stat;
end;
end.
Bardzo proszę o pomoc, ale znając życie to pewnie nikt nie zrobi tego, bo troszke tego jest :(