Very cool
I would like you to run a test program on your scanner trx-1-2 etc and see if it works.
I will complie a simple program and you can tell me if it grabs the info from the scanner.
I had AI read the reference PDF and build the code for me with prompting.
program WhistlerRemoteControl;
uses
SysUtils, Math, synaser;
const
STX = #2;
ETX = #3;
SERIAL_PORT_NAME = 'COM1'; // Replace with your serial port name
TIMEOUT_MS = 1000; // Timeout in milliseconds
type
TRecordingType = (rtConventional, rtTalkgroup, rtSearch);
TStm = packed record
tm_sec: SmallInt;
tm_min: SmallInt;
tm_hour: SmallInt;
tm_mday: SmallInt;
tm_mon: SmallInt;
tm_year: SmallInt;
tm_wday: SmallInt;
tm_yday: SmallInt;
tm_isdst: SmallInt;
end;
TAudioFileHeader = packed record
MagicNumber: Cardinal;
AudioDataOffset: Cardinal;
AudioDataSize: Cardinal;
EncodingFormat: Cardinal;
SampleRate: Cardinal;
ChannelCount: Cardinal;
RecordingType: Byte;
StartTime: TStm;
ObjectAlphaTag: array[0..16] of Char;
TrunkedSystemAlphaTag: array[0..16] of Char;
InfoAlphaTag: array[0..16] of Char;
ObjectID: Cardinal;
TalkgroupID1: Cardinal;
TalkgroupID2: Cardinal;
RadioID1: Cardinal;
RadioID2: Cardinal;
SiteName: array[0..16] of Char;
TSYSFileIndex: Cardinal;
MiscInfo: array[0..16] of Char;
VoiceFrequency: Cardinal;
ControlChannelFrequency: Cardinal;
SquelchMode: Word;
SquelchValue: Word;
TSYSType: Byte;
Reserved: array[0..154] of Byte;
end;
var
SerialPort: TBlockSerial;
ModelNumber: string;
ChannelInfo: string;
AudioHeader: TAudioFileHeader;
function CalculateChecksum(const Data: string): Byte;
var
i: Integer;
Sum: Byte;
begin
Sum := 0;
for i := 1 to Length(Data) do
Sum := Sum + Ord(Data);
Result := Sum and $FF;
end;
function CreateCommand(const MsgCode: Char; const MsgData: string): string;
var
Command: string;
begin
Command := STX + MsgCode + MsgData + ETX;
Command := Command + Chr(CalculateChecksum(Command));
Result := Command;
end;
function SendCommand(const Command: string): Boolean;
begin
Result := False;
try
SerialPort.SendString(Command);
SerialPort.WaitForTx(TIMEOUT_MS);
Result := True;
except
on E: Exception do
begin
WriteLn('Error sending command: ' + E.Message);
end;
end;
end;
function ReceiveResponse: string;
var
Response: string;
Data: Char;
begin
Response := '';
try
repeat
SerialPort.RecvString(Data, 1);
Response := Response + Data;
until (Data = ETX) or (SerialPort.LastError <> 0);
if CalculateChecksum(Response) = Ord(Response[Length(Response)]) then
Result := Response
else
Result := '';
except
on E: Exception do
begin
WriteLn('Error receiving response: ' + E.Message);
Result := '';
end;
end;
end;
procedure CloseSerialPort;
begin
SerialPort.CloseSocket;
SerialPort.Free;
end;
procedure GetModelNumber;
var
Command, Response: string;
begin
Command := CreateCommand('V', #0);
if SendCommand(Command) then
begin
Response := ReceiveResponse;
if (Length(Response) >= 14) and (Response[2] = 'V') then
begin
ModelNumber := Copy(Response, 4, 8);
WriteLn('Model Number: ', ModelNumber);
end
else
WriteLn('Invalid response for model number');
end
else
WriteLn('Failed to send command for model number');
end;
procedure GetChannelInfo;
var
Command, Response: string;
i, Len: Integer;
begin
Command := CreateCommand('a', '');
if SendCommand(Command) then
begin
Response := ReceiveResponse;
if (Length(Response) >= 8) and (Response[2] = 'a') then
begin
Len := Ord(Response[4]) * 256 + Ord(Response[5]);
if Len > 0 then
begin
ChannelInfo := Copy(Response, 6, Len);
WriteLn('Channel Info: ', ChannelInfo);
// Extract audio file header information
Move(ChannelInfo[1], AudioHeader, SizeOf(AudioHeader));
// Extract individual fields from the audio file header
WriteLn('Magic Number: ', AudioHeader.MagicNumber);
WriteLn('Audio Data Offset: ', AudioHeader.AudioDataOffset);
WriteLn('Audio Data Size: ', AudioHeader.AudioDataSize);
WriteLn('Encoding Format: ', AudioHeader.EncodingFormat);
WriteLn('Sample Rate: ', AudioHeader.SampleRate);
WriteLn('Channel Count: ', AudioHeader.ChannelCount);
WriteLn('Recording Type: ', Ord(AudioHeader.RecordingType));
WriteLn('Start Time:');
WriteLn(' Year: ', AudioHeader.StartTime.tm_year + 1900);
WriteLn(' Month: ', AudioHeader.StartTime.tm_mon + 1);
WriteLn(' Day: ', AudioHeader.StartTime.tm_mday);
WriteLn(' Hour: ', AudioHeader.StartTime.tm_hour);
WriteLn(' Minute: ', AudioHeader.StartTime.tm_min);
WriteLn(' Second: ', AudioHeader.StartTime.tm_sec);
WriteLn('Object Alpha Tag: ', AudioHeader.ObjectAlphaTag);
WriteLn('Trunked System Alpha Tag: ', AudioHeader.TrunkedSystemAlphaTag);
WriteLn('Info Alpha Tag: ', AudioHeader.InfoAlphaTag);
WriteLn('Object ID: ', AudioHeader.ObjectID);
WriteLn('Talkgroup ID 1: ', AudioHeader.TalkgroupID1);
WriteLn('Talkgroup ID 2: ', AudioHeader.TalkgroupID2);
WriteLn('Radio ID 1: ', AudioHeader.RadioID1);
WriteLn('Radio ID 2: ', AudioHeader.RadioID2);
WriteLn('Site Name: ', AudioHeader.SiteName);
WriteLn('TSYS File Index: ', AudioHeader.TSYSFileIndex);
WriteLn('Misc Info: ', AudioHeader.MiscInfo);
WriteLn('Voice Frequency: ', AudioHeader.VoiceFrequency);
WriteLn('Control Channel Frequency: ', AudioHeader.ControlChannelFrequency);
WriteLn('Squelch Mode: ', AudioHeader.SquelchMode);
WriteLn('Squelch Value: ', AudioHeader.SquelchValue);
WriteLn('TSYS Type: ', AudioHeader.TSYSType);
end
else
WriteLn('No active channel');
end
else
WriteLn('Invalid response for channel info');
end
else
WriteLn('Failed to send command for channel info');
end;
begin
SerialPort := TBlockSerial.Create;
try
// Open the serial port
SerialPort.Connect(SERIAL_PORT_NAME);
SerialPort.Config(115200, 8, 'N', 1, False, False);
// Get model number
GetModelNumber;
// Get channel info
GetChannelInfo;
// Add more commands and processing as needed
except
on E: Exception do
begin
WriteLn('Error: ' + E.Message);
end;
end;
// Close the serial port when the program is complete
CloseSerialPort;
end.