diff --git a/Host/MicroBoot.exe b/Host/MicroBoot.exe index 1a221632..a59e991d 100644 Binary files a/Host/MicroBoot.exe and b/Host/MicroBoot.exe differ diff --git a/Host/PCANBasic.dll b/Host/PCANBasic.dll new file mode 100644 index 00000000..4836d8a8 Binary files /dev/null and b/Host/PCANBasic.dll differ diff --git a/Host/Pcan_usb.dll b/Host/Pcan_usb.dll deleted file mode 100644 index cfd024d5..00000000 Binary files a/Host/Pcan_usb.dll and /dev/null differ diff --git a/Host/Source/MicroBoot/MainUnit.dfm b/Host/Source/MicroBoot/MainUnit.dfm index 488be260..3534005d 100644 Binary files a/Host/Source/MicroBoot/MainUnit.dfm and b/Host/Source/MicroBoot/MainUnit.dfm differ diff --git a/Host/Source/MicroBoot/MainUnit.pas b/Host/Source/MicroBoot/MainUnit.pas index 23447f4c..24f49976 100644 --- a/Host/Source/MicroBoot/MainUnit.pas +++ b/Host/Source/MicroBoot/MainUnit.pas @@ -141,6 +141,8 @@ end; //*** end of OnMbiStarted *** procedure TmainForm.OnMbiProgress(progress: Longword); begin prgDownload.Position := progress; // update the progress bar + prgDownload.Position := progress-1; // fix for progress bar not going to 100% + prgDownload.Position := progress; // update the progress bar end; //*** end of OnMbiProgress *** @@ -178,7 +180,7 @@ end; //*** end of OnMbiDone *** //*************************************************************************************** procedure TmainForm.OnMbiError(error: ShortString); begin - ShowMessage(error); // display error + ShowMessage(String(error)); // display error Timer.Enabled := false; // stop the timer StopWatch.Stop; // stop the stopwatch mainForm.Caption := FormCaption; // restore caption @@ -205,7 +207,7 @@ procedure TmainForm.OnMbiLog(info: ShortString); begin if MbiLogging = True then begin - LogLines.Add(info); // add to log + LogLines.Add(String(info)); // add to log end; end; //*** end of OnMbiLog *** @@ -221,7 +223,7 @@ end; //*** end of OnMbiLog *** procedure TmainForm.OnMbiInfo(info: ShortString); begin if NtbPages.PageIndex = 1 then - lblDownloadProgress.Caption := info; + lblDownloadProgress.Caption := String(info); end; //*** end of OnMbiLog *** @@ -235,8 +237,8 @@ end; //*** end of OnMbiLog *** //*************************************************************************************** function TmainForm.GetActiveMbi : string; begin - if IsMbiInterface(MbiLibFile) then - Result := MbiLibFile + if IsMbiInterface(String(MbiLibFile)) then + Result := String(MbiLibFile) else Result := ''; end; //*** end of GetActiveMbi *** @@ -255,7 +257,7 @@ begin if IsMbiInterface(libFile) then begin - MbiLibFile := libFile; + MbiLibFile := ShortString(libFile); MbiInterfaced := MbiInterface.Enable(libFile, OnMbiStarted, OnMbiProgress, OnMbiDone, OnMbiError, OnMbiLog, OnMbiInfo); end; @@ -315,7 +317,8 @@ begin end; end; Result := LibValid; -end; //*** end of IsMbiInterface *** +end; +//*** end of IsMbiInterface *** //*************************************************************************************** @@ -348,7 +351,7 @@ begin if Assigned(DescriptionFnc) then begin - Result := Result + DescriptionFnc; + Result := Result + String(DescriptionFnc); end; if Assigned(VersionFnc) then @@ -406,11 +409,11 @@ end; //*** end of GetInterfaceFileList *** //*************************************************************************************** procedure TmainForm.StartFileDownload(fileName : ShortString); begin - if FileExists(fileName) and (MbiInterfaced = True) then + if FileExists(String(fileName)) and (MbiInterfaced = True) then begin FormCaption := mainForm.Caption; // backup original caption mainForm.Caption := FormCaption + ' - Downloading ' + - ExtractFileName(fileName) + '...'; + ExtractFileName(String(fileName)) + '...'; prgDownload.Position := 0; // reset the progress bar NtbPages.PageIndex := 1; // go to the next page btnSettings.Enabled := false; // settings can't be changed anymore @@ -432,7 +435,7 @@ begin // display interface library description if MbiInterfaced = True then begin - lblInterfaceName.Caption := 'for ' + MbiInterface.Description; + lblInterfaceName.Caption := 'for ' + String(MbiInterface.Description); end else begin @@ -538,7 +541,7 @@ begin // is it a valid Mbi interface library? if IsMbiInterface(foundLibrary) = True then begin - MbiLibFile := foundLibrary; + MbiLibFile := ShortString(foundLibrary); foundInterface := True; end; end; @@ -560,7 +563,7 @@ begin // is it a valid Mbi interface library? if IsMbiInterface(foundLibrary) = True then begin - MbiLibFile := foundLibrary; + MbiLibFile := ShortString(foundLibrary); foundInterface := True; end; end; @@ -579,7 +582,7 @@ begin // is it a valid Mbi interface library? if IsMbiInterface(foundLibrary) = True then begin - MbiLibFile := foundLibrary; + MbiLibFile := ShortString(foundLibrary); foundInterface := True; end; end; @@ -589,7 +592,7 @@ begin // did we find a Mbi interface library? if foundInterface = True then begin - SetActiveMbi(MbiLibFile); + SetActiveMbi(String(MbiLibFile)); end; // create the stopwatch timer @@ -634,7 +637,7 @@ begin if (ParamCount > 0) and (FileExists(ParamStr(ParamCount))) then begin edtDownloadFile.Text := ParamStr(ParamCount); - StartFileDownload(ParamStr(ParamCount)); + StartFileDownload(ShortString(ParamStr(ParamCount))); Exit; // nothing more todo end; @@ -653,7 +656,7 @@ begin if FileExists(OpenDialog.FileName) then begin edtDownloadFile.Text := OpenDialog.FileName; - StartFileDownload(OpenDialog.FileName); + StartFileDownload(ShortString(OpenDialog.FileName)); end; end; end; @@ -676,7 +679,7 @@ begin if FileExists(OpenDialog.FileName) then begin edtDownloadFile.Text := OpenDialog.FileName; - StartFileDownload(OpenDialog.FileName); + StartFileDownload(ShortString(OpenDialog.FileName)); end; end; end; //*** end of btnBrowseClick *** @@ -702,7 +705,7 @@ begin winRegistry := TRegistry.Create; winRegistry.RootKey := HKEY_CURRENT_USER; winRegistry.OpenKey('Software\Feaser\MicroBoot', true); - winRegistry.WriteString('Interface', ExtractFileName(MbiLibFile)); + winRegistry.WriteString('Interface', ExtractFileName(String(MbiLibFile))); winRegistry.Free; end; UpdateInterfaceLabel; @@ -751,7 +754,7 @@ begin // start the download if FileExists(edtDownloadFile.Text) then begin - StartFileDownload(edtDownloadFile.Text); + StartFileDownload(ShortString(edtDownloadFile.Text)); end; end; diff --git a/Host/Source/MicroBoot/MicroBoot.cfg b/Host/Source/MicroBoot/MicroBoot.cfg deleted file mode 100644 index d9e521de..00000000 --- a/Host/Source/MicroBoot/MicroBoot.cfg +++ /dev/null @@ -1,35 +0,0 @@ --$A+ --$B- --$C+ --$D+ --$E- --$F- --$G+ --$H+ --$I+ --$J+ --$K- --$L+ --$M- --$N+ --$O+ --$P+ --$Q- --$R- --$S- --$T- --$U- --$V+ --$W- --$X+ --$YD --$Z1 --cg --AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; --H+ --W+ --M --$M16384,1048576 --K$00400000 --E../../ --LNc:\borland\delphi4\Lib diff --git a/Host/Source/MicroBoot/MicroBoot.dof b/Host/Source/MicroBoot/MicroBoot.dof deleted file mode 100644 index ff39552a..00000000 --- a/Host/Source/MicroBoot/MicroBoot.dof +++ /dev/null @@ -1,89 +0,0 @@ -[Compiler] -A=1 -B=0 -C=1 -D=1 -E=0 -F=0 -G=1 -H=1 -I=1 -J=1 -K=0 -L=1 -M=0 -N=1 -O=1 -P=1 -Q=0 -R=0 -S=0 -T=0 -U=0 -V=1 -W=0 -X=1 -Y=1 -Z=1 -ShowHints=1 -ShowWarnings=1 -UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -[Linker] -MapFile=0 -OutputObjs=0 -ConsoleApp=1 -DebugInfo=0 -RemoteSymbols=0 -MinStackSize=16384 -MaxStackSize=1048576 -ImageBase=4194304 -ExeDescription= -[Directories] -OutputDir=../../ -UnitOutputDir= -PackageDLLOutputDir= -PackageDCPOutputDir= -SearchPath= -Packages=Vcl40;Vclx40;Vcldb40;vcldbx40;VclSmp40;Qrpt40 -Conditionals= -DebugSourceDirs= -UsePackages=0 -[Parameters] -RunParams= -HostApplication= -[Version Info] -IncludeVerInfo=0 -AutoIncBuild=0 -MajorVer=1 -MinorVer=0 -Release=0 -Build=0 -Debug=0 -PreRelease=0 -Special=0 -Private=0 -DLL=0 -Locale=1031 -CodePage=1252 -[Version Info Keys] -CompanyName= -FileDescription= -FileVersion=1.0.0.0 -InternalName= -LegalCopyright= -LegalTrademarks= -OriginalFilename= -ProductName= -ProductVersion=1.0.0.0 -Comments= -[Excluded Packages] -$(DELPHI)\Lib\dclusr40.bpl=Borland User -$(DELPHI)\Components\tsock\tsock.bpl=(untitled) -[HistoryLists\hlUnitAliases] -Count=1 -Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -[HistoryLists\hlOutputDirectorry] -Count=3 -Item0=../../ -Item1=../.. -Item2=../ diff --git a/Host/Source/MicroBoot/MicroBoot.dpr b/Host/Source/MicroBoot/MicroBoot.dpr index 3245830b..e5242bf6 100644 --- a/Host/Source/MicroBoot/MicroBoot.dpr +++ b/Host/Source/MicroBoot/MicroBoot.dpr @@ -35,7 +35,8 @@ uses Forms, MainUnit in 'MainUnit.pas' {mainForm}, SettingsUnit in 'SettingsUnit.pas' {settingsForm}, - StopWatch in 'StopWatch.pas'; + StopWatch in 'StopWatch.pas', + uBootInterface in 'uBootInterface.pas'; {$R *.RES} diff --git a/Host/Source/MicroBoot/MicroBoot.dproj b/Host/Source/MicroBoot/MicroBoot.dproj new file mode 100644 index 00000000..50f8e317 --- /dev/null +++ b/Host/Source/MicroBoot/MicroBoot.dproj @@ -0,0 +1,136 @@ + + + {DF84500F-F9C3-464D-AB96-10E57464FFB5} + MicroBoot.dpr + True + Debug + 1 + Application + VCL + 18.1 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + 1 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;System.Win;$(DCC_Namespace) + 00400000 + MicroBoot + 1 + true + false + ../../ + 1 + true + 1031 + Vcl40;Vclx40;Vcldb40;vcldbx40;VclSmp40;Qrpt40;$(DCC_UsePackage) + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= + + + $(BDS)\bin\default_app.manifest + Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + true + true + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + 1033 + MicroBoot.ico + true + true + true + + + DEBUG;$(DCC_Define) + false + true + + + 2 + CompanyName=Feaser;FileDescription=PC download tool for the OpenBLT bootloader;FileVersion=1.2.0.0;InternalName=;LegalCopyright=Feaser;LegalTrademarks=;OriginalFilename=;ProductName=MicroBoot;ProductVersion=1.2.0.0;Comments= + true + true + 1033 + true + MicroBoot.ico + + + + MainSource + + +
mainForm
+
+ +
settingsForm
+
+ + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + +
+ + Delphi.Personality.12 + + + + + MicroBoot.dpr + + + + True + + + 12 + + + +
diff --git a/Host/Source/MicroBoot/interfaces/XcpIcon.bmp b/Host/Source/MicroBoot/interfaces/XcpIcon.bmp deleted file mode 100644 index c7923878..00000000 Binary files a/Host/Source/MicroBoot/interfaces/XcpIcon.bmp and /dev/null differ diff --git a/Host/Source/MicroBoot/interfaces/XcpIcon.png b/Host/Source/MicroBoot/interfaces/XcpIcon.png new file mode 100644 index 00000000..6c0e1944 Binary files /dev/null and b/Host/Source/MicroBoot/interfaces/XcpIcon.png differ diff --git a/Host/Source/MicroBoot/interfaces/XcpLoader.pas b/Host/Source/MicroBoot/interfaces/XcpLoader.pas index 7a89ae2b..c250f3f8 100644 --- a/Host/Source/MicroBoot/interfaces/XcpLoader.pas +++ b/Host/Source/MicroBoot/interfaces/XcpLoader.pas @@ -453,6 +453,10 @@ begin // init return value Result := false; + // validate packet length. it must always be > 0 + if comDriver.packetLen = 0 then + Exit; + // make a copy of the packet data because the synch command could overwrite it SetLength(dataCpy, comDriver.packetLen); for cnt := 0 to comDriver.packetLen-1 do @@ -1256,6 +1260,10 @@ begin // init return value result := false; + // validate FCtoPGMPacketLen because using it to prevent possible divide by 0 + if FCtoPGMPacketLen = 0 then + exit; + // set the start address for the program operation if not CmdSetMta(addr) then Exit; diff --git a/Host/Source/MicroBoot/interfaces/can/peak/CANIcon.bmp b/Host/Source/MicroBoot/interfaces/can/peak/CANIcon.bmp deleted file mode 100644 index 6ca58cdf..00000000 Binary files a/Host/Source/MicroBoot/interfaces/can/peak/CANIcon.bmp and /dev/null differ diff --git a/Host/Source/MicroBoot/interfaces/can/peak/CANIcon.png b/Host/Source/MicroBoot/interfaces/can/peak/CANIcon.png new file mode 100644 index 00000000..ed2db00d Binary files /dev/null and b/Host/Source/MicroBoot/interfaces/can/peak/CANIcon.png differ diff --git a/Host/Source/MicroBoot/interfaces/can/peak/PCANBasic.pas b/Host/Source/MicroBoot/interfaces/can/peak/PCANBasic.pas new file mode 100644 index 00000000..c0257a96 --- /dev/null +++ b/Host/Source/MicroBoot/interfaces/can/peak/PCANBasic.pas @@ -0,0 +1,557 @@ +// PCANBasic.pas +// +// ~~~~~~~~~~~~ +// +// PCAN-Basic API +// +// ~~~~~~~~~~~~ +// +// ------------------------------------------------------------------ +// Author : Keneth Wagner +// Last change: 18.05.2016 Wagner +// +// Language: Pascal +// ------------------------------------------------------------------ +// +// Copyright (C) 1999-2016 PEAK-System Technik GmbH, Darmstadt +// more Info at http://www.peak-system.com +// +unit PCANBasic; + +interface + +const + //////////////////////////////////////////////////////////// + // Value definitions + //////////////////////////////////////////////////////////// + + // Currently defined and supported PCAN channels + // + PCAN_NONEBUS = $00; // Undefined/default value for a PCAN bus + + PCAN_ISABUS1 = $21; // PCAN-ISA interface, channel 1 + PCAN_ISABUS2 = $22; // PCAN-ISA interface, channel 2 + PCAN_ISABUS3 = $23; // PCAN-ISA interface, channel 3 + PCAN_ISABUS4 = $24; // PCAN-ISA interface, channel 4 + PCAN_ISABUS5 = $25; // PCAN-ISA interface, channel 5 + PCAN_ISABUS6 = $26; // PCAN-ISA interface, channel 6 + PCAN_ISABUS7 = $27; // PCAN-ISA interface, channel 7 + PCAN_ISABUS8 = $28; // PCAN-ISA interface, channel 8 + + PCAN_DNGBUS1 = $31; // PPCAN-Dongle/LPT interface, channel 1 + + PCAN_PCIBUS1 = $41; // PCAN-PCI interface, channel 1 + PCAN_PCIBUS2 = $42; // PCAN-PCI interface, channel 2 + PCAN_PCIBUS3 = $43; // PCAN-PCI interface, channel 3 + PCAN_PCIBUS4 = $44; // PCAN-PCI interface, channel 4 + PCAN_PCIBUS5 = $45; // PCAN-PCI interface, channel 5 + PCAN_PCIBUS6 = $46; // PCAN-PCI interface, channel 6 + PCAN_PCIBUS7 = $47; // PCAN-PCI interface, channel 7 + PCAN_PCIBUS8 = $48; // PCAN-PCI interface, channel 8 + PCAN_PCIBUS9 = $409; // PCAN-PCI interface, channel 9 + PCAN_PCIBUS10 = $40A; // PCAN-PCI interface, channel 10 + PCAN_PCIBUS11 = $40B; // PCAN-PCI interface, channel 11 + PCAN_PCIBUS12 = $40C; // PCAN-PCI interface, channel 12 + PCAN_PCIBUS13 = $40D; // PCAN-PCI interface, channel 13 + PCAN_PCIBUS14 = $40E; // PCAN-PCI interface, channel 14 + PCAN_PCIBUS15 = $40F; // PCAN-PCI interface, channel 15 + PCAN_PCIBUS16 = $410; // PCAN-PCI interface, channel 16 + + PCAN_USBBUS1 = $51; // PCAN-USB interface, channel 1 + PCAN_USBBUS2 = $52; // PCAN-USB interface, channel 2 + PCAN_USBBUS3 = $53; // PCAN-USB interface, channel 3 + PCAN_USBBUS4 = $54; // PCAN-USB interface, channel 4 + PCAN_USBBUS5 = $55; // PCAN-USB interface, channel 5 + PCAN_USBBUS6 = $56; // PCAN-USB interface, channel 6 + PCAN_USBBUS7 = $57; // PCAN-USB interface, channel 7 + PCAN_USBBUS8 = $58; // PCAN-USB interface, channel 8 + PCAN_USBBUS9 = $509; // PCAN-USB interface, channel 9 + PCAN_USBBUS10 = $50A; // PCAN-USB interface, channel 10 + PCAN_USBBUS11 = $50B; // PCAN-USB interface, channel 11 + PCAN_USBBUS12 = $50C; // PCAN-USB interface, channel 12 + PCAN_USBBUS13 = $50D; // PCAN-USB interface, channel 13 + PCAN_USBBUS14 = $50E; // PCAN-USB interface, channel 14 + PCAN_USBBUS15 = $50F; // PCAN-USB interface, channel 15 + PCAN_USBBUS16 = $510; // PCAN-USB interface, channel 16 + + PCAN_PCCBUS1 = $61; // PCAN-PC Card interface, channel 1 + PCAN_PCCBUS2 = $62; // PCAN-PC Card interface, channel 2 + + PCAN_LANBUS1 = $801; // PCAN-LAN interface, channel 1 + PCAN_LANBUS2 = $802; // PCAN-LAN interface, channel 2 + PCAN_LANBUS3 = $803; // PCAN-LAN interface, channel 3 + PCAN_LANBUS4 = $804; // PCAN-LAN interface, channel 4 + PCAN_LANBUS5 = $805; // PCAN-LAN interface, channel 5 + PCAN_LANBUS6 = $806; // PCAN-LAN interface, channel 6 + PCAN_LANBUS7 = $807; // PCAN-LAN interface, channel 7 + PCAN_LANBUS8 = $808; // PCAN-LAN interface, channel 8 + PCAN_LANBUS9 = $809; // PCAN-LAN interface, channel 9 + PCAN_LANBUS10 = $80A; // PCAN-LAN interface, channel 10 + PCAN_LANBUS11 = $80B; // PCAN-LAN interface, channel 11 + PCAN_LANBUS12 = $80C; // PCAN-LAN interface, channel 12 + PCAN_LANBUS13 = $80D; // PCAN-LAN interface, channel 13 + PCAN_LANBUS14 = $80E; // PCAN-LAN interface, channel 14 + PCAN_LANBUS15 = $80F; // PCAN-LAN interface, channel 15 + PCAN_LANBUS16 = $810; // PCAN-LAN interface, channel 16 + + // Represent the PCAN error and status codes + // + PCAN_ERROR_OK = $00000; // No error + PCAN_ERROR_XMTFULL = $00001; // Transmit buffer in CAN controller is full + PCAN_ERROR_OVERRUN = $00002; // CAN controller was read too late + PCAN_ERROR_BUSLIGHT = $00004; // Bus error: an error counter reached the 'light' limit [Not used with the *FD functions] + PCAN_ERROR_BUSHEAVY = $00008; // Bus error: an error counter reached the 'heavy' limit + PCAN_ERROR_BUSWARNING = PCAN_ERROR_BUSHEAVY; // An error counter reached the 'warning' limit [ONLY used with the *FD functions] + PCAN_ERROR_BUSPASSIVE = $40000; // Bus error: the CAN controller is in bus-off state + PCAN_ERROR_BUSOFF = $00010; // Bus error: the CAN controller is in bus-off state + PCAN_ERROR_ANYBUSERR = PCAN_ERROR_BUSWARNING Or PCAN_ERROR_BUSLIGHT Or PCAN_ERROR_BUSHEAVY Or PCAN_ERROR_BUSOFF Or PCAN_ERROR_BUSPASSIVE; // Mask for all bus errors + PCAN_ERROR_QRCVEMPTY = $00020; // Receive queue is empty + PCAN_ERROR_QOVERRUN = $00040; // Receive queue was read too late + PCAN_ERROR_QXMTFULL = $00080; // Transmit queue is full + PCAN_ERROR_REGTEST = $00100; // Test of the CAN controller hardware registers failed (no hardware found) + PCAN_ERROR_NODRIVER = $00200; // Driver not loaded + PCAN_ERROR_HWINUSE = $00400; // Hardware already in use by a Net + PCAN_ERROR_NETINUSE = $00800; // A Client is already connected to the Net + PCAN_ERROR_ILLHW = $01400; // Hardware handle is invalid + PCAN_ERROR_ILLNET = $01800; // Net handle is invalid + PCAN_ERROR_ILLCLIENT = $01C00; // Client handle is invalid + PCAN_ERROR_ILLHANDLE = PCAN_ERROR_ILLHW Or PCAN_ERROR_ILLNET Or PCAN_ERROR_ILLCLIENT; // Mask for all handle errors + PCAN_ERROR_RESOURCE = $02000; // Resource (FIFO, Client, timeout) cannot be created + PCAN_ERROR_ILLPARAMTYPE = $04000; // Invalid parameter + PCAN_ERROR_ILLPARAMVAL = $08000; // Invalid parameter value + PCAN_ERROR_UNKNOWN = $10000; // Unknown error + PCAN_ERROR_ILLDATA = $20000; // Invalid data, function, or action + PCAN_ERROR_CAUTION = $2000000; // An operation was successfully carried out, however, irregularities were registered + PCAN_ERROR_INITIALIZE = $4000000; // Channel is not initialized [Value was changed from 0x40000 to 0x4000000] + PCAN_ERROR_ILLOPERATION = $8000000; // Invalid operation [Value was changed from 0x80000 to 0x8000000] + + // PCAN devices + // + PCAN_NONE = $00; // Undefined, unknown or not selected PCAN device value + PCAN_PEAKCAN = $01; // PCAN Non-Plug&Play devices. NOT USED WITHIN PCAN-Basic API + PCAN_ISA = $02; // PCAN-ISA, PCAN-PC/104, and PCAN-PC/104-Plus + PCAN_DNG = $03; // PCAN-Dongle + PCAN_PCI = $04; // PCAN-PCI, PCAN-cPCI, PCAN-miniPCI, and PCAN-PCI Express + PCAN_USB = $05; // PCAN-USB and PCAN-USB Pro + PCAN_PCC = $06; // PCAN-PC Card + PCAN_VIRTUAL = $07; // PCAN Virtual hardware. NOT USED WITHIN PCAN-Basic API + PCAN_LAN = $08; // PCAN Gateway devices + + // PCAN parameters + // + PCAN_DEVICE_NUMBER = $01; // PCAN-USB device number parameter + PCAN_5VOLTS_POWER = $02; // PCAN-PC Card 5-Volt power parameter + PCAN_RECEIVE_EVENT = $03; // PCAN receive event handler parameter + PCAN_MESSAGE_FILTER = $04; // PCAN message filter parameter + PCAN_API_VERSION = $05; // PCAN-Basic API version parameter + PCAN_CHANNEL_VERSION = $06; // PCAN device channel version parameter + PCAN_BUSOFF_AUTORESET = $07; // PCAN Reset-On-Busoff parameter + PCAN_LISTEN_ONLY = $08; // PCAN Listen-Only parameter + PCAN_LOG_LOCATION = $09; // Directory path for log files + PCAN_LOG_STATUS = $0A; // Debug-Log activation status + PCAN_LOG_CONFIGURE = $0B; // Configuration of the debugged information (LOG_FUNCTION_***) + PCAN_LOG_TEXT = $0C; // Custom insertion of text into the log file + PCAN_CHANNEL_CONDITION = $0D; // Availability status of a PCAN-Channel + PCAN_HARDWARE_NAME = $0E; // PCAN hardware name parameter + PCAN_RECEIVE_STATUS = $0F; // Message reception status of a PCAN-Channel + PCAN_CONTROLLER_NUMBER = $10; // CAN-Controller number of a PCAN-Channel + PCAN_TRACE_LOCATION = $11; // Directory path for PCAN trace files + PCAN_TRACE_STATUS = $12; // CAN tracing activation status + PCAN_TRACE_SIZE = $13; // Configuration of the maximum file size of a CAN trace + PCAN_TRACE_CONFIGURE = $14; // Configuration of the trace file storing mode (TRACE_FILE_***) + PCAN_CHANNEL_IDENTIFYING = $15; // Physical identification of a USB based PCAN-Channel by blinking its associated LED + PCAN_CHANNEL_FEATURES = $16; // Capabilities of a PCAN device (FEATURE_***) + PCAN_BITRATE_ADAPTING = $17; // Using of an existing bit rate (PCAN-View connected to a channel) + PCAN_BITRATE_INFO = $18; // Configured bit rate as Btr0Btr1 value + PCAN_BITRATE_INFO_FD = $19; // Configured bit rate as TPCANBitrateFD string + PCAN_BUSSPEED_NOMINAL = $1A; // Configured nominal CAN Bus speed as Bits per seconds + PCAN_BUSSPEED_DATA = $1B; // Configured CAN data speed as Bits per seconds + PCAN_IP_ADDRESS = $1C; // Remote address of a LAN channel as string in IPv4 format + PCAN_LAN_SERVICE_STATUS = $1D; // Status of the Virtual PCAN-Gateway Service + + // PCAN parameter values + // + PCAN_PARAMETER_OFF = $00; // The PCAN parameter is not set (inactive) + PCAN_PARAMETER_ON = $01; // The PCAN parameter is set (active) + PCAN_FILTER_CLOSE = $00; // The PCAN filter is closed. No messages will be received + PCAN_FILTER_OPEN = $01; // The PCAN filter is fully opened. All messages will be received + PCAN_FILTER_CUSTOM = $02; // The PCAN filter is custom configured. Only registered + PCAN_CHANNEL_UNAVAILABLE = $00; // The PCAN-Channel handle is illegal, or its associated hardware is not available + PCAN_CHANNEL_AVAILABLE = $01; // The PCAN-Channel handle is available to be connected (Plug&Play Hardware: it means furthermore that the hardware is plugged-in) + PCAN_CHANNEL_OCCUPIED = $02; // The PCAN-Channel handle is valid, and is already being used + PCAN_CHANNEL_PCANVIEW = PCAN_CHANNEL_AVAILABLE Or PCAN_CHANNEL_OCCUPIED; // The PCAN-Channel handle is already being used by a PCAN-View application, but is available to connect + + LOG_FUNCTION_DEFAULT = $00; // Logs system exceptions / errors + LOG_FUNCTION_ENTRY = $01; // Logs the entries to the PCAN-Basic API functions + LOG_FUNCTION_PARAMETERS = $02; // Logs the parameters passed to the PCAN-Basic API functions + LOG_FUNCTION_LEAVE = $04; // Logs the exits from the PCAN-Basic API functions + LOG_FUNCTION_WRITE = $08; // Logs the CAN messages passed to the CAN_Write function + LOG_FUNCTION_READ = $10; // Logs the CAN messages received within the CAN_Read function + LOG_FUNCTION_ALL = $FFFF;// Logs all possible information within the PCAN-Basic API functions + + TRACE_FILE_SINGLE = $00; // A single file is written until it size reaches PAN_TRACE_SIZE + TRACE_FILE_SEGMENTED = $01; // Traced data is distributed in several files with size PAN_TRACE_SIZE + TRACE_FILE_DATE = $02; // Includes the date into the name of the trace file + TRACE_FILE_TIME = $04; // Includes the start time into the name of the trace file + TRACE_FILE_OVERWRITE = $80; // Causes the overwriting of available traces (same name) + + FEATURE_FD_CAPABLE = $01; // Device supports flexible data-rate (CAN-FD) + + SERVICE_STATUS_STOPPED = $01; // The service is not running + SERVICE_STATUS_RUNNING = $04; // The service is running + + // PCAN message types + // + PCAN_MESSAGE_STANDARD = $00; // The PCAN message is a CAN Standard Frame (11-bit identifier) + PCAN_MESSAGE_RTR = $01; // The PCAN message is a CAN Remote-Transfer-Request Frame + PCAN_MESSAGE_EXTENDED = $02; // The PCAN message is a CAN Extended Frame (29-bit identifier) + PCAN_MESSAGE_FD = $04; // The PCAN message represents a FD frame in terms of CiA Specs + PCAN_MESSAGE_BRS = $08; // The PCAN message represents a FD bit rate switch (CAN data at a higher bit rate) + PCAN_MESSAGE_ESI = $10; // The PCAN message represents a FD error state indicator(CAN FD transmitter was error active) + PCAN_MESSAGE_STATUS = $80; // The PCAN message represents a PCAN status message + + // Frame Type / Initialization Mode + // + PCAN_MODE_STANDARD = PCAN_MESSAGE_STANDARD; // Mode is Standard (11-bit identifier) + PCAN_MODE_EXTENDED = PCAN_MESSAGE_EXTENDED; // Mode is Extended (29-bit identifier) + + + // Baud rate codes = BTR0/BTR1 register values for the CAN controller. + // You can define your own Baud rate with the BTROBTR1 register. + // Take a look at www.peak-system.com for our free software "BAUDTOOL" + // to calculate the BTROBTR1 register for every bit rate and sample point. + // + PCAN_BAUD_1M = $0014; // 1 MBit/s + PCAN_BAUD_800K = $0016; // 800 kBit/s + PCAN_BAUD_500K = $001C; // 500 kBit/s + PCAN_BAUD_250K = $011C; // 250 kBit/s + PCAN_BAUD_125K = $031C; // 125 kBit/s + PCAN_BAUD_100K = $432F; // 100 kBit/s + PCAN_BAUD_95K = $C34E; // 95,238 kBit/s + PCAN_BAUD_83K = $852B; // 83,333 kBit/s + PCAN_BAUD_50K = $472F; // 50 kBit/s + PCAN_BAUD_47K = $1414; // 47,619 kBit/s + PCAN_BAUD_33K = $8B2F; // 33,333 kBit/s + PCAN_BAUD_20K = $532F; // 20 kBit/s + PCAN_BAUD_10K = $672F; // 10 kBit/s + PCAN_BAUD_5K = $7F7F; // 5 kBit/s + + // Represents the configuration for a CAN bit rate + // Note: + // * Each parameter and its value must be separated with a '='. + // * Each pair of parameter/value must be separated using ','. + // + // Example: + // f_clock=80000000,nom_brp=0,nom_tseg1=13,nom_tseg2=0,nom_sjw=0,data_brp=0,data_tseg1=13,data_tseg2=0,data_sjw=0 + // + PCAN_BR_CLOCK = 'f_clock'; + PCAN_BR_CLOCK_MHZ = 'f_clock_mhz'; + PCAN_BR_NOM_BRP = 'nom_brp'; + PCAN_BR_NOM_TSEG1 = 'nom_tseg1'; + PCAN_BR_NOM_TSEG2 = 'nom_tseg2'; + PCAN_BR_NOM_SJW = 'nom_sjw'; + PCAN_BR_NOM_SAMPLE = 'nom_sam'; + PCAN_BR_DATA_BRP = 'data_brp'; + PCAN_BR_DATA_TSEG1 = 'data_tseg1'; + PCAN_BR_DATA_TSEG2 = 'data_tseg2'; + PCAN_BR_DATA_SJW = 'data_sjw'; + PCAN_BR_DATA_SAMPLE = 'data_ssp_offset'; + + // Type of PCAN (non plug&play) hardware + // + PCAN_TYPE_ISA = $01; // PCAN-ISA 82C200 + PCAN_TYPE_ISA_SJA = $09; // PCAN-ISA SJA1000 + PCAN_TYPE_ISA_PHYTEC = $04; // PHYTEC ISA + PCAN_TYPE_DNG = $02; // PCAN-Dongle 82C200 + PCAN_TYPE_DNG_EPP = $03; // PCAN-Dongle EPP 82C200 + PCAN_TYPE_DNG_SJA = $05; // PCAN-Dongle SJA1000 + PCAN_TYPE_DNG_SJA_EPP = $06; // PCAN-Dongle EPP SJA1000 + +type + //////////////////////////////////////////////////////////// + // Type definitions + //////////////////////////////////////////////////////////// + + TPCANHandle = Word; // Represents a PCAN hardware channel handle + TPCANStatus = Longword; // Represents a PCAN status/error code + TPCANParameter = Byte; // Represents a PCAN parameter to be read or set + TPCANDevice = Byte; // Represents a PCAN device + TPCANMessageType = Byte; // Represents the type of a PCAN message + TPCANType = Byte; // Represents the type of PCAN hardware to be initialized + TPCANMode = Byte; // Represents a PCAN filter mode + TPCANBaudrate = Word; // Represents a PCAN Baud rate register value + TPCANBitrateFD = PAnsiChar;// Represents a PCAN-FD bit rate string + TPCANTimestampFD = UInt64; // Represents a timestamp of a received PCAN FD message + + //////////////////////////////////////////////////////////// + // Structure definitions + //////////////////////////////////////////////////////////// + + // Represents a PCAN message + // + TPCANMsg = record + ID: Longword; // 11/29-bit message identifier + MSGTYPE: TPCANMessageType; // Type of the message + LEN: Byte; // Data Length Code of the message (0..8) + DATA: array[0..7] of Byte; // Data of the message (DATA[0]..DATA[7]) + end; + + // Represents a timestamp of a received PCAN message. + // Total Microseconds = micros + 1000 * millis + 0x100000000 * 1000 * millis_overflow + // + TPCANTimestamp = record + millis: Longword; // Base-value: milliseconds: 0.. 2^32-1 + millis_overflow: Word; // Roll-arounds of millis + micros: Word; // Microseconds: 0..999 + end; + PTPCANTimestamp = ^TPCANTimestamp; + + // Represents a PCAN message from a FD capable hardware + // + TPCANMsgFD = record + ID: Longword; // 11/29-bit message identifier + MSGTYPE: TPCANMessageType; // Type of the message + DLC: Byte; // Data Length Code of the message (0..15) + DATA: array[0..63] of Byte; // Data of the message (DATA[0]..DATA[63]) + end; + PTPCANTimestampFD = ^TPCANTimestampFD; + +//////////////////////////////////////////////////////////// +// PCAN-Basic API function declarations +//////////////////////////////////////////////////////////// + +/// +/// Initializes a PCAN Channel +/// +/// The handle of a PCAN Channel +/// The speed for the communication (BTR0BTR1 code) +/// NON PLUG&PLAY: The type of hardware and operation mode +/// NON PLUG&PLAY: The I/O address for the parallel port +/// NON PLUG&PLAY: Interrupt number of the parallel port +/// A TPCANStatus error code +function CAN_Initialize( + Channel: TPCANHandle; + Btr0Btr1: TPCANBaudrate; + HwType: TPCANType; + IOPort: LongWord; + Interrupt: Word + ): TPCANStatus; stdcall; + +/// +/// Initializes a FD capable PCAN Channel +/// +/// "The handle of a FD capable PCAN Channel" +/// "The speed for the communication (FD bit rate string)" +/// See PCAN_BR_* values +/// * parameter and values ust be separated by '=' +/// * Couples of Parameter/value must be separated by ',' +/// * Following Parameter must be filled out: f_clock, data_brp, data_sjw, data_tseg1, data_tseg2, +/// nom_brp, nom_sjw, nom_tseg1, nom_tseg2. +/// * Following Parameters are optional (not used yet): data_ssp_offset, nom_samp +/// +/// f_clock_mhz=80,nom_brp=0,nom_tseg1=13,nom_tseg2=0,nom_sjw=0,data_brp=0, +/// data_tseg1=13,data_tseg2=0,data_sjw=0 +/// "A TPCANStatus error code" +function CAN_InitializeFD( + Channel: TPCANHandle; + BitrateFD: TPCANBitrateFD + ): TPCANStatus; stdcall; + +/// +/// Uninitializes one or all PCAN Channels initialized by CAN_Initialize +/// +/// Giving the TPCANHandle value "PCAN_NONEBUS", +/// uninitialize all initialized channels +/// The handle of a PCAN Channel +/// A TPCANStatus error code +function CAN_Uninitialize( + Channel: TPCANHandle + ): TPCANStatus; stdcall; + +/// +/// Resets the receive and transmit queues of the PCAN Channel +/// +/// A reset of the CAN controller is not performed +/// The handle of a PCAN Channel +/// A TPCANStatus error code +function CAN_Reset( + Channel: TPCANHandle + ): TPCANStatus; stdcall; + +/// +/// Gets the current status of a PCAN Channel +/// +/// The handle of a PCAN Channel +/// A TPCANStatus error code +function CAN_GetStatus( + Channel: TPCANHandle + ): TPCANStatus; stdcall; + +/// +/// Reads a CAN message from the receive queue of a PCAN Channel +/// +/// The handle of a PCAN Channel +/// A TPCANMsg structure buffer to store the CAN message +/// A TPCANTimestamp structure buffer to get +/// the reception time of the message +/// A TPCANStatus error code +function CAN_Read( + Channel: TPCANHandle; + var MessageBuffer: TPCANMsg; + TimestampBuffer: PTPCANTimestamp + ):TPCANStatus; stdcall; + +/// +/// Reads a CAN message from the receive queue of a FD capable PCAN Channel +/// +/// "The handle of a FD capable PCAN Channel" +/// "A TPCANMsgFD structure buffer to store the CAN message" +/// "A TPCANTimestampFD buffer to get +/// the reception time of the message. If this value is not desired, this parameter +/// should be passed as NULL" +/// "A TPCANStatus error code" +function CAN_ReadFD( + Channel: TPCANHandle; + var MessageBuffer: TPCANMsgFD; + TimestampBuffer: PTPCANTimestampFD + ): TPCANStatus; stdcall; + +/// +/// Transmits a CAN message +/// +/// The handle of a PCAN Channel +/// A TPCANMsg buffer with the message to be sent +/// A TPCANStatus error code +function CAN_Write( + Channel: TPCANHandle; + var MessageBuffer: TPCANMsg + ): TPCANStatus; stdcall; + +/// +/// Transmits a CAN message over a FD capable PCAN Channel +/// +/// "The handle of a FD capable PCAN Channel" +/// "A TPCANMsgFD buffer with the message to be sent" +/// "A TPCANStatus error code" +function CAN_WriteFD( + Channel: TPCANHandle; + var MessageBuffer: TPCANMsgFD + ): TPCANStatus; stdcall; + +/// +/// Configures the reception filter +/// +/// The message filter will be expanded with every call to +/// this function. If it is desired to reset the filter, please use +/// the 'SetValue' function +/// The handle of a PCAN Channel +/// The lowest CAN ID to be received +/// The highest CAN ID to be received +/// Message type, Standard (11-bit identifier) or +/// Extended (29-bit identifier) +/// A TPCANStatus error code +function CAN_FilterMessages( + Channel: TPCANHandle; + FromID: LongWord; + ToID: LongWord; + Mode: TPCANMode + ): TPCANStatus; stdcall; + +/// +/// Retrieves a PCAN Channel value +/// +/// Parameters can be present or not according with the kind +/// of Hardware (PCAN Channel) being used. If a parameter is not available, +/// a PCAN_ERROR_ILLPARAMTYPE error will be returned +/// The handle of a PCAN Channel +/// The TPCANParameter parameter to get +/// Buffer for the parameter value +/// Size in bytes of the buffer +/// A TPCANStatus error code +function CAN_GetValue( + Channel: TPCANHandle; + Parameter: TPCANParameter; + Buffer: Pointer; + BufferLength: LongWord + ): TPCANStatus; stdcall; + +/// +/// Configures or sets a PCAN Channel value +/// +/// Parameters can be present or not according with the kind +/// of Hardware (PCAN Channel) being used. If a parameter is not available, +/// a PCAN_ERROR_ILLPARAMTYPE error will be returned +/// The handle of a PCAN Channel +/// The TPCANParameter parameter to set +/// Buffer with the value to be set +/// Size in bytes of the buffer +/// A TPCANStatus error code +function CAN_SetValue( + Channel: TPCANHandle; + Parameter: TPCANParameter; + Buffer: Pointer; + BufferLength: LongWord + ): TPCANStatus; stdcall; + +/// +/// Returns a descriptive text of a given TPCANStatus error +/// code, in any desired language +/// +/// The current languages available for translation are: +/// Neutral (0x00), German (0x07), English (0x09), Spanish (0x0A), +/// Italian (0x10) and French (0x0C) +/// A TPCANStatus error code +/// Indicates a 'Primary language ID' +/// Buffer for the text (must be at least 256 in length) +/// A TPCANStatus error code +function CAN_GetErrorText( + Error: TPCANStatus; + Language: Word; + StringBuffer: PAnsiChar + ): TPCANStatus; stdcall; + +implementation +uses SysUtils; + +const DLL_Name = 'PCANBASIC.DLL'; + +function CAN_Initialize(Channel: TPCANHandle; Btr0Btr1: TPCANBaudrate; HwType: TPCANType; IOPort: LongWord; Interrupt: Word): TPCANStatus; stdcall; +external DLL_Name; + +function CAN_InitializeFD(Channel: TPCANHandle; BitrateFD: TPCANBitrateFD): TPCANStatus; stdcall; +external DLL_Name; + +function CAN_Uninitialize(Channel: TPCANHandle): TPCANStatus; stdcall; +external DLL_Name; + +function CAN_Reset(Channel: TPCANHandle): TPCANStatus; stdcall; +external DLL_Name; + +function CAN_GetStatus(Channel: TPCANHandle): TPCANStatus; stdcall; +external DLL_Name; + +function CAN_Read(Channel: TPCANHandle; var MessageBuffer: TPCANMsg; TimestampBuffer: PTPCANTimestamp):TPCANStatus; stdcall; +external DLL_Name; + +function CAN_ReadFD(Channel: TPCANHandle; var MessageBuffer: TPCANMsgFD; TimestampBuffer: PTPCANTimestampFD):TPCANStatus; stdcall; +external DLL_Name; + +function CAN_Write(Channel: TPCANHandle; var MessageBuffer: TPCANMsg): TPCANStatus; stdcall; +external DLL_Name; + +function CAN_WriteFD(Channel: TPCANHandle; var MessageBuffer: TPCANMsgFD): TPCANStatus; stdcall; +external DLL_Name; + +function CAN_FilterMessages(Channel: TPCANHandle; FromID: LongWord; ToID: LongWord; Mode: TPCANMode): TPCANStatus; stdcall; +external DLL_Name; + +function CAN_GetValue(Channel: TPCANHandle; Parameter: TPCANParameter; Buffer: Pointer; BufferLength: LongWord): TPCANStatus; stdcall; +external DLL_Name; + +function CAN_SetValue(Channel: TPCANHandle; Parameter: TPCANParameter; Buffer: Pointer; BufferLength: LongWord): TPCANStatus; stdcall; +external DLL_Name; + +function CAN_GetErrorText(Error: TPCANStatus; Language: Word; StringBuffer: PAnsiChar): TPCANStatus; stdcall; +external DLL_Name; + +end. \ No newline at end of file diff --git a/Host/Source/MicroBoot/interfaces/can/peak/PCANdrvD.pas b/Host/Source/MicroBoot/interfaces/can/peak/PCANdrvD.pas deleted file mode 100644 index dc43a464..00000000 --- a/Host/Source/MicroBoot/interfaces/can/peak/PCANdrvD.pas +++ /dev/null @@ -1,559 +0,0 @@ -unit PCANdrvD; -//*************************************************************************************** -// Project Name: TPCanDriver component for Borland Delphi -// Description: Encapsulates PCAN's Light driver into a VCL component for PCANUSB 1CH. -// File Name: PCANdrvD.pas -// -//--------------------------------------------------------------------------------------- -// C O P Y R I G H T -//--------------------------------------------------------------------------------------- -// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved -// -// This software has been carefully tested, but is not guaranteed for any particular -// purpose. The author does not offer any warranties and does not guarantee the accuracy, -// adequacy, or completeness of the software and is not responsible for any errors or -// omissions or the results obtained from use of the software. -// -//--------------------------------------------------------------------------------------- -// L I C E N S E -//--------------------------------------------------------------------------------------- -// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or -// modify it under the terms of the GNU General Public License as published by the Free -// Software Foundation, either version 3 of the License, or (at your option) any later -// version. -// -// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -// PURPOSE. See the GNU General Public License for more details. -// -// You have received a copy of the GNU General Public License along with OpenBLT. It -// should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy. -// -//*************************************************************************************** -interface - - -//*************************************************************************************** -// Includes -//*************************************************************************************** -uses - Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Pcan_usb; - - -//*************************************************************************************** -// Type Definitions -//*************************************************************************************** -type - TPCanChannel = ( pcanchannel0 ); - TPCanHardware = ( PCAN_USB1CH ); - TPCanDirection = ( PcanTx, PCanRx ); - TPCanMessage = packed record - id : LongInt; - dlc : Byte; - data : array [0..7] of Byte; - time : LongInt; - ext : Boolean; - end; - -type - TPCanMessageEvent = procedure( Sender: TObject; Direction: TPCanDirection; Message: TPCanMessage ) of object; - -type - TPCanEventThread = class(TThread) - private - { Private declarations } - FMethod: TThreadMethod; - protected - procedure Execute; override; - public - property Method : TThreadMethod read FMethod write FMethod; - end; - -type - TPCanDriver = class(TComponent) - private - { Private declarations } - FCanEventThread: TPCanEventThread; - FThreadRunning : boolean; - FCanConnected : boolean; - FStartTickCnt : DWORD; - function IsThreadRunning: boolean; - procedure ProcessReception; - protected - { Protected declarations } - FBaudRate : LongInt; - FChannel : TPCanChannel; - FHardware : TPCanHardware; - FPriority : TThreadPriority; - FExtendedId : Boolean; - FOnMessage : TPCanMessageEvent; - procedure SetBaudRate( Value: LongInt ); - procedure SetChannel( Value: TPCanChannel ); - procedure SetHardware( Value: TPCanHardware ); - procedure SetPriority( Value: TThreadPriority ); - procedure SetExtendedId( Value: Boolean ); - public - { Public declarations } - constructor Create( AOwner: TComponent ); override; - destructor Destroy; override; - function Connect: boolean; virtual; - procedure Disconnect; virtual; - function Transmit( Message: TPCanMessage): boolean; virtual; - function IsConnected: boolean; virtual; - function IsComError: boolean; virtual; - published - { Published declarations } - property BaudRate : LongInt read FBaudRate write SetBaudRate default 500000; - property Channel : TPCanChannel read FChannel write SetChannel default pcanchannel0; - property Hardware : TPCanHardware read FHardware write SetHardware default PCAN_USB1CH; - property Priority : TThreadPriority read FPriority write SetPriority default tpNormal; - property ExtendedId : Boolean read FExtendedId write SetExtendedId default False; - property OnMessage : TPCanMessageEvent read FOnMessage write FOnMessage; - end; - - -//*************************************************************************************** -// Prototypes -//*************************************************************************************** -procedure Register; - -implementation -//*************************************************************************************** -// NAME: Execute -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Overriden Execute function for the CanEventThread. Calls and synchro- -// nizes with the TCanDriver.ProcessEvents function. -// -//*************************************************************************************** -procedure TPCanEventThread.Execute; -begin - while not Terminated do - begin - if Assigned(Method) then // make sure TPCanDriver.ProcessEvents is set - Synchronize(Method); // call and synchronize - end; -end; //*** end of Execute *** - - -//*************************************************************************************** -// NAME: Create -// PRECONDITIONS: none -// PARAMETER: AOwner : owner of the component -// RETURN VALUE: none -// DESCRIPTION: Component constructor. Calls TComponent's constructor and initializes -// the private property variables to their default values. -// -//*************************************************************************************** -constructor TPCanDriver.Create( AOwner: TComponent ); -begin - // call inherited constructor - inherited Create( AOwner ); - - // set defaults for internal variables - FThreadRunning := False; - FCanConnected := False; - - // set defaults for properties - FBaudRate := 500000; - FChannel := pcanchannel0; - FHardware := PCAN_USB1CH; - FPriority := tpNormal; - FExtendedId := False; -end; //*** end of Create *** - - -//*************************************************************************************** -// NAME: Destroy -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Component destructor. Calls TComponent's destructor -// -//*************************************************************************************** -destructor TPCanDriver.Destroy; -begin - Disconnect; // close the port and driver - inherited Destroy; // call inherited destructor -end; //*** end of Destroy *** - - -//*************************************************************************************** -// NAME: IsConnected -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: True or False -// DESCRIPTION: Determines whether or not the CAN driver is connected and active -// -//*************************************************************************************** -function TPCanDriver.IsConnected: boolean; -begin - Result := FCanConnected; -end; //*** end of IsConnected *** - - -//*************************************************************************************** -// NAME: IsComError -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: True if the communication interface is in error state, False otherwise -// DESCRIPTION: Determines whether or not the CAN controller is in error state. -// -//*************************************************************************************** -function TPCanDriver.IsComError: boolean; -begin - // check for bus off - result := ((CAN_Status and CAN_ERR_BUSOFF) <> 0); -end; //*** end of IsComError *** - - -//*************************************************************************************** -// NAME: IsThreadRunning -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: True or False -// DESCRIPTION: Determines whether or not the CAN event thread is running -// -//*************************************************************************************** -function TPCanDriver.IsThreadRunning: boolean; -begin - if FThreadRunning = True then - Result := True - else - Result := False; -end; //*** end of IsThreadRunning *** - - -//*************************************************************************************** -// NAME: SetBaudRate -// PRECONDITIONS: none -// PARAMETER: Value : new baudrate value [0 - 1000000 bps] -// RETURN VALUE: none -// DESCRIPTION: Configures the baudrate -// -// |------------------------------------------------------------------------------------ -// | Update baudrate configuration -// |------------------------------------------------------------------------------------ -//*************************************************************************************** -procedure TPCanDriver.SetBaudRate( Value: LongInt ); -begin - FBaudRate := Value; // update property -end; //*** end of SetBaudRate *** - - -//*************************************************************************************** -// NAME: SetChannel -// PRECONDITIONS: none -// PARAMETER: Value : channel0 or channel1 -// RETURN VALUE: none -// DESCRIPTION: Configures the used CAN channel -// -// |------------------------------------------------------------------------------------ -// | Update channel configuration -// |------------------------------------------------------------------------------------ -//*************************************************************************************** -procedure TPCanDriver.SetChannel( Value: TPCanChannel ); -begin - FChannel := Value; -end; //*** end of SetChannel *** - - -//*************************************************************************************** -// NAME: SetHardware -// PRECONDITIONS: none -// PARAMETER: Value : type of CAN hardware (Virtual, CANcardXL, etc.) -// RETURN VALUE: none -// DESCRIPTION: Configures the used CAN hardware -// -// |------------------------------------------------------------------------------------ -// | Update hardware configuration -// |------------------------------------------------------------------------------------ -//*************************************************************************************** -procedure TPCanDriver.SetHardware( Value: TPCanHardware ); -begin - FHardware := Value; -end; //*** end of SetHardware *** - - -//*************************************************************************************** -// NAME: SetPriority -// PRECONDITIONS: none -// PARAMETER: Value : thread priority -// RETURN VALUE: none -// DESCRIPTION: Configures the priority for the CAN event thread -// -// |------------------------------------------------------------------------------------ -// | y\ Is Thread running? /n -// |------------------------------------------------------------------------------------ -// | Stop Thread | -// | Update Thread priority | Update Thread priority -// | Restart Thread | -// |------------------------------------------------------------------------------------ -//*************************************************************************************** -procedure TPCanDriver.SetPriority( Value: TThreadPriority ); -begin - if IsThreadRunning then - begin - FCanEventThread.Suspend; // suspend the thread - FPriority := Value; // update the priority - FCanEventThread.Resume; // resume the thread - end - else - begin - FPriority := Value; // update the priority - end; -end; //*** end of SetPriority *** - - -//*************************************************************************************** -// NAME: SetExtendedId -// PRECONDITIONS: none -// PARAMETER: Value : true = support only 29-bit id's, false = support only 11-bit -// RETURN VALUE: none -// DESCRIPTION: Configures the support of extended 29-bit identifiers -// -// |------------------------------------------------------------------------------------ -// | Update extended id support selection -// |------------------------------------------------------------------------------------ -//*************************************************************************************** -procedure TPCanDriver.SetExtendedId( Value: Boolean ); -begin - FExtendedId := Value; -end; //*** end of SetExtendedId ***/ - - -//*************************************************************************************** -// NAME: Connect -// PRECONDITIONS: Disconnected from CAN bus -// PARAMETER: none -// RETURN VALUE: True or False for succees or error, respectively -// DESCRIPTION: Initializes the CAN driver and synchronizes the hardware with the CAN -// bus. -// -//*************************************************************************************** -function TPCanDriver.Connect: boolean; -var - Baudcode : Word; - MsgType : Integer; - -begin - Result := False; - FThreadRunning := False; - FCanConnected := False; - - // convert baudrate in bps to supported baudrate code - Baudcode := CAN_BAUD_500K; // init local - case FBaudRate of - 5000 : Baudcode := CAN_BAUD_5K; - 10000 : Baudcode := CAN_BAUD_10K; - 20000 : Baudcode := CAN_BAUD_20K; - 33333 : Baudcode := $1D14; - 50000 : Baudcode := CAN_BAUD_50K; - 83333 : Baudcode := $4B14; - 100000 : Baudcode := CAN_BAUD_100K; - 125000 : Baudcode := CAN_BAUD_125K; - 250000 : Baudcode := CAN_BAUD_250K; - 500000 : Baudcode := CAN_BAUD_500K; - 1000000 : Baudcode := CAN_BAUD_1M; - end; - - // convert extented id info - if FExtendedId then - MsgType := 1 - else - MsgType := 0; - - //-------------------------- open the driver ------------------------------------------ - if CAN_Init(Baudcode, MsgType) <> CAN_ERR_OK then Exit; - - - - //-------------------------- open the acceptance filter -------------------------------- - if CAN_ResetFilter <> CAN_ERR_OK then - begin - CAN_Close; - Exit; - end; - - if FExtendedId then - begin - if CAN_MsgFilter($000, $1FFFFFFF, MSGTYPE_EXTENDED) <> CAN_ERR_OK then - begin - CAN_Close; - Exit; - end; - end - else - begin - if CAN_MsgFilter($000, $7FF, MSGTYPE_STANDARD) <> CAN_ERR_OK then - begin - CAN_Close; - Exit; - end; - end; - - //-------------------------- reset message queues ------------------------------------- - if CAN_ResetClient <> CAN_ERR_OK then - begin - CAN_Close; - Exit; - end; - - //-------------------------- start CAN event thread ----------------------------------- - FCanEventThread := TPCanEventThread.Create(True); // create and suspend - FCanEventThread.FreeOnTerminate := True; // auto free on termination - FCanEventThread.Method := ProcessReception; // set method - FCanEventThread.Resume; // start - FThreadRunning := True; - - - //-------------------------- store start time for time stamps ------------------------- - FStartTickCnt := GetTickCount; - - //-------------------------- success -------------------------------------------------- - FCanConnected := True; - Result := True; // successfully initialized the driver -end; //*** end of Connect *** - - -//*************************************************************************************** -// NAME: Disconnect -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Disconnects the CAN driver -// -//*************************************************************************************** -procedure TPCanDriver.Disconnect; -begin - if IsConnected = True then // are we connected? - begin - FCanConnected := False; - // close the channel - CAN_Close; - end; - - if IsThreadRunning then - begin - FCanEventThread.Terminate; // stop - FThreadRunning := False; - end; -end; //*** end of Disconnect *** - - -//*************************************************************************************** -// NAME: Transmit -// PRECONDITIONS: Driver initialized using 'Connect' -// PARAMETER: Message: CAN message that is to be transmitted -// RETURN VALUE: True or False for succees or error, respectively -// DESCRIPTION: Transmits a CAN message. -// -//*************************************************************************************** -function TPCanDriver.Transmit( Message: TPCanMessage): boolean; -var - cnt : Byte; - msg : TPCANMsg; - msgcpy : TPCanMessage; -begin - // make sure the CAN driver is connected - if not IsConnected then - begin - Result := False; // can't transmit it not connected - exit; // no need to continue - end; - - // set the message identifier - msg.ID := Message.id; - if Message.ext then - msg.MSGTYPE := MSGTYPE_EXTENDED - else - msg.MSGTYPE := MSGTYPE_STANDARD; - - // set the data length - msg.LEN := Message.dlc; - - // store the data bytes - for cnt :=0 to Message.dlc do - begin - msg.DATA[cnt] := Message.data[cnt]; - end; - - // submit the transmit request - if CAN_Write(msg) <> CAN_ERR_OK then - begin - Result := False; - exit; - end; - - //---------------- process transmission confirmation -------------------------- - if Assigned( FOnMessage ) then - begin - msgcpy := Message; - msgcpy.time := GetTickCount - FStartTickCnt; - FOnMessage( Self, PCanTx, msgcpy ); // call application's event handler - end; - - Result := True; -end; //*** end of Transmit *** - - -//*************************************************************************************** -// NAME: ProcessReception -// PRECONDITIONS: thread running -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Called by the CAN event tread. This function traps and processes CAN -// events for OnMessage. -// -//*************************************************************************************** -procedure TPCanDriver.ProcessReception; -var - cnt : Byte; - msg : TPCanMessage; - msgraw : TPCANMsg; -begin - //---------------- process reception indication ------------------------------- - // continue only if a new message is present in the queue - if CAN_Read(msgraw) <> CAN_ERR_OK then - Exit; - - // only process CAN messages and not the status messages - if (msgraw.MSGTYPE = MSGTYPE_EXTENDED) or (msgraw.MSGTYPE = MSGTYPE_STANDARD) then - begin - // copy the message info - msg.time := GetTickCount - FStartTickCnt; - msg.id := msgraw.ID; - msg.dlc := msgraw.LEN; - // store the data bytes - for cnt :=0 to msg.dlc do - begin - msg.data[cnt] := msgraw.DATA[cnt]; - end; - - if Assigned( FOnMessage ) then - begin - FOnMessage( Self, PCanRx, msg ); // call application's event handler - end; - end; -end; //*** end of ProcessReception *** - - -//*************************************************************************************** -// NAME: Register -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Registers the TPCanDriver component into Borland Delphi's IDE. -// -//*************************************************************************************** -procedure Register; -begin - RegisterComponents('Feaser', [TPCanDriver]); -end; //*** end of Register *** - - -end. -//********************************** end of PCANdrvD.pas ******************************** - - diff --git a/Host/Source/MicroBoot/interfaces/can/peak/Pcan_usb.pas b/Host/Source/MicroBoot/interfaces/can/peak/Pcan_usb.pas deleted file mode 100644 index 2c7a4259..00000000 --- a/Host/Source/MicroBoot/interfaces/can/peak/Pcan_usb.pas +++ /dev/null @@ -1,372 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// PCAN-Light -// PCAN_USB.pas -// -// Version 2.x -// -// ~~~~~~~~~~ -// -// Definition of the PCAN-Light API. -// The Driver support a Hardware and a Software who want to communicate with CAN-busses -// -// ~~~~~~~~~~~~ -// -// PCAN-Light-API -// -// ~~~~~~~~~~~~ -// -// - CAN_Init(wBTR0BTR1: Word; CANMsgType: Integer) -// - CAN_Close() -// - CAN_Status() -// - CAN_Write(var MsgBuff: TPCANMsg) -// - CAN_Read(var MsgBuff: TPCANMsg) -// - CAN_ReadEx(var MsgBuff: TPCANMsg; var RcvTime: TPCANTimestamp) -// - CAN_VersionInfo(lpszTextBuff: PChar) -// - CAN_DLLVersionInfo(lpszTextBuff: PChar) -// - CAN_SpecialFunktion(distributorcode: LongWord; codenumber: Integer) -// - CAN_ResetClient() -// - CAN_MsgFilter(FromID, ToID: LongWord; _Type: Integer) -// - CAN_ResetFilter() -// - SetUSBDeviceNr(DevNum: Integer) -// - GetUSBDeviceNr(var DevNum: Integer) -// - CAN_SetRcvFunc(hEvent: THandle) -// -// ------------------------------------------------------------------ -// Author : Hoppe, Wilhelm -// Modified By: Wagner (29.09.2009) -// -// Language: PASCAL OO -// ------------------------------------------------------------------ -// -// Copyright (C) 1999-2009 PEAK-System Technik GmbH, Darmstadt -// -unit pcan_usb; - -interface - -const - // Constants definitions - Frame Type - // - CAN_INIT_TYPE_EX = $01; //Extended Frame - CAN_INIT_TYPE_ST = $00; //Standart Frame - - // Constants definitions - ID - // - CAN_MAX_STANDARD_ID = $7ff; - CAN_MAX_EXTENDED_ID = $1fffffff; - - // Constants definitions - CAN message types - // - MSGTYPE_STANDARD = $00; // Standard Data frame (11-bit ID) - MSGTYPE_RTR = $01; // 1, if Remote Request frame - MSGTYPE_EXTENDED = $02; // 1, if Extended Data frame (CAN 2.0B, 29-bit ID) - MSGTYPE_ERROR = $80; // 1, if Status information - - // Baud rate codes = BTR0/BTR1 register values for the CAN controller. - // You can define your own Baudrate with the BTROBTR1 register !! - // take a look at www.peak-system.com for our software BAUDTOOL to - // calculate the BTROBTR1 register for every baudrate and sample point. - // - CAN_BAUD_1M = $0014; // 1 MBit/s - CAN_BAUD_500K = $001C; // 500 kBit/s - CAN_BAUD_250K = $011C; // 250 kBit/s - CAN_BAUD_125K = $031C; // 125 kBit/s - CAN_BAUD_100K = $432F; // 100 kBit/s - CAN_BAUD_50K = $472F; // 50 kBit/s - CAN_BAUD_20K = $532F; // 20 kBit/s - CAN_BAUD_10K = $672F; // 10 kBit/s - CAN_BAUD_5K = $7F7F; // 5 kBit/s - - // Error codes (bit code) - // - CAN_ERR_OK = $0000; // No error - CAN_ERR_XMTFULL = $0001; // Transmit buffer in CAN controller is full - CAN_ERR_OVERRUN = $0002; // CAN controller was read too late - CAN_ERR_BUSLIGHT = $0004; // Bus error: an error counter reached the 'light' limit - CAN_ERR_BUSHEAVY = $0008; // Bus error: an error counter reached the 'heavy' limit - CAN_ERR_BUSOFF = $0010; // Bus error: the CAN controller is in bus-off state - CAN_ERR_QRCVEMPTY = $0020; // Receive queue is empty - CAN_ERR_QOVERRUN = $0040; // Receive queue was read too late - CAN_ERR_QXMTFULL = $0080; // Transmit queue ist full - CAN_ERR_REGTEST = $0100; // Test of the CAN controller hardware registers failed (no hardware found) - CAN_ERR_NOVXD = $0200; // Driver not loaded - CAN_ERR_NODRIVER = $0200; // Driver not loaded - CAN_ERRMASK_ILLHANDLE=$1C00; // Mask for all handle errors - CAN_ERR_HWINUSE = $0400; // Hardware already in use by a Net - CAN_ERR_NETINUSE = $0800; // a Client is already connected to the Net - CAN_ERR_ILLHW = $1400; // Hardware handle is invalid - CAN_ERR_ILLNET = $1800; // Net handle is invalid - CAN_ERR_ILLCLIENT = $1C00; // Client handle is invalid - CAN_ERR_RESOURCE = $2000; // Resource (FIFO, Client, timeout) cannot be created - CAN_ERR_ILLPARAMTYPE = $4000; // Invalid parameter - CAN_ERR_ILLPARAMVAL = $8000; // Invalid parameter value - CAN_ERR_UNKNOWN = $10000; // Unknown error - CAN_ERR_ANYBUSERR = (CAN_ERR_BUSLIGHT or CAN_ERR_BUSHEAVY or CAN_ERR_BUSOFF); - - -type - // CAN Message - // - TPCANMsg = record - ID: LongWord; // 11/29 bit identifier - MSGTYPE: Byte; // Bits from MSGTYPE_* - LEN: Byte; // Data Length Code of the Msg (0..8) - DATA: array[0..7] of Byte; // Data 0 .. 7 - end; - - // Timestamp of a receive/transmit event - // Total microseconds = micros + 1000 * millis + 0xFFFFFFFF * 1000 * millis_overflow - // - TPCANTimestamp = record - millis: LongWord; // Base-value: milliseconds: 0.. 2^32-1 - millis_overflow: Word; // Roll-arounds of millis - micros: Word; // Microseconds: 0..999 - end; - -/////////////////////////////////////////////////////////////////////////////// -// CAN_Init() -// This function make the following: -// - Activate a Hardware -// - Make a Register Test of 82C200/SJA1000 -// - Allocate a Send buffer and a Hardware handle -// - Programs the configuration of the transmit/receive driver -// - Set the Baudrate register -// - Set the Controller in RESET condition -// -// If CANMsgType=0 ---> ID 11Bit -// If CANMsgType=1 ---> ID 11/29Bit -// -// Possible Errors: NOVXD ILLHW REGTEST RESOURCE -// -function CAN_Init(wBTR0BTR1: Word; - CANMsgType: Integer): LongWord; stdcall; - -/////////////////////////////////////////////////////////////////////////////// -// CAN_Close() -// This function terminate and release the configured hardware and all -// allocated resources -// -// Possible Errors: NOVXD -// -function CAN_Close: LongWord; stdcall; - -/////////////////////////////////////////////////////////////////////////////// -// CAN_Status() -// This function request the current status of the hardware (b.e. BUS-OFF) -// -// Possible Errors: NOVXD BUSOFF BUSHEAVY OVERRUN -// -function CAN_Status: LongWord; stdcall; - -/////////////////////////////////////////////////////////////////////////////// -// CAN_Write() -// This function Place a CAN message into the Transmit Queue of the CAN Hardware -// -// Possible Errors: NOVXD RESOURCE BUSOFF QXMTFULL -// -function CAN_Write(var MsgBuff: TPCANMsg): LongWord; stdcall; - -/////////////////////////////////////////////////////////////////////////////// -// CAN_Read() -// This function get the next message or the next error from the Receive Queue of -// the CAN Hardware. -// REMARK: -// - Check always the type of the received Message (MSGTYPE_STANDARD,MSGTYPE_RTR, -// MSGTYPE_EXTENDED,MSGTYPE_STATUS) -// - The function will return ERR_OK always that you receive a CAN message successfully -// although if the messages is a MSGTYPE_STATUS message. -// - When a MSGTYPE_STATUS mesasge is got, the ID and Length information of the message -// will be treated as indefined values. Actually information of the received message -// should be interpreted using the first 4 data bytes as follow: -// * Data0 Data1 Data2 Data3 Kind of Error -// 0x00 0x00 0x00 0x02 CAN_ERR_OVERRUN 0x0002 CAN Controller was read to late -// 0x00 0x00 0x00 0x04 CAN_ERR_BUSLIGHT 0x0004 Bus Error: An error counter limit reached (96) -// 0x00 0x00 0x00 0x08 CAN_ERR_BUSHEAVY 0x0008 Bus Error: An error counter limit reached (128) -// 0x00 0x00 0x00 0x10 CAN_ERR_BUSOFF 0x0010 Bus Error: Can Controller went "Bus-Off" -// - If a CAN_ERR_BUSOFF status message is received, the CAN Controller must to be -// initialized again using the Init() function. Otherwise, will be not possible -// to send/receive more messages. -// - The message will be written to 'msgbuff'. -// -// Possible Errors: NOVXD QRCVEMPTY -// -function CAN_Read(var MsgBuff: TPCANMsg): LongWord; stdcall; - -/////////////////////////////////////////////////////////////////////////////// -// CAN_ReadEx() -// This function get the next message or the next error from the Receive Queue of -// the CAN Hardware and the time when the message arrived. -// REMARK: -// - Check always the type of the received Message (MSGTYPE_STANDARD,MSGTYPE_RTR, -// MSGTYPE_EXTENDED,MSGTYPE_STATUS) -// - The function will return ERR_OK always that you receive a CAN message successfully -// although if the messages is a MSGTYPE_STATUS message. -// - When a MSGTYPE_STATUS mesasge is got, the ID and Length information of the message -// will be treated as indefined values. Actually information of the received message -// should be interpreted using the first 4 data bytes as follow: -// * Data0 Data1 Data2 Data3 Kind of Error -// 0x00 0x00 0x00 0x02 CAN_ERR_OVERRUN 0x0002 CAN Controller was read to late -// 0x00 0x00 0x00 0x04 CAN_ERR_BUSLIGHT 0x0004 Bus Error: An error counter limit reached (96) -// 0x00 0x00 0x00 0x08 CAN_ERR_BUSHEAVY 0x0008 Bus Error: An error counter limit reached (128) -// 0x00 0x00 0x00 0x10 CAN_ERR_BUSOFF 0x0010 Bus Error: Can Controller went "Bus-Off" -// - If a CAN_ERR_BUSOFF status message is received, the CAN Controller must to be -// initialized again using the Init() function. Otherwise, will be not possible -// to send/receive more messages. -// - The message will be written to 'msgbuff'. -// Since Version 2.x the Ext. Version is available - new Parameter: -// - Receive timestamp -// -// Possible Errors: NOVXD QRCVEMPTY -// -function CAN_ReadEx( - var MsgBuff: TPCANMsg; - var RcvTime: TPCANTimestamp - ): LongWord; stdcall; - -/////////////////////////////////////////////////////////////////////////////// -// CAN_VersionInfo() -// This function get the Version and copyright of the hardware as text -// (max. 255 characters) -// -// Possible Errors: NOVXD -// -function CAN_VersionInfo( - lpszTextBuff: PChar - ): LongWord; stdcall; - -/////////////////////////////////////////////////////////////////////////////// -// CAN_DLLVersionInfo() -// This function is used to get the Version and copyright of the DLL as -// text (max. 255 characters) -// -// Possible Errors: -1 for NULL-Pointer parameters :-) -// -function CAN_DLLVersionInfo( - lpszTextBuff: PChar - ): LongWord; stdcall; - -/////////////////////////////////////////////////////////////////////////////// -// CAN_SpecialFunktion() -// This function is an special function to be used "ONLY" for distributors -// Return: 1 - the given parameters and the parameters in the hardware agree -// 0 - otherwise -// -// Possible Errors: NOVXD -// -function CAN_SpecialFunktion( - distributorcode: LongWord; - codenumber: Integer - ): LongWord; stdcall; - -////////////////////////////////////////////////////////////////////////////// -// CAN_ResetClient() -// This function delete the both queues (Transmit,Receive) of the CAN Controller -// using a RESET -// -// Possible Errors: ERR_ILLCLIENT ERR_NOVXD -// -function CAN_ResetClient: LongWord; stdcall; - -/////////////////////////////////////////////////////////////////////////////// -// CAN_MsgFilter(FromID, ToID, int Type) -// This function set the receive message filter of the CAN Controller. -// REMARK: -// - A quick register of all messages is possible using the parameters FromID and ToID = 0 -// - Every call of this function maybe cause an extention of the receive filter of the -// CAN controller, which one can go briefly to RESET -// - New in Ver 2.x: -// * Standard frames will be put it down in the acc_mask/code as Bits 28..13 -// * Hardware driver for 82C200 must to be moved to Bits 10..0 again! -// WARNING: -// It is not guaranteed to receive ONLY the registered messages. -// -// Possible Errors: NOVXD ILLCLIENT ILLNET REGTEST -// -function CAN_MsgFilter(FromID, ToID: LongWord; _Type: Integer): LongWord; stdcall; - -/////////////////////////////////////////////////////////////////////////////// -// CAN_ResetFilter() -// This function close completely the Message Filter of the Hardware. -// They will be no more messages received. -// -// Possible Errors: NOVXD -// -function CAN_ResetFilter: LongWord; stdcall; - -////////////////////////////////////////////////////////////////////////////// -// SetUSBDeviceNr() -// This function set an identification number to the USB CAN hardware -// -// Possible Errors: NOVXD ILLHW ILLPARAMTYPE ILLPARAMVAL REGTEST -// -function SetUSBDeviceNr(DevNum: LongWord): LongWord; stdcall; - -////////////////////////////////////////////////////////////////////////////// -// GetUSBDeviceNr() -// This function read the device number of a USB CAN Hardware -// -// Possible Errors: NOVXD ILLHW ILLPARAMTYPE -// -function GetUSBDeviceNr(var DevNum: LongWord): LongWord; stdcall; - -/////////////////////////////////////////////////////////////////////////////// -// CAN_SetRcvEvent() -// This function is used to set the Event for the Event Handler -// -// Possible Errors: ILLCLIENT ILLPARAMTYPE ILLPARAMVAL NOVXD -// -function CAN_SetRcvEvent(hEvent: LongInt): LongWord; stdcall; - - -implementation - -uses SysUtils; - -const DLL_Name = 'PCAN_USB.dll'; - -function CAN_Init(wBTR0BTR1: Word; CANMsgType: Integer): LongWord; stdcall; -external DLL_Name; - -function CAN_Close: LongWord; stdcall; -external DLL_Name; - -function CAN_Status: LongWord; stdcall; -external DLL_Name; - -function CAN_Write(var MsgBuff: TPCANMsg): LongWord; stdcall; -external DLL_Name; - -function CAN_Read(var MsgBuff: TPCANMsg): LongWord; stdcall; -external DLL_Name; - -function CAN_ReadEx(var MsgBuff: TPCANMsg; var RcvTime: TPCANTimestamp): LongWord; stdcall; -external DLL_NAME; - -function CAN_VersionInfo(lpszTextBuff: PChar): LongWord; stdcall; -external DLL_Name; - -function CAN_DLLVersionInfo(lpszTextBuff: PChar): LongWord; stdcall; -external DLL_Name; - -function CAN_SpecialFunktion(distributorcode: LongWord; codenumber: Integer): LongWord; stdcall; -external DLL_Name; - -function CAN_ResetClient: LongWord; stdcall; -external DLL_Name; - -function CAN_MsgFilter(FromID, ToID: LongWord; _Type: Integer): LongWord; stdcall; -external DLL_Name; - -function CAN_ResetFilter: LongWord; stdcall; -external DLL_Name; - -function SetUSBDeviceNr(DevNum: LongWord): LongWord; stdcall; -external DLL_Name; - -function GetUSBDeviceNr(var DevNum: LongWord): LongWord; stdcall; -external DLL_Name; - -function CAN_SetRcvEvent(hEvent: LongInt):LongWord; stdcall; -external DLL_Name; - -end. diff --git a/Host/Source/MicroBoot/interfaces/can/peak/XcpSettings.dfm b/Host/Source/MicroBoot/interfaces/can/peak/XcpSettings.dfm index 8bb21c85..22d0b1cc 100644 Binary files a/Host/Source/MicroBoot/interfaces/can/peak/XcpSettings.dfm and b/Host/Source/MicroBoot/interfaces/can/peak/XcpSettings.dfm differ diff --git a/Host/Source/MicroBoot/interfaces/can/peak/XcpSettings.pas b/Host/Source/MicroBoot/interfaces/can/peak/XcpSettings.pas index ec639384..7e312609 100644 --- a/Host/Source/MicroBoot/interfaces/can/peak/XcpSettings.pas +++ b/Host/Source/MicroBoot/interfaces/can/peak/XcpSettings.pas @@ -36,7 +36,7 @@ interface //*************************************************************************************** uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, - StdCtrls, ComCtrls, ExtCtrls, IniFiles; + StdCtrls, ComCtrls, ExtCtrls, IniFiles, Vcl.Imaging.pngimage; //*************************************************************************************** @@ -60,7 +60,6 @@ type cmbChannel: TComboBox; lblBaudRate: TLabel; chbExtendedId: TCheckBox; - edtBaudRate: TEdit; lblT1: TLabel; lblT3: TLabel; lblT4: TLabel; @@ -83,13 +82,22 @@ type openDialog: TOpenDialog; edtTconnect: TEdit; lblTconnect: TLabel; + cmbBaudrate: TComboBox; procedure btnOKClick(Sender: TObject); procedure btnCancelClick(Sender: TObject); procedure btnBrowseClick(Sender: TObject); + procedure cmbHardwareChange(Sender: TObject); + procedure edtTransmitIdChange(Sender: TObject); + procedure edtTransmitIdKeyPress(Sender: TObject; var Key: Char); + procedure edtReceiveIdKeyPress(Sender: TObject; var Key: Char); + procedure edtReceiveIdChange(Sender: TObject); private { Private declarations } + procedure ValidateHexCanIdInputChange(EdtID: TEdit); + procedure ValidateHexCanIdInputPress(Sender: TObject; var Key: char); public { Public declarations } + procedure SetAvailableChannels; end; type @@ -106,6 +114,187 @@ type implementation {$R *.DFM} + +//*************************************************************************************** +// NAME: SetAvailableChannels +// PARAMETER: none +// RETURN VALUE: none +// DESCRIPTION: Updates the items in the channels combobox based on the selected +// hardware. +// +//*************************************************************************************** +procedure TXcpSettingsForm.SetAvailableChannels; +var + maxChannels: Integer; + channelCnt: Integer; + oldSelectedIdx: Integer; +begin + // init to safe value + maxChannels := 2; + + case cmbHardware.ItemIndex of + 0 , 1: { PCAN USB or PCAN PCI } + begin + maxChannels := 8; + end; + 2: { PCAN PC Card } + begin + maxChannels := 2; + end; + end; + + // backup currently selected channel + oldSelectedIdx := cmbChannel.ItemIndex; + + // update the combobox contents + cmbChannel.Items.Clear; + for channelCnt := 1 to maxChannels do + begin + cmbChannel.Items.Add('Channel' + InttoStr(channelCnt)); + end; + cmbChannel.DropDownCount := maxChannels; + + // restore the selected channel + if oldSelectedIdx >= (maxChannels) then + begin + cmbChannel.ItemIndex := 0; + end + else + begin + cmbChannel.ItemIndex := oldSelectedIdx; + end; +end; //*** end of SetAvailableChannels *** + + +//*************************************************************************************** +// NAME: ValidateHexCanIdInputChange +// PARAMETER: EdtID Signal source. +// RETURN VALUE: none. +// DESCRIPTION: Checks to see if a valid hexadecimal CAN identifier was entered in +// the specified edit box. Should be called in the edit box's onChange +// event handler. +// +//*************************************************************************************** +procedure TXcpSettingsForm.ValidateHexCanIdInputChange(EdtID: TEdit); +var + value: Int64; +begin + // prevent a message identifier > 0x1FFFFFFF from being entered + if EdtID.Text <> '' then + begin + try + value := StrToInt64('$' + EdtID.Text); + if value < 0 then + begin + EdtID.Text := '0'; + end + else if value > $1FFFFFFF then + begin + EdtID.Text := '1FFFFFFF'; + end; + // automatically set extended if flag + if value > $7ff then + chbExtendedId.Checked := True; + except + // use id 0 if a non hex value was entered, for example through copy-paste + EdtID.Text := '0'; + end; + end; +end; //*** end of ValidateHexCanIdInputChange *** + + +//*************************************************************************************** +// NAME: ValidateHexCanIdInputPress +// PARAMETER: Sender Signal source. +// Key The key's character code that was pressed. +// RETURN VALUE: none. +// DESCRIPTION: Checks to see if a valid hexadecimal CAN identifier was entered in +// the specified edit box. Should be called in the edit box's onPress +// event handler. +// +//*************************************************************************************** +procedure TXcpSettingsForm.ValidateHexCanIdInputPress(Sender: TObject; var Key: char); +begin + if not (AnsiChar(Key) In ['0'..'9', 'a'..'f', 'A'..'F', #8, ^V, ^C]) then // #8 = backspace + begin + // ignore it + Key := #0; + end; + // convert a..f to upper case + if AnsiChar(Key) In ['a'..'f'] then + begin + Key := UpCase(Key); + end; +end; //*** end of ValidateHexCanIdInputPress *** + + +//*************************************************************************************** +// NAME: cmbHardwareChange +// PARAMETER: none +// RETURN VALUE: modal result +// DESCRIPTION: Event handler for when the hardware combobox selection changed. +// +//*************************************************************************************** +procedure TXcpSettingsForm.cmbHardwareChange(Sender: TObject); +begin + SetAvailableChannels; +end; //*** end of cmbHardwareChange *** + + +//*************************************************************************************** +// NAME: edtTransmitIdChange +// PARAMETER: Sender Signal source. +// RETURN VALUE: None. +// DESCRIPTION: Called when the text in the edit box changed. +// +//*************************************************************************************** +procedure TXcpSettingsForm.edtReceiveIdChange(Sender: TObject); +begin + ValidateHexCanIdInputChange(edtReceiveId); +end; //*** end of edtReceiveIdChange *** + + +//*************************************************************************************** +// NAME: edtReceiveIdKeyPress +// PARAMETER: Sender Signal source. +// Key The key's character code that was pressed. +// RETURN VALUE: None. +// DESCRIPTION: Called when a key is pressed. +// +//*************************************************************************************** +procedure TXcpSettingsForm.edtReceiveIdKeyPress(Sender: TObject; var Key: Char); +begin + ValidateHexCanIdInputPress(edtReceiveId, Key); +end; //*** end of edtReceiveIdKeyPress *** + + +//*************************************************************************************** +// NAME: edtTransmitIdChange +// PARAMETER: Sender Signal source. +// RETURN VALUE: None. +// DESCRIPTION: Called when the text in the edit box changed. +// +//*************************************************************************************** +procedure TXcpSettingsForm.edtTransmitIdChange(Sender: TObject); +begin + ValidateHexCanIdInputChange(edtTransmitId); +end; //*** end of edtTransmitIdChange *** + + +//*************************************************************************************** +// NAME: edtTransmitIdKeyPress +// PARAMETER: Sender Signal source. +// Key The key's character code that was pressed. +// RETURN VALUE: None. +// DESCRIPTION: Called when a key is pressed. +// +//*************************************************************************************** +procedure TXcpSettingsForm.edtTransmitIdKeyPress(Sender: TObject; var Key: Char); +begin + ValidateHexCanIdInputPress(edtTransmitId, Key); +end; //*** end of edtTransmitIdKeyPress *** + + //*************************************************************************************** // NAME: btnOKClick // PARAMETER: none @@ -196,6 +385,7 @@ end; //*** end of Destroy *** function TXcpSettings.Configure : Boolean; var settingsIni: TIniFile; + settingsInt: Integer; begin // initialize the return value result := false; @@ -207,9 +397,22 @@ begin settingsIni := TIniFile.Create(FIniFile); // CAN related elements - FSettingsForm.cmbHardware.ItemIndex := settingsIni.ReadInteger('can', 'hardware', 0); - FSettingsForm.cmbChannel.ItemIndex := settingsIni.ReadInteger('can', 'channel', 0); - FSettingsForm.edtBaudRate.Text := IntToStr(settingsIni.ReadInteger('can', 'baudrate', 500)); + settingsInt := settingsIni.ReadInteger('can', 'hardware', 0); + if settingsInt > FSettingsForm.cmbHardware.Items.Count then + settingsInt := 0; + FSettingsForm.cmbHardware.ItemIndex := settingsInt; + FSettingsForm.SetAvailableChannels; + + settingsInt := settingsIni.ReadInteger('can', 'channel', 0); + if settingsInt >= FSettingsForm.cmbChannel.Items.Count then + settingsInt := 0; + FSettingsForm.cmbChannel.ItemIndex := settingsInt; + + settingsInt := settingsIni.ReadInteger('can', 'baudrate', 2); + if settingsInt >= FSettingsForm.cmbBaudrate.Items.Count then + settingsInt := 2; + FSettingsForm.cmbBaudrate.ItemIndex := settingsInt; + FSettingsForm.chbExtendedId.Checked := settingsIni.ReadBool('can', 'extended', false); FSettingsForm.edtTransmitId.Text := Format('%x',[settingsIni.ReadInteger('can', 'txid', $667)]); FSettingsForm.edtReceiveId.Text := Format('%x',[settingsIni.ReadInteger('can', 'rxid', $7e1)]); @@ -231,8 +434,9 @@ begin // set defaults // CAN related elements FSettingsForm.cmbHardware.ItemIndex := 0; + FSettingsForm.SetAvailableChannels; FSettingsForm.cmbChannel.ItemIndex := 0; - FSettingsForm.edtBaudRate.Text := IntToStr(500); + FSettingsForm.cmbBaudrate.ItemIndex := 2; FSettingsForm.chbExtendedId.Checked := false; FSettingsForm.edtTransmitId.Text := Format('%x',[$667]); FSettingsForm.edtReceiveId.Text := Format('%x',[$7e1]); @@ -258,7 +462,7 @@ begin // CAN related elements settingsIni.WriteInteger('can', 'hardware', FSettingsForm.cmbHardware.ItemIndex); settingsIni.WriteInteger('can', 'channel', FSettingsForm.cmbChannel.ItemIndex); - settingsIni.WriteInteger('can', 'baudrate', StrToInt(FSettingsForm.edtBaudRate.Text)); + settingsIni.WriteInteger('can', 'baudrate', FSettingsForm.cmbBaudrate.ItemIndex); settingsIni.WriteBool('can', 'extended', FSettingsForm.chbExtendedId.Checked); settingsIni.WriteInteger('can', 'txid', StrToInt('$'+FSettingsForm.edtTransmitId.Text)); settingsIni.WriteInteger('can', 'rxid', StrToInt('$'+FSettingsForm.edtReceiveId.Text)); diff --git a/Host/Source/MicroBoot/interfaces/can/peak/XcpTransport.pas b/Host/Source/MicroBoot/interfaces/can/peak/XcpTransport.pas index 020666f4..ef4183df 100644 --- a/Host/Source/MicroBoot/interfaces/can/peak/XcpTransport.pas +++ b/Host/Source/MicroBoot/interfaces/can/peak/XcpTransport.pas @@ -36,36 +36,35 @@ interface // Includes //*************************************************************************************** uses - Windows, Messages, SysUtils, Classes, Forms, IniFiles, PCANdrvD; + Windows, Messages, SysUtils, Classes, Forms, IniFiles, PCANBasic; //*************************************************************************************** // Global Constants //*************************************************************************************** -const kMaxPacketSize = 256; +// a CAN message can only have up to 8 bytes +const kMaxPacketSize = 8; //*************************************************************************************** // Type Definitions //*************************************************************************************** type - TXcpTransportInfo = (kNone, kResponse, kError); + TPCANhardware = ( PCAN_PCI = $40, PCAN_USB = $50, PCAN_PCC = $60 ); - -type TXcpTransport = class(TObject) private - comEventInfo : TXcpTransportInfo; - comEvent : THandle; packetTxId : LongWord; packetRxId : Longword; extendedId : Boolean; - procedure OnCanMessage(Sender: TObject; Direction: TPCanDirection; Message: TPCanMessage); - function MsgWaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD; + canHardware : TPCANhardware; { PCAN_xxx } + canChannel : Word; { currently supported is 1..8 } + canBaudrate : Word; { in bits/sec } + connected : Boolean; + function ConstructPeakHandle(hardware: TPCANhardware; channel: Word): TPCANHandle; public packetData : array[0..kMaxPacketSize-1] of Byte; packetLen : Word; - pcanDriver : TPCanDriver; constructor Create; procedure Configure(iniFile : string); function Connect: Boolean; @@ -90,22 +89,6 @@ begin // call inherited constructor inherited Create; - // reset can event info - comEventInfo := kNone; - - // create the event that requires manual reset - comEvent := CreateEvent(nil, True, False, nil); - - if comEvent = 0 then - Application.MessageBox( 'Could not obtain event placeholder.', - 'Error', MB_OK or MB_ICONERROR ); - - // create a pcan driver instance - pcanDriver := TPCanDriver.Create(nil); - - // set can driver event handlers - pcanDriver.OnMessage := OnCanMessage; - // reset the packet ids packetTxId := 0; packetRxId := 0; @@ -115,6 +98,9 @@ begin // reset packet length packetLen := 0; + + // disconnected by default + connected := false; end; //*** end of Create *** @@ -127,12 +113,6 @@ end; //*** end of Create *** //*************************************************************************************** destructor TXcpTransport.Destroy; begin - // release can driver instance - pcanDriver.Free; - - // release event handle - CloseHandle(comEvent); - // call inherited destructor inherited; end; //*** end of Destroy *** @@ -148,7 +128,6 @@ end; //*** end of Destroy *** procedure TXcpTransport.Configure(iniFile : string); var settingsIni : TIniFile; - hwIndex : integer; begin // read XCP configuration from INI if FileExists(iniFile) then @@ -156,24 +135,37 @@ begin // create ini file object settingsIni := TIniFile.Create(iniFile); + // set hardware configuration + case settingsIni.ReadInteger('can', 'hardware', 0) of + 0: canHardware := PCAN_USB; + 1: canHardware := PCAN_PCI; + 2: canHardware := PCAN_PCC; + else + canHardware := PCAN_USB; + end; + canChannel := settingsIni.ReadInteger('can', 'channel', 0) + 1; + + case settingsIni.ReadInteger('can', 'baudrate', 2) of + 0: canBaudrate := PCAN_BAUD_1M; + 1: canBaudrate := PCAN_BAUD_800K; + 2: canBaudrate := PCAN_BAUD_500K; + 3: canBaudrate := PCAN_BAUD_250K; + 4: canBaudrate := PCAN_BAUD_125K; + 5: canBaudrate := PCAN_BAUD_100K; + 6: canBaudrate := PCAN_BAUD_83K; + 7: canBaudrate := PCAN_BAUD_33K; + 8: canBaudrate := PCAN_BAUD_20K; + 9: canBaudrate := PCAN_BAUD_10K; + 10: canBaudrate := PCAN_BAUD_5K; + else + canBaudrate := PCAN_BAUD_500K; + end; + // set message configuration packetTxId := settingsIni.ReadInteger('can', 'txid', $667); packetRxId := settingsIni.ReadInteger('can', 'rxid', $7e1); extendedId := settingsIni.ReadBool('can', 'extended', false); - // configure can hardware - hwIndex := settingsIni.ReadInteger('can', 'hardware', 0); - pcanDriver.Hardware := PCAN_USB1CH; // init to PCAN_USB1CH - case hwIndex of - 0 : pcanDriver.Hardware := PCAN_USB1CH; - end; - - // configure baudrate - pcanDriver.BaudRate := settingsIni.ReadInteger('can', 'baudrate', 500) * 1000; - - // only 1 channel on PCAN USB 1CH - pcanDriver.Channel := pcanchannel0; - // release ini file object settingsIni.Free; end; @@ -188,10 +180,33 @@ end; //*** end of Configure *** // //*************************************************************************************** function TXcpTransport.Connect: Boolean; +var + status: TPCANStatus; + iBuffer : Integer; begin - result := true; - if not pcanDriver.Connect then - result := false; + // init result value + result := false; + + // disconnect first if still connected + if connected then + Disconnect; + + // attempt to connect to the CAN hardware interface + status := CAN_Initialize(ConstructPeakHandle(canHardware, canChannel), canBaudrate, 0, 0, 0); + + // process the result + if status = PCAN_ERROR_OK then + begin + // connected. now enable the bus off automatic reset + iBuffer := PCAN_PARAMETER_ON; + status := CAN_SetValue(ConstructPeakHandle(canHardware, canChannel), PCAN_BUSOFF_AUTORESET, + PLongWord(@iBuffer), sizeof(iBuffer)); + if status = PCAN_ERROR_OK then + begin + connected := true; + result := true; + end; + end; end; //*** end of Connect *** @@ -203,8 +218,21 @@ end; //*** end of Connect *** // //*************************************************************************************** function TXcpTransport.IsComError: Boolean; +var + status: TPCANStatus; begin - result := pcanDriver.IsComError; + // init result to no error. + result := false; + + // check for bus off error if connected + if connected then + begin + status := CAN_GetStatus(ConstructPeakHandle(canHardware, canChannel)); + if (status = PCAN_ERROR_BUSOFF) or (status = PCAN_ERROR_BUSHEAVY) then + begin + result := true; + end; + end; end; //*** end of IsComError *** @@ -218,57 +246,89 @@ end; //*** end of IsComError *** //*************************************************************************************** function TXcpTransport.SendPacket(timeOutms: LongWord): Boolean; var - pcanmsg : TPCanMessage; - cnt : byte; - waitResult: Integer; + txMsg: TPCANMsg; + rxMsg: TPCANMsg; + byteIdx: Byte; + status: TPCANStatus; + responseReceived: Boolean; + timeoutTime: DWORD; begin - // do not send any more data on the network when we are in bus off state. - if IsComError then + // initialize the result value + result := false; + + // do not send data when the packet length is invalid or when not connected + // to the CAN hardware + if (packetLen > kMaxPacketSize) or (not connected) then begin - result := false; Exit; end; - // prepare the packet - pcanmsg.id := LongInt(PacketTxId); - pcanmsg.dlc := packetLen; - pcanmsg.ext := extendedId; - for cnt := 0 to packetLen-1 do + // prepare the packet for transmission in a CAN message + txMsg.ID := packetTxId; + if extendedId then + txMsg.MSGTYPE := PCAN_MESSAGE_EXTENDED + else + txMsg.MSGTYPE := PCAN_MESSAGE_STANDARD; + txMsg.LEN := packetLen; + for byteIdx := 0 to (packetLen-1) do begin - pcanmsg.data[cnt] := packetData[cnt]; + txMsg.DATA[byteIdx] := packetData[byteIdx]; end; - // make sure the event is reset - ResetEvent(comEvent); - comEventInfo := kNone; - - // submit the packet transmission request - if not pcanDriver.Transmit(pcanmsg) then + // transmit the packet via CAN + status := CAN_Write(ConstructPeakHandle(canHardware, canChannel), txMsg); + if status <> PCAN_ERROR_OK then begin - // unable to submit tx request - result := False; Exit; + end; - // packet is being transmitted. Now wait for the response to come in - waitResult := MsgWaitForSingleObject(comEvent, timeOutms); + // reset flag and set the reception timeout time + responseReceived := false; + timeoutTime := GetTickCount + timeOutms; - if waitResult <> WAIT_OBJECT_0 then + // attempt to receive the packet response within the timeout time + repeat + // read out the next message in the receive queue + status := CAN_Read(ConstructPeakHandle(canHardware, canChannel), rxMsg, nil); + // check if an error occurred + if (status <> PCAN_ERROR_OK) and (status <> PCAN_ERROR_QRCVEMPTY) then + begin + // error detected. stop loop. + Break; + end + // no error occurred, so either a message was received or the queue was + // empty. check for the latter condition + else if status = PCAN_ERROR_OK then + begin + // was the newly received CAN message the response we are waiting for? + if rxMsg.ID = packetRxId then + begin + // was the id type also a match? + if ((rxMsg.MSGTYPE = PCAN_MESSAGE_STANDARD) and (not extendedId)) or + ((rxMsg.MSGTYPE = PCAN_MESSAGE_EXTENDED) and (extendedId)) then + begin + // response received. set flag + responseReceived := true; + end; + end; + end; + // give the application a chance to use the processor + Application.ProcessMessages; + until (GetTickCount > timeoutTime) or (responseReceived); + + // check if the response was correctly received + if responseReceived then begin - // no com event triggered so either a timeout or internal error occurred - result := False; - Exit; + // copy the response for futher processing + packetLen := rxMsg.LEN; + for byteIdx := 0 to (packetLen-1) do + begin + packetData[byteIdx] := rxMsg.DATA[byteIdx]; + end; + // success + result := true; end; - - // com event was triggered. now check if the reponse was correctly received - if comEventInfo <> kResponse then - begin - result := False; - Exit; - end; - - // packet successfully transmitted and response packet received - result := True; end; //*** end of SendPacket *** @@ -281,97 +341,28 @@ end; //*** end of SendPacket *** //*************************************************************************************** procedure TXcpTransport.Disconnect; begin - pcanDriver.Disconnect; + // disconnect CAN interface if connected + if connected then + begin + CAN_Uninitialize(ConstructPeakHandle(canHardware, canChannel)); + end; + connected := false; end; //*** end of Disconnect *** //*************************************************************************************** -// NAME: OnCanMessage -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Can message event handler +// NAME: ConstructPeakHandle +// PARAMETER: hardware Peak hardware identifier. +// channel Peak channel. +// RETURN VALUE: Peak hardware channel handle. +// DESCRIPTION: Converts this class' hardware and channel values into a handle that +// can be passed to the Peak API. // //*************************************************************************************** -procedure TXcpTransport.OnCanMessage(Sender: TObject; Direction: TPCanDirection; Message: TPCanMessage); -var - cnt : integer; +function TXcpTransport.ConstructPeakHandle(hardware: TPCANhardware; channel: Word): TPCANHandle; begin - // the event we are interested in is the reception of the command response from - // slave. - if Direction = PCanRx then - begin - if Message.id = LongInt(PacketRxId) then - begin - // store response data - for cnt := 0 to Message.dlc-1 do - begin - packetData[cnt] := Message.data[cnt]; - end; - - // store response length - packetLen := Message.dlc; - - // set event flag - comEventInfo := kResponse; - - // trigger the event - SetEvent(comEvent); - end; - end; -end; //*** end of OnCanMessage *** - - -//*************************************************************************************** -// NAME: MsgWaitForSingleObject -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Improved version of WaitForSingleObject. This version actually -// processes messages in the queue instead of blocking them. -// -//*************************************************************************************** -function TXcpTransport.MsgWaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD; -var - dwEnd:DWord; -begin - // compute the time when the WaitForSingleObject is supposed to time out - dwEnd := GetTickCount + dwMilliseconds; - - repeat - // wait for an event to happen or a message to be in the queue - result := MsgWaitForMultipleObjects(1, hHandle, False, dwMilliseconds, QS_ALLINPUT); - - // a message was in the queue? - if result = WAIT_OBJECT_0 + 1 then - begin - // process these messages - Application.ProcessMessages; - - // check for timeout manually because if a message in the queue occurred, the - // MsgWaitForMultipleObjects will be called again and the timer will start from - // scratch. we need to make sure the correct timeout time is used. - dwMilliseconds := GetTickCount; - if dwMilliseconds < dwEnd then - begin - dwMilliseconds := dwEnd - dwMilliseconds; - end - else - begin - // timeout occured - result := WAIT_TIMEOUT; - Break; - end; - end - else - // the event occured? - begin - // we can stop - Break; - end; - until True = False; -end; //*** end of MsgWaitForSingleObject *** - + result := Word(hardware) + channel; +end; //*** end of ConstructPeakHandle *** end. //******************************** end of XcpTransport.pas ****************************** diff --git a/Host/Source/MicroBoot/interfaces/can/peak/openblt_can_peak.cfg b/Host/Source/MicroBoot/interfaces/can/peak/openblt_can_peak.cfg deleted file mode 100644 index d2841ff5..00000000 --- a/Host/Source/MicroBoot/interfaces/can/peak/openblt_can_peak.cfg +++ /dev/null @@ -1,35 +0,0 @@ --$A+ --$B- --$C+ --$D+ --$E- --$F- --$G+ --$H+ --$I+ --$J+ --$K- --$L+ --$M- --$N+ --$O+ --$P+ --$Q- --$R- --$S- --$T- --$U- --$V+ --$W- --$X+ --$YD --$Z1 --cg --AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; --H+ --W+ --M --$M16384,1048576 --K$00400000 --E../../../../../ --LNc:\borland\delphi4\Lib diff --git a/Host/Source/MicroBoot/interfaces/can/peak/openblt_can_peak.dof b/Host/Source/MicroBoot/interfaces/can/peak/openblt_can_peak.dof deleted file mode 100644 index 12f6b2c7..00000000 --- a/Host/Source/MicroBoot/interfaces/can/peak/openblt_can_peak.dof +++ /dev/null @@ -1,88 +0,0 @@ -[Compiler] -A=1 -B=0 -C=1 -D=1 -E=0 -F=0 -G=1 -H=1 -I=1 -J=1 -K=0 -L=1 -M=0 -N=1 -O=1 -P=1 -Q=0 -R=0 -S=0 -T=0 -U=0 -V=1 -W=0 -X=1 -Y=1 -Z=1 -ShowHints=1 -ShowWarnings=1 -UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -[Linker] -MapFile=0 -OutputObjs=0 -ConsoleApp=1 -DebugInfo=0 -RemoteSymbols=0 -MinStackSize=16384 -MaxStackSize=1048576 -ImageBase=4194304 -ExeDescription= -[Directories] -OutputDir=../../../../../ -UnitOutputDir= -PackageDLLOutputDir= -PackageDCPOutputDir= -SearchPath= -Packages=Vcl40;Vclx40;Vcldb40;vcldbx40;VclSmp40;Qrpt40 -Conditionals= -DebugSourceDirs= -UsePackages=0 -[Parameters] -RunParams= -HostApplication= -[Version Info] -IncludeVerInfo=0 -AutoIncBuild=0 -MajorVer=1 -MinorVer=0 -Release=0 -Build=0 -Debug=0 -PreRelease=0 -Special=0 -Private=0 -DLL=0 -Locale=1031 -CodePage=1252 -[Version Info Keys] -CompanyName= -FileDescription= -FileVersion=1.0.0.0 -InternalName= -LegalCopyright= -LegalTrademarks= -OriginalFilename= -ProductName= -ProductVersion=1.0.0.0 -Comments= -[Excluded Packages] -$(DELPHI)\Lib\dclusr40.bpl=Borland User -[HistoryLists\hlUnitAliases] -Count=1 -Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -[HistoryLists\hlOutputDirectorry] -Count=3 -Item0=../../../../../ -Item1=../../../../ -Item2=../../../ diff --git a/Host/Source/MicroBoot/interfaces/can/peak/openblt_can_peak.dpr b/Host/Source/MicroBoot/interfaces/can/peak/openblt_can_peak.dpr index 470531b8..aeb81d0f 100644 --- a/Host/Source/MicroBoot/interfaces/can/peak/openblt_can_peak.dpr +++ b/Host/Source/MicroBoot/interfaces/can/peak/openblt_can_peak.dpr @@ -51,9 +51,7 @@ uses XcpLoader in '..\..\XcpLoader.pas', XcpTransport in 'XcpTransport.pas', XcpSettings in 'XcpSettings.pas' {XcpSettingsForm}, - pcan_usb in 'Pcan_usb.pas', - PCANdrvD in 'PCANdrvD.pas'; - + PCANBasic in 'PCANBasic.pas'; //*************************************************************************************** // Global Constants @@ -225,7 +223,7 @@ begin end; // update the log - MbiCallbackOnLog(logStr); + MbiCallbackOnLog(ShortString(logStr)); // update loop variables len := len - currentWriteCnt; @@ -259,25 +257,25 @@ begin // connect the transport layer MbiCallbackOnInfo('Connecting to the CAN interface.'); - MbiCallbackOnLog('Connecting to the CAN interface. t='+TimeToStr(Time)); + MbiCallbackOnLog('Connecting to the CAN interface. t='+ShortString(TimeToStr(Time))); Application.ProcessMessages; if not loader.Connect then begin // update the user info MbiCallbackOnError('Could not connect to CAN interface. Check your configuration.'); - MbiCallbackOnLog('Could not connect to CAN interface. Check your configuration and try again. t='+TimeToStr(Time)); + MbiCallbackOnLog('Could not connect to CAN interface. Check your configuration and try again. t='+ShortString(TimeToStr(Time))); Exit; end; //---------------- start the programming session -------------------------------------- - MbiCallbackOnLog('Starting the programming session. t='+TimeToStr(Time)); + MbiCallbackOnLog('Starting the programming session. t='+ShortString(TimeToStr(Time))); // try initial connect via XCP. if the user program is able to reactivate the bootloader // it will do so now sessionStartResult := loader.StartProgrammingSession; if sessionStartResult = kProgSessionUnlockError then begin - MbiCallbackOnLog('Security issue. Could not unprotect the programming resource. Check your configured XCP protection DLL. t='+TimeToStr(Time)); + MbiCallbackOnLog('Security issue. Could not unprotect the programming resource. Check your configured XCP protection DLL. t='+ShortString(TimeToStr(Time))); MbiCallbackOnError('Security issue. Could not unprotect the programming resource.'); loader.Disconnect; Exit; @@ -287,11 +285,11 @@ begin begin // update the user info MbiCallbackOnInfo('Could not connect. Retrying. Reset your target if this takes a long time.'); - MbiCallbackOnLog('Connect failed. Switching to backdoor entry mode. t='+TimeToStr(Time)); + MbiCallbackOnLog('Connect failed. Switching to backdoor entry mode. t='+ShortString(TimeToStr(Time))); Application.ProcessMessages; // possible that the bootloader is being activated, which means that the target's // CAN controller is being reinitialized. We should not send any data on the CAN - // network for this to finish. 200ms should do it. not that the backdoor entry time + // network for this to finish. 200ms should do it. note that the backdoor entry time // should be at least 2.5x this. Sleep(200); // continuously try to connect via XCP true the backdoor @@ -301,17 +299,17 @@ begin sessionStartResult := loader.StartProgrammingSession; Application.ProcessMessages; Sleep(5); - // if the is in reset of otherwise does not have the CAN controller synchronized to + // if the hardware is in reset or otherwise does not have the CAN controller synchronized to // the CAN bus, we will be generating error frames, possibly leading to a bus off. // check for this if loader.IsComError then begin // bus off state, so try to recover. - MbiCallbackOnLog('Communication error detected. Trying automatic recovery. t='+TimeToStr(Time)); + MbiCallbackOnLog('Communication error detected. Trying automatic recovery. t='+ShortString(TimeToStr(Time))); loader.Disconnect; if not loader.Connect then begin - MbiCallbackOnLog('Could not connect to CAN interface. Check your configuration and try again. t='+TimeToStr(Time)); + MbiCallbackOnLog('Could not connect to CAN interface. Check your configuration and try again. t='+ShortString(TimeToStr(Time))); MbiCallbackOnError('Could not connect to CAN interface. Check your configuration.'); Exit; end; @@ -320,7 +318,7 @@ begin // don't retry if the error was caused by not being able to unprotect the programming resource if sessionStartResult = kProgSessionUnlockError then begin - MbiCallbackOnLog('Security issue. Could not unprotect the programming resource. Check your configured XCP protection DLL. t='+TimeToStr(Time)); + MbiCallbackOnLog('Security issue. Could not unprotect the programming resource. Check your configured XCP protection DLL. t='+ShortString(TimeToStr(Time))); MbiCallbackOnError('Security issue. Could not unprotect the programming resource.'); Exit; end; @@ -335,7 +333,7 @@ begin end; // still here so programming session was started - MbiCallbackOnLog('Programming session started. t='+TimeToStr(Time)); + MbiCallbackOnLog('Programming session started. t='+ShortString(TimeToStr(Time))); // create the datafile object datafile := TXcpDataFile.Create(progfile); @@ -361,16 +359,16 @@ begin datafile.GetRegionInfo(regionCnt, addr, len); // erase the memory - MbiCallbackOnLog('Clearing Memory '+Format('addr:0x%x,len:0x%x',[addr,len])+'. t='+TimeToStr(Time)); + MbiCallbackOnLog('Clearing Memory '+ShortString(Format('addr:0x%x,len:0x%x',[addr,len]))+'. t='+ShortString(TimeToStr(Time))); if not loader.ClearMemory(addr, len) then begin loader.GetLastError(errorInfo); - MbiCallbackOnLog('Could not clear memory ('+errorInfo+'). t='+TimeToStr(Time)); - MbiCallbackOnError('Could not clear memory ('+errorInfo+').'); + MbiCallbackOnLog('Could not clear memory ('+ShortString(errorInfo)+'). t='+ShortString(TimeToStr(Time))); + MbiCallbackOnError('Could not clear memory ('+ShortString(errorInfo)+').'); datafile.Free; Exit; end; - MbiCallbackOnLog('Memory cleared. t='+TimeToStr(Time)); + MbiCallbackOnLog('Memory cleared. t='+ShortString(TimeToStr(Time))); end; //---------------- next program the memory regions ------------------------------------ @@ -394,18 +392,18 @@ begin if currentWriteCnt = 0 then currentWriteCnt := kMaxProgLen; // program the data - MbiCallbackOnLog('Programming Data '+Format('addr:0x%x,len:0x%x',[addr,currentWriteCnt])+'. t='+TimeToStr(Time)); + MbiCallbackOnLog('Programming Data '+ShortString(Format('addr:0x%x,len:0x%x',[addr,currentWriteCnt]))+'. t='+ShortString(TimeToStr(Time))); LogData(@progdata[bufferOffset], currentWriteCnt); if not loader.WriteData(addr, currentWriteCnt, @progdata[bufferOffset]) then begin loader.GetLastError(errorInfo); - MbiCallbackOnLog('Could not program data ('+errorInfo+'). t='+TimeToStr(Time)); - MbiCallbackOnError('Could not program data ('+errorInfo+').'); + MbiCallbackOnLog('Could not program data ('+ShortString(errorInfo)+'). t='+ShortString(TimeToStr(Time))); + MbiCallbackOnError('Could not program data ('+ShortString(errorInfo)+').'); datafile.Free; Exit; end; - MbiCallbackOnLog('Data Programmed. t='+TimeToStr(Time)); + MbiCallbackOnLog('Data Programmed. t='+ShortString(TimeToStr(Time))); // update progress progress := progress + currentWriteCnt; @@ -417,28 +415,28 @@ begin bufferOffset := bufferOffset + currentWriteCnt; // update the user info - MbiCallbackOnInfo('Programming data... ' + Format('(%.1n of %.1n Kbytes)',[(progress/1024), dataSizeKB])); + MbiCallbackOnInfo('Programming data... ' + ShortString(Format('(%.1n of %.1n Kbytes)',[(progress/1024), dataSizeKB]))); end; end; //---------------- stop the programming session --------------------------------------- - MbiCallbackOnLog('Stopping the programming session. t='+TimeToStr(Time)); + MbiCallbackOnLog('Stopping the programming session. t='+ShortString(TimeToStr(Time))); if not loader.StopProgrammingSession then begin loader.GetLastError(errorInfo); - MbiCallbackOnLog('Could not stop the programming session ('+errorInfo+'). t='+TimeToStr(Time)); - MbiCallbackOnError('Could not stop the programming session ('+errorInfo+').'); + MbiCallbackOnLog('Could not stop the programming session ('+ShortString(errorInfo)+'). t='+ShortString(TimeToStr(Time))); + MbiCallbackOnError('Could not stop the programming session ('+ShortString(errorInfo)+').'); datafile.Free; Exit; end; - MbiCallbackOnLog('Programming session stopped. t='+TimeToStr(Time)); + MbiCallbackOnLog('Programming session stopped. t='+ShortString(TimeToStr(Time))); // all done so set progress to 100% and finish up progress := datafile.GetDataCnt; datafile.Free; MbiCallbackOnProgress(progress); - MbiCallbackOnLog('File successfully downloaded t='+TimeToStr(Time)); + MbiCallbackOnLog('File successfully downloaded t='+ShortString(TimeToStr(Time))); MbiCallbackOnDone; end; //*** end of OnTimeout *** @@ -502,7 +500,7 @@ begin timer.Enabled := True; // store the program's filename - progfile := fileName; + progfile := String(fileName); end; //*** end of MbiStart *** @@ -520,7 +518,7 @@ begin stopRequest := true; // disconnect the transport layer - MbiCallbackOnLog('Disconnecting the transport layer. t='+TimeToStr(Time)); + MbiCallbackOnLog('Disconnecting the transport layer. t='+ShortString(TimeToStr(Time))); loader.Disconnect; end; //*** end of MbiStop *** @@ -639,15 +637,15 @@ end; //*** end of MbiConfigure *** //*************************************************************************************** exports //--- begin of don't change --- - MbiInit index 1, - MbiStart index 2, - MbiStop index 3, - MbiDeInit index 4, - MbiName index 5, - MbiDescription index 6, - MbiVersion index 7, - MbiConfigure index 8, - MbiVInterface index 9; + MbiInit, + MbiStart, + MbiStop, + MbiDeInit, + MbiName, + MbiDescription, + MbiVersion, + MbiConfigure, + MbiVInterface; //--- end of don't change --- end. diff --git a/Host/Source/MicroBoot/interfaces/can/peak/openblt_can_peak.dproj b/Host/Source/MicroBoot/interfaces/can/peak/openblt_can_peak.dproj new file mode 100644 index 00000000..484f6e54 --- /dev/null +++ b/Host/Source/MicroBoot/interfaces/can/peak/openblt_can_peak.dproj @@ -0,0 +1,120 @@ + + + {C587575B-3E1C-4EA4-BB4F-912B83127DCE} + openblt_can_peak.dpr + True + Debug + 1 + Library + VCL + 18.1 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + true + ../../../../../ + openblt_can_peak + 1 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace) + 00400000 + 1 + false + false + false + true + Vcl40;Vclx40;Vcldb40;vcldbx40;VclSmp40;Qrpt40;$(DCC_UsePackage) + true + 1031 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= + 1 + false + + + System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + true + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + true + DEBUG;$(DCC_Define) + false + + + C:\Work\software\OpenBLT\Host\MicroBoot.exe + true + (None) + 1033 + + + + MainSource + + + + + + + +
XcpSettingsForm
+
+ + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + +
+ + Delphi.Personality.12 + + + + + openblt_can_peak.dpr + + + + True + + + 12 + + + +
diff --git a/Host/Source/MicroBoot/interfaces/can/vector/CANIcon.bmp b/Host/Source/MicroBoot/interfaces/can/vector/CANIcon.bmp deleted file mode 100644 index 6ca58cdf..00000000 Binary files a/Host/Source/MicroBoot/interfaces/can/vector/CANIcon.bmp and /dev/null differ diff --git a/Host/Source/MicroBoot/interfaces/can/vector/CANdrvD.pas b/Host/Source/MicroBoot/interfaces/can/vector/CANdrvD.pas deleted file mode 100644 index 9e508c30..00000000 --- a/Host/Source/MicroBoot/interfaces/can/vector/CANdrvD.pas +++ /dev/null @@ -1,754 +0,0 @@ -unit CANdrvD; -//*************************************************************************************** -// Project Name: TCanDriver component for Borland Delphi -// Description: Encapsulates Vector's CANlib v4.3 into a VCL component -// File Name: CANdrvD.pas -// -//--------------------------------------------------------------------------------------- -// C O P Y R I G H T -//--------------------------------------------------------------------------------------- -// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved -// -// This software has been carefully tested, but is not guaranteed for any particular -// purpose. The author does not offer any warranties and does not guarantee the accuracy, -// adequacy, or completeness of the software and is not responsible for any errors or -// omissions or the results obtained from use of the software. -// -//--------------------------------------------------------------------------------------- -// L I C E N S E -//--------------------------------------------------------------------------------------- -// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or -// modify it under the terms of the GNU General Public License as published by the Free -// Software Foundation, either version 3 of the License, or (at your option) any later -// version. -// -// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -// PURPOSE. See the GNU General Public License for more details. -// -// You have received a copy of the GNU General Public License along with OpenBLT. It -// should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy. -// -//*************************************************************************************** -interface - - -//*************************************************************************************** -// Includes -//*************************************************************************************** -uses - Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, CANlibD; - - -//*************************************************************************************** -// Type Definitions -//*************************************************************************************** -type - TChannel = ( channel0, channel1 ); - THardware = ( Virtual, CANcardX, CANcardXL, CANcaseXL, CANboardXL, - CANboardXL_Compact, CANac2, CANac2Pci, CANpari, CANdongle, - CANcard, CANcardY, CANcard2, EDICcard ); - TDirection = ( Tx, Rx ); - TCanMsg = packed record - id : LongInt; - dlc : Byte; - data : array [0..MAX_MSG_LEN-1] of Byte; - time : LongInt; - ext : Boolean; - end; - -type - TMessageEvent = procedure( Sender: TObject; Direction: TDirection; Message: TCanMsg ) of object; - TErrorFrameEvent = procedure( Sender: TObject; time: LongInt ) of object; - TBusOffEvent = procedure( Sender: TObject; time: LongInt ) of object; - -type - TCanEventThread = class(TThread) - private - { Private declarations } - FMethod: TThreadMethod; - protected - FEventHndl: LongInt; - procedure Execute; override; - public - property Method : TThreadMethod read FMethod write FMethod; - property EventHandle: LongInt read FEventHndl write FEventHndl; - end; - -type - TCanDriver = class(TComponent) - private - { Private declarations } - FPortHandle : VPortHandle; - FChannelMask : Vaccess; - FPermissionMask: Vaccess; - FCanEventThread: TCanEventThread; - FThreadRunning : boolean; - FEventHandle : LongInt; - FBusOffPending : Boolean; - function IsThreadRunning: boolean; - procedure ProcessEvents; - procedure CopyMessage(event: Vevent; var msg: TCanMsg); - protected - { Protected declarations } - FBaudRate : LongInt; - FChannel : TChannel; - FHardware : THardware; - FFilterMask : LongInt; - FFilterCode : LongInt; - FPriority : TThreadPriority; - FExtendedId : Boolean; - FOnMessage : TMessageEvent; - FOnErrorFrame: TErrorFrameEvent; - FOnBusOff : TBusOffEvent; - procedure SetBaudRate( Value: LongInt ); - procedure SetChannel( Value: TChannel ); - procedure SetHardware( Value: THardware ); - procedure SetFilterMask( Value: LongInt ); - procedure SetFilterCode( Value: LongInt ); - procedure SetPriority( Value: TThreadPriority ); - procedure SetExtendedId( Value: Boolean ); - public - { Public declarations } - constructor Create( AOwner: TComponent ); override; - destructor Destroy; override; - function Connect: boolean; virtual; - procedure Disconnect; virtual; - function Transmit( Message: TCanMsg): boolean; virtual; - function IsConnected: boolean; virtual; - function IsComError: boolean; virtual; - published - { Published declarations } - property BaudRate : LongInt read FBaudRate write SetBaudRate default 500000; - property Channel : TChannel read FChannel write SetChannel default channel0; - property Hardware : THardware read FHardware write SetHardware default Virtual; - property FilterMask : LongInt read FFilterMask write SetFilterMask default 0; - property FilterCode : LongInt read FFilterCode write SetFilterCode default 0; - property Priority : TThreadPriority read FPriority write SetPriority default tpNormal; - property ExtendedId : Boolean read FExtendedId write SetExtendedId default False; - property OnMessage : TMessageEvent read FOnMessage write FOnMessage; - property OnErrorFrame: TErrorFrameEvent read FOnErrorFrame write FOnErrorFrame; - property OnBusOff : TBusOffEvent read FOnBusOff write FOnBusOff; - end; - - -//*************************************************************************************** -// Prototypes -//*************************************************************************************** -procedure Register; - -implementation -//*************************************************************************************** -// Constants -//*************************************************************************************** -const - Channels: array[channel0..channel1] of integer = ( 0, 1 ); - HardwareTypes: array[Virtual..EDICcard] of integer = ( - HWTYPE_VIRTUAL, HWTYPE_CANCARDX, HWTYPE_CANCARDXL, HWTYPE_CANCASEXL, HWTYPE_CANBOARDXL, - HWTYPE_CANBOARDXL_COMPACT, HWTYPE_CANAC2, HWTYPE_CANAC2PCI, HWTYPE_CANPARI, - HWTYPE_CANDONGLE, HWTYPE_CANCARD, HWTYPE_CANCARDY, HWTYPE_CANCARD2, HWTYPE_EDICCARD); - - -//*************************************************************************************** -// NAME: Execute -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Overriden Execute function for the CanEventThread. Calls and synchro- -// nizes with the TCanDriver.ProcessEvents function. -// -//*************************************************************************************** -procedure TCanEventThread.Execute; -begin - while not Terminated do - begin - if FEventHndl <> 0 then // make sure event is configured - begin - // wait for receive event - WaitForSingleObject(FEventHndl, 1000); - - if Assigned(Method) then // make sure TCanDriver.ProcessEvents is set - Synchronize(Method); // call and synchronize - end; - end; -end; //*** end of Execute *** - - -//*************************************************************************************** -// NAME: Create -// PRECONDITIONS: none -// PARAMETER: AOwner : owner of the component -// RETURN VALUE: none -// DESCRIPTION: Component constructor. Calls TComponent's constructor and initializes -// the private property variables to their default values. -// -//*************************************************************************************** -constructor TCanDriver.Create( AOwner: TComponent ); -begin - // call inherited constructor - inherited Create( AOwner ); - - // set defaults for internal variables - FPortHandle := INVALID_PORTHANDLE; - FChannelMask := 0; - FPermissionMask:= 0; - FThreadRunning := False; - FEventHandle := 0; - FBusOffPending := False; - - // set defaults for properties - FBaudRate := 500000; - FChannel := channel0; - FHardware := Virtual; - FFilterMask := 0; - FFilterCode := 0; - FPriority := tpNormal; - FExtendedId := False; -end; //*** end of Create *** - - -//*************************************************************************************** -// NAME: Destroy -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Component destructor. Calls TComponent's destructor -// -//*************************************************************************************** -destructor TCanDriver.Destroy; -begin - Disconnect; // close the port and driver - inherited Destroy; // call inherited destructor -end; //*** end of Destroy *** - - -//*************************************************************************************** -// NAME: IsConnected -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: True or False -// DESCRIPTION: Determines whether or not the CAN driver is connected and active -// -//*************************************************************************************** -function TCanDriver.IsConnected: boolean; -begin - if FPortHandle <> INVALID_PORTHANDLE then - Result := True - else - Result := False; -end; //*** end of IsConnected *** - - -//*************************************************************************************** -// NAME: IsComError -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: True if the communication interface is in error state, False otherwise -// DESCRIPTION: Determines whether or not the CAN controller is in error state. -// -//*************************************************************************************** -function TCanDriver.IsComError: boolean; -begin - result := FBusOffPending; -end; //*** end of IsComError *** - - -//*************************************************************************************** -// NAME: IsThreadRunning -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: True or False -// DESCRIPTION: Determines whether or not the CAN event thread is running -// -//*************************************************************************************** -function TCanDriver.IsThreadRunning: boolean; -begin - if FThreadRunning = True then - Result := True - else - Result := False; -end; //*** end of IsThreadRunning *** - - -//*************************************************************************************** -// NAME: CopyMessage -// PRECONDITIONS: none -// PARAMETER: event: msg tx or rx event information (source) -// msg: buffer to copy message to (destination) -// RETURN VALUE: none -// DESCRIPTION: Copies a CAN message from an event type to a TCanMsg type. -// -//*************************************************************************************** -procedure TCanDriver.CopyMessage(event: Vevent; var msg: TCanMsg); -var - cnt: integer; -begin - if (event.msg.id and EXT_MSG) = EXT_MSG then // 29-bit id? - begin - msg.id := (event.msg.id and not EXT_MSG); // reset ext bit - msg.ext := True; // this is an 29-bit id - end - else - begin - msg.id := event.msg.id; // store id - msg.ext := False; // this is an 11-bit id - end; - msg.dlc := event.msg.dlc; - msg.time := event.timeStamp; - - // copy the data bytes - for cnt :=0 to MAX_MSG_LEN-1 do - begin - if cnt < event.msg.dlc then - msg.data[cnt] := event.msg.data[cnt] - else - msg.data[cnt] := 0; - end; -end; //*** end of CopyMessage *** - - -//*************************************************************************************** -// NAME: SetBaudRate -// PRECONDITIONS: none -// PARAMETER: Value : new baudrate value [0 - 1000000 bps] -// RETURN VALUE: none -// DESCRIPTION: Configures the baudrate -// -// |------------------------------------------------------------------------------------ -// | Update baudrate configuration -// |------------------------------------------------------------------------------------ -//*************************************************************************************** -procedure TCanDriver.SetBaudRate( Value: LongInt ); -begin - FBaudRate := Value; // update property -end; //*** end of SetBaudRate *** - - -//*************************************************************************************** -// NAME: SetChannel -// PRECONDITIONS: none -// PARAMETER: Value : channel0 or channel1 -// RETURN VALUE: none -// DESCRIPTION: Configures the used CAN channel -// -// |------------------------------------------------------------------------------------ -// | Update channel configuration -// |------------------------------------------------------------------------------------ -//*************************************************************************************** -procedure TCanDriver.SetChannel( Value: TChannel ); -begin - FChannel := Value; -end; //*** end of SetChannel *** - - -//*************************************************************************************** -// NAME: SetHardware -// PRECONDITIONS: none -// PARAMETER: Value : type of CAN hardware (Virtual, CANcardXL, etc.) -// RETURN VALUE: none -// DESCRIPTION: Configures the used CAN hardware -// -// |------------------------------------------------------------------------------------ -// | Update hardware configuration -// |------------------------------------------------------------------------------------ -//*************************************************************************************** -procedure TCanDriver.SetHardware( Value: THardware ); -begin - FHardware := Value; -end; //*** end of SetHardware *** - - -//*************************************************************************************** -// NAME: SetFilterMask -// PRECONDITIONS: none -// PARAMETER: Value : acceptance filter mask -// RETURN VALUE: none -// DESCRIPTION: Configures the acceptance filter mask for the CAN channel -// -// |------------------------------------------------------------------------------------ -// | Update filter mask value -// |------------------------------------------------------------------------------------ -//*************************************************************************************** -procedure TCanDriver.SetFilterMask( Value: LongInt ); -begin - FFilterMask := Value; -end; //*** end of SetFilterMask *** - - -//*************************************************************************************** -// NAME: SetFilterCode -// PRECONDITIONS: none -// PARAMETER: Value : acceptance filter code -// RETURN VALUE: none -// DESCRIPTION: Configures the acceptance filter code for the CAN channel -// -// |------------------------------------------------------------------------------------ -// | Update filter code value -// |------------------------------------------------------------------------------------ -//*************************************************************************************** -procedure TCanDriver.SetFilterCode( Value: LongInt ); -begin - FFilterCode := Value; -end; //*** end of SetFilterCode *** - - -//*************************************************************************************** -// NAME: SetPriority -// PRECONDITIONS: none -// PARAMETER: Value : thread priority -// RETURN VALUE: none -// DESCRIPTION: Configures the priority for the CAN event thread -// -// |------------------------------------------------------------------------------------ -// | y\ Is Thread running? /n -// |------------------------------------------------------------------------------------ -// | Stop Thread | -// | Update Thread priority | Update Thread priority -// | Restart Thread | -// |------------------------------------------------------------------------------------ -//*************************************************************************************** -procedure TCanDriver.SetPriority( Value: TThreadPriority ); -begin - if IsThreadRunning then - begin - FCanEventThread.Suspend; // suspend the thread - FPriority := Value; // update the priority - FCanEventThread.Resume; // resume the thread - end - else - begin - FPriority := Value; // update the priority - end; -end; //*** end of SetPriority *** - - -//*************************************************************************************** -// NAME: SetExtendedId -// PRECONDITIONS: none -// PARAMETER: Value : true = support only 29-bit id's, false = support only 11-bit -// RETURN VALUE: none -// DESCRIPTION: Configures the support of extended 29-bit identifiers -// -// |------------------------------------------------------------------------------------ -// | Update extended id support selection -// |------------------------------------------------------------------------------------ -//*************************************************************************************** -procedure TCanDriver.SetExtendedId( Value: Boolean ); -begin - FExtendedId := Value; -end; //*** end of SetExtendedId ***/ - - -//*************************************************************************************** -// NAME: Connect -// PRECONDITIONS: Disconnected from CAN bus -// PARAMETER: none -// RETURN VALUE: True or False for succees or error, respectively -// DESCRIPTION: Initializes the CAN driver and synchronizes the hardware with the CAN -// bus. -// -// |------------------------------------------------------------------------------------ -// | y\ Connected? /n -// |------------------------------------------------------------------------------------ -// | Open the driver (ncdOpenDriver) -// | Obtain mask to channel (ncdGetChannelMask) -// | Open the port using this mask (ncdOpenPort) -// |------------------------------------------------------------------------------------ -// | y\ Permission to change settings? /n -// |------------------------------------------------------------------------------------ -// | Configure baudrate (ncdSetChannelBitrate) | -// |------------------------------------------------------------------------------------ -// | Configure acceptance filter (ncdSetChannelAcceptance) -// | Enable error frames and chipstate events (ncdSetReceiveMode) -// | Create synchronizatio object (ncdSetNotification) -// | Reset internal clock (ncdResetClock) -// | Sync to the CAN bus (ncdActivateChannel) -// | Empty transmit and receive queue's (ncdFlushXxxQueue) -// |------------------------------------------------------------------------------------ -// | y\ Errors occurred during init? /n -// |------------------------------------------------------------------------------------ -// | y\ Port opened? /n | -// |-------------------------------------------------------------| Start CAN event thread -// | Close port (ncdClosePort) | | Return TRUE -// |-------------------------------------------------------------| -// | Return FALSE | -// |------------------------------------------------------------------------------------ -//*************************************************************************************** -function TCanDriver.Connect: boolean; -var - vErr : Vstatus; - acc : VsetAcceptance; -label - error; -begin - // reset internal variables - FPortHandle := INVALID_PORTHANDLE; - FChannelMask := 0; - FPermissionMask:= 0; - FThreadRunning := False; - FEventHandle := 0; - FBusOffPending := False; - - //-------------------------- open the driver ------------------------------------------ - vErr := ncdOpenDriver; - if vErr <> VSUCCESS then goto error; - - //-------------------------- select a channel ----------------------------------------- - FChannelMask := ncdGetChannelMask(HardwareTypes[FHardware], 0, Channels[FChannel]); - if FChannelMask=0 then goto error; - - //-------------------------- open a port ---------------------------------------------- - FPermissionMask := FChannelMask; - vErr := ncdOpenPort(FPortHandle, 'TCanDriver0', FChannelMask, FPermissionMask, - FPermissionMask, 1024); - if vErr <> VSUCCESS then goto error; - - //-------------------------- set baudrate --------------------------------------------- - if FPermissionMask<>0 then - begin - vErr := ncdSetChannelBitrate(FPortHandle, FPermissionMask, FBaudRate); - if vErr <> VSUCCESS then goto error; - end; - - //-------------------------- set the acceptance filter -------------------------------- - acc.mask := FFilterMask; - acc.code := FFilterCode; - if FExtendedId = True then // 29-bit id used? - begin - acc.mask := acc.mask or LongInt(EXT_MSG); - acc.code := acc.code or LongInt(EXT_MSG); - end; - vErr := ncdSetChannelAcceptance(FPortHandle, FChannelMask, acc); - if vErr <> VSUCCESS then goto error; - - //-------------------------- enable error frames and chipstate events ----------------- - vErr := ncdSetReceiveMode(FPortHandle, 0, 0); - if vErr <> VSUCCESS then goto error; - - //-------------------------- create synchronisation object ---------------------------- - FEventHandle := CreateEvent(nil, FALSE, FALSE, nil); - if FEventHandle = 0 then goto error; - vErr := ncdSetNotification(FPortHandle, FEventHandle, 1); - if vErr<>VSUCCESS then goto error; - - //-------------------------- reset the clock ------------------------------------------ - vErr := ncdResetClock(FPortHandle); - if vErr <> VSUCCESS then goto error; - - //-------------------------- sync with bus -------------------------------------------- - vErr := ncdActivateChannel(FPortHandle, FChannelMask); - if vErr <> VSUCCESS then goto error; - - //-------------------------- flush queue's -------------------------------------------- - vErr := ncdFlushReceiveQueue(FPortHandle); - if vErr <> VSUCCESS then goto error; - vErr := ncdFlushTransmitQueue(FPortHandle, FChannelMask); - if vErr <> VSUCCESS then goto error; - - //-------------------------- start CAN event thread ----------------------------------- - FCanEventThread := TCanEventThread.Create(True); // create and suspend - FCanEventThread.FreeOnTerminate := True; // auto free on termination - FCanEventThread.Method := ProcessEvents; // set method - FCanEventThread.FEventHndl := FEventHandle; // set event handle - FCanEventThread.Resume; // start - FThreadRunning := True; - - //-------------------------- success -------------------------------------------------- - Result := True; // successfully initialized the driver - exit; // stop here - - //-------------------------- error occurred ------------------------------------------- - error: - if FEventHandle <> 0 then - CloseHandle(FEventHandle); - if FPortHandle <> INVALID_PORTHANDLE then - begin - ncdClosePort(FPortHandle); - FPortHandle := INVALID_PORTHANDLE; - end; - Result := False; -end; //*** end of Connect *** - - -//*************************************************************************************** -// NAME: Disconnect -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Disconnects the CAN driver -// -// |------------------------------------------------------------------------------------ -// | y\ Connected? /n -// |------------------------------------------------------------------------------------ -// | Deactivate the channel (ncdDeactivateChannel) | -// | Close port (ncdClosePort) | -// |------------------------------------------------------------------------------------ -// | Close the driver (ncdCloseDriver) -// |------------------------------------------------------------------------------------ -// | y\ CAN event thread active? /n -// |------------------------------------------------------------------------------------ -// | Stop CAN event thread | -// |------------------------------------------------------------------------------------ -//*************************************************************************************** -procedure TCanDriver.Disconnect; -begin - if IsConnected = True then begin // are we connected? - ncdDeactivateChannel(FPortHandle, FChannelMask); // deactivate channel - if FEventHandle <> 0 then - CloseHandle(FEventHandle); - ncdClosePort(FPortHandle); // close the port - FPortHandle := INVALID_PORTHANDLE; // invalidate handle - end; - ncdCloseDriver; // close the driver - if IsThreadRunning then - begin - FCanEventThread.FEventHndl := 0; // reset event handle - FCanEventThread.Terminate; // stop - FThreadRunning := False; - end; -end; //*** end of Disconnect *** - - -//*************************************************************************************** -// NAME: Transmit -// PRECONDITIONS: Driver initialized using 'Connect' -// PARAMETER: Message: CAN message that is to be transmitted -// RETURN VALUE: True or False for succees or error, respectively -// DESCRIPTION: Transmits a CAN message. -// -// |------------------------------------------------------------------------------------ -// | y\ Connected? /n -// |------------------------------------------------------------------------------------ -// | Transmit message using ncdTransmit | -// |----------------------------------------------| Return FALSE -// | Return TRUE | -// |------------------------------------------------------------------------------------ -//*************************************************************************************** -function TCanDriver.Transmit( Message: TCanMsg): boolean; -var - vErr : Vstatus; - event : Vevent; - cnt : integer; -begin - // make sure the CAN driver is connected - if not IsConnected then - begin - Result := False; // can't transmit it not connected - exit; // no need to continue - end; - - // configure message as tx with acknowledge - event.tag := V_TRANSMIT_MSG; - event.msg.flags := MSGFLAG_TX; - - // set the message identifier - if Message.ext = True then - event.msg.id := Message.id or LongInt(EXT_MSG) - else - event.msg.id := Message.id; - - // set the data length - event.msg.dlc := Message.dlc; - - // store the data bytes - for cnt :=0 to MAX_MSG_LEN-1 do - begin - event.msg.data[cnt] := Message.data[cnt]; - end; - - vErr := ncdTransmit(FPortHandle, FChannelMask, event); - - if vErr <> VSUCCESS then - Result := False - else - Result := True; -end; //*** end of Transmit *** - - -//*************************************************************************************** -// NAME: ProcessEvents -// PRECONDITIONS: thread running -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Called by the CAN event tread. This function traps and processes CAN -// events for OnMessage, OnBusOff, and OnErrorFrame. -// -//*************************************************************************************** -procedure TCanDriver.ProcessEvents; -var - vErr : Vstatus; - pEvent : PVEvent; - msg : TCanMsg; -begin - while True do - begin - vErr := ncdReceive1(FPortHandle, pEvent); - - if (vErr<>VSUCCESS) and (vErr<>VERR_QUEUE_IS_EMPTY) then break; - if vErr=VERR_QUEUE_IS_EMPTY then break; - - case pEvent^.tag of - V_RECEIVE_MSG, V_TRANSMIT_MSG: - begin - if (pEvent^.msg.flags and MSGFLAG_ERROR_FRAME) = MSGFLAG_ERROR_FRAME then - begin - //---------------- process errorframe ----------------------------------------- - if Assigned( FOnErrorFrame ) then - begin - FOnErrorFrame( Self, pEvent^.timeStamp ); // call application's event handler - end; - end - else if pEvent^.msg.flags = 0 then // msg rx indication - begin - //---------------- process reception indication ------------------------------- - CopyMessage(pEvent^, msg); - if Assigned( FOnMessage ) then - begin - FOnMessage( Self, Rx, msg ); // call application's event handler - end; - end - else if (pEvent^.msg.flags and MSGFLAG_TX) = MSGFLAG_TX then // msg tx confirmation - begin - //---------------- process transmission confirmation -------------------------- - CopyMessage(pEvent^, msg); - if Assigned( FOnMessage ) then - begin - FOnMessage( Self, Tx, msg ); // call application's event handler - end; - end; - end; - V_CHIP_STATE: - begin - if (pEvent^.chipState.busStatus and CHIPSTAT_BUSOFF) = CHIPSTAT_BUSOFF then - begin - //---------------- process bus off event -------------------------------------- - FBusOffPending := True; - if Assigned( FOnBusOff ) then - begin - FOnBusOff( Self, pEvent^.timeStamp ); // call application's event handler - end; - end; - end; - end; - end; -end; //*** end of ProcessEvents *** - - -//*************************************************************************************** -// NAME: Register -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Registers the TCanDriver component into Borland Delphi's IDE. -// -//*************************************************************************************** -procedure Register; -begin - RegisterComponents('Feaser', [TCanDriver]); -end; //*** end of Register *** - - -end. -//********************************** end of CANdrvD.pas ********************************* - - diff --git a/Host/Source/MicroBoot/interfaces/can/vector/CANlibD.pas b/Host/Source/MicroBoot/interfaces/can/vector/CANlibD.pas deleted file mode 100644 index e6e6a3af..00000000 --- a/Host/Source/MicroBoot/interfaces/can/vector/CANlibD.pas +++ /dev/null @@ -1,959 +0,0 @@ -unit CANlibD; - -(*---------------------------------------------------------------------------- -| File: -| CANlibD.pas -| Project: -| Unit for Delphi32 samples (V2.0) -| -|----------------------------------------------------------------------------- -| Ported from cantrace.c by Torsten Lang -|----------------------------------------------------------------------------- -| Copyright (c) 1998 BSK Datentechnik GmbH, Kiesacker 14, 35418 Buseck / -| 1998 by Vector Informatik GmbH, Friolzheimer Str. 6, 70499 Stuttgart -| All rights reserved. -| -| BSK Datentechnik räumt der Vector Informatik GmbH das nicht ausschließliche Recht -| ein, CANlibD.pas für eigene Zwecke zu nutzen. Vector ist es gestattet, die -| Software zu kopieren, abzuändern, zu erweitern, weiterzugeben und in Software von -| Vector zu integrieren. Im Quelltext enthaltene Copyright-Hinweise dürfen hierbei -| nicht entfernt oder geändert werden. -| Vector darf aus von ihm vorgenommenen Anpassungen und/oder Erweiterungen der -| CANlibD.pas keine Rechte an irgendwelchen Teilen der Software gegenüber BSK -| Datentechnik geltend machen. - ----------------------------------------------------------------------------*) - -{ environment switches } -(******************************************************************************* -Attention: -1. All functions that use pointers to structures (either explicitly or by using - var parameters) may change the contents of the structures right after the - funtction returns. -*******************************************************************************) -{$ifdef WIN32} -{$define CanLib4Delphi32} -{$else} -{$ifdef CONSOLE} -{$define CanLib4Delphi32} -{$endif} -{$endif} - -{ public interface } - -interface - -type - ncdStringType = PChar; - Vstatus = Word; - -const - MAX_APPNAME = 32; - - VCAN_WAIT = 0; - VCAN_POLL = 1; - {$ifdef CanLib4Delphi32} - { Attention: This exists only under Win32 } - VCAN_NOTIFY = 2; - {$endif} - - VSUCCESS = 0; - VPENDING = 1; - VERROR = 255; - VERR_QUEUE_IS_EMPTY = 10; - VERR_QUEUE_IS_FULL = 11; - VERR_TX_NOT_POSSIBLE = 12; - VERR_NO_LICENSE = 14; - VERR_WRONG_PARAMETER = 101; - VERR_TWICE_REGISTER = 110; - VERR_INVALID_CHAN_INDEX = 111; - VERR_INVALID_ACCESS = 112; - VERR_PORT_IS_OFFLINE = 113; - VERR_CHAN_IS_ONLINE = 116; - VERR_INVALID_PORT = 118; - VERR_HW_NOT_READY = 120; - VERR_CMD_TIMEOUT = 121; - VERR_HW_NOT_PRESENT = 129; - VERR_NOTIFY_ALREADY_ACTIVE = 131; - VERR_CANNOT_OPEN_DRIVER = 201; - -{ -//------------------------------------------------------------------------------ -// accessmask -} -type - Vaccess = LongInt; { unsigned long doesn't exist for Delphi32 / Borland Pascal 7! } - -{ -//------------------------------------------------------------------------------ -// porthandle -} - -const - INVALID_PORTHANDLE = -1; - -type - VportHandle = LongInt; - -{ -//------------------------------------------------------------------------------ -// acceptance filter -} - -type - VsetAcceptance = packed record - code : LongInt; {unsigned long doesn't exist!} - mask : LongInt; {unsigned long doesn't exist!} - end; - PVsetAcceptance = ^VsetAcceptance; - -{ -//------------------------------------------------------------------------------ -// bit timing -} - -type - VchipParams = packed record - bitRate : LongInt; {unsigned long doesn't exist!} - sjw : Byte; - tseg1 : Byte; - tseg2 : Byte; - sam : Byte; { 1 or 3 } - end; - PVchipParams = ^VchipParams; - -{ -//------------------------------------------------------------------------------ -// definitions for the events and commands used by the driver -} - -const - V_RECEIVE_MSG = 1; - V_CHIP_STATE = 4; - V_CLOCK_OVERFLOW = 5; - V_TRIGGER = 6; - V_TIMER = 8; - V_TRANSCEIVER = 9; - V_TRANSMIT_MSG = 10; - -type - VeventTag = Byte; - -{ -//------------------------------------------------------------------------------ -// events -} - -{ -//------------------------------------------------------------------------------ -// structure for V_RECEIVE_MSG -} - -const - MAX_MSG_LEN = 8; - EXT_MSG = $80000000; { signs an extended identifier } - - MSGFLAG_ERROR_FRAME = $01; { Msg is a bus error } - MSGFLAG_OVERRUN = $02; { Msgs following this has been lost } - MSGFLAG_NERR = $04; { NERR active during this msg } - MSGFLAG_WAKEUP = $08; { Msg rcv'd in wakeup mode } - MSGFLAG_REMOTE_FRAME = $10; { Msg is a remote frame } - MSGFLAG_RESERVED_1 = $20; { Reserved for future usage } - MSGFLAG_TX = $40; { TX acknowledge } - MSGFLAG_TXRQ = $80; { TX request } - -type - _Vmsg = packed record - id : LongInt; {unsigned long doesn't exist!} - flags : Byte; - dlc : Byte; - data : array [0..MAX_MSG_LEN-1] of Byte; - end; { 14 Bytes } - _PVmsg = ^_Vmsg; - -{ -// structure for V_CHIP_STATE -} - -const - CHIPSTAT_BUSOFF = $01; - CHIPSTAT_ERROR_PASSIVE = $02; - CHIPSTAT_ERROR_WARNING = $04; - CHIPSTAT_ERROR_ACTIVE = $08; - -type - _VchipState = packed record - busStatus : Byte; - txErrorCounter : Byte; - rxErrorCounter : Byte; - end; - _PVchipState = ^_VchipState; - -{ -// structure for V_TRANSCEIVER -} - -const - TRANSCEIVER_EVENT_ERROR = 1; - TRANSCEIVER_EVENT_CHANGED = 2; - - TRANSCEIVER_TYPE_NONE = 0; - TRANSCEIVER_TYPE_251 = 1; - TRANSCEIVER_TYPE_252 = 2; - TRANSCEIVER_TYPE_DNOPTO = 3; - TRANSCEIVER_TYPE_W210 = 4; - - TRANSCEIVER_LINEMODE_NA = 0; - TRANSCEIVER_LINEMODE_TWO_LINE = 1; - TRANSCEIVER_LINEMODE_CAN_H = 2; - TRANSCEIVER_LINEMODE_CAN_L = 3; - - TRANSCEIVER_RESNET_NA = 0; - TRANSCEIVER_RESNET_MASTER = 1; - TRANSCEIVER_RESNET_MASTER_STBY = 2; - TRANSCEIVER_RESNET_SLAVE = 3; - -type - _Vtransceiver = packed record - event : Byte; { TRANSCEIVER_EVENT_xxx } - end; - _PVtransceiver = ^_Vtransceiver; - - Vevent = packed record - tag : VeventTag; { 1 } - chanIndex : Byte; { 1 } - _transId : Byte; { 1 not implemented yet !!!! } - portHandle : Byte; { 1 internal use only !!!! } - timeStamp : LongInt; { 4 } { unsigned long doesn't exist! } - case {tagData:}Byte of - 0 : (msg : _Vmsg); - 1 : (chipState : _VchipState); - 2 : (transceiver : _Vtransceiver); - { 14 Bytes (_VMessage) } - end; - { -------- } - { 22 Bytes } - PVevent = ^Vevent; - -{ -//------------------------------------------------------------------------------ -// structure for SET_OUTPUT_MODE -} - -const - OUTPUT_MODE_SILENT = 0; - OUTPUT_MODE_NORMAL = 1; - -{ -//------------------------------------------------------------------------------ -// configuration -} - -{ -// defines for the supported hardware -} -const - HWTYPE_NONE = 0; - HWTYPE_VIRTUAL = 1; - HWTYPE_CANCARDX = 2; - HWTYPE_CANPARI = 3; - HWTYPE_CANDONGLE = 4; - HWTYPE_CANAC2 = 5; - HWTYPE_CANAC2PCI = 6; - HWTYPE_CANCARD = 7; - HWTYPE_CANCARDY = 12; - HWTYPE_CANCARDXL = 15; - HWTYPE_CANCARD2 = 17; - HWTYPE_EDICCARD = 19; - HWTYPE_CANCASEXL = 21; - HWTYPE_CANBOARDXL = 25; - HWTYPE_CANBOARDXL_COMPACT = 27; - MAX_HWTYPE = 27; - -{ -// defines for the tranceiver type -} -const - (* - TRANSCEIVER_TYPE_NONE = 0; - TRANSCEIVER_TYPE_251 = 1; - TRANSCEIVER_TYPE_252 = 2; - TRANSCEIVER_TYPE_DNOPTO = 3; - TRANSCEIVER_TYPE_W210 = 4; - *) { These have already been defined above } - MAX_TRANSCEIVER_TYPE = 4; - - MAX_CHAN_NAME = 31; - MAX_DRIVER_NAME = 31; - -type - VChannelConfig = packed record - name : array [0..MAX_CHAN_NAME] of Char; - hwType : Byte; { HWTYPE_xxxx (see above) } - hwIndex : Byte; { Index of the hardware (same type) (0,1,...) } - hwChannel : Byte; { Index of the channel (same hardware) (0,1,...) } - tranceiverType : Byte; { TRANCEIVER_TYPE_xxxx (see above) } - channelIndex : Byte; { Global channel index (0,1,...) } - channelMask : LongInt; { Global channel mask (=1< '' then - begin - // create ini file object - settingsIni := TIniFile.Create(FIniFile); - - // CAN related elements - settingsIni.WriteInteger('can', 'hardware', FSettingsForm.cmbHardware.ItemIndex); - settingsIni.WriteInteger('can', 'channel', FSettingsForm.cmbChannel.ItemIndex); - settingsIni.WriteInteger('can', 'baudrate', StrToInt(FSettingsForm.edtBaudRate.Text)); - settingsIni.WriteBool('can', 'extended', FSettingsForm.chbExtendedId.Checked); - settingsIni.WriteInteger('can', 'txid', StrToInt('$'+FSettingsForm.edtTransmitId.Text)); - settingsIni.WriteInteger('can', 'rxid', StrToInt('$'+FSettingsForm.edtReceiveId.Text)); - - // XCP related elements - settingsIni.WriteString('xcp', 'seedkey', FSettingsForm.edtSeedKey.Text); - settingsIni.WriteInteger('xcp', 't1', StrToInt(FSettingsForm.edtT1.Text)); - settingsIni.WriteInteger('xcp', 't3', StrToInt(FSettingsForm.edtT3.Text)); - settingsIni.WriteInteger('xcp', 't4', StrToInt(FSettingsForm.edtT4.Text)); - settingsIni.WriteInteger('xcp', 't5', StrToInt(FSettingsForm.edtT5.Text)); - settingsIni.WriteInteger('xcp', 't7', StrToInt(FSettingsForm.edtT7.Text)); - settingsIni.WriteInteger('xcp', 'tconnect', StrToInt(FSettingsForm.edtTconnect.Text)); - - // release ini file object - settingsIni.Free; - - // indicate that the settings where successfully updated - result := true; - end; - end; -end; //*** end of Configure *** - - -end. -//******************************** end of XcpSettings.pas ******************************* - - diff --git a/Host/Source/MicroBoot/interfaces/can/vector/XcpTransport.pas b/Host/Source/MicroBoot/interfaces/can/vector/XcpTransport.pas deleted file mode 100644 index e144075f..00000000 --- a/Host/Source/MicroBoot/interfaces/can/vector/XcpTransport.pas +++ /dev/null @@ -1,414 +0,0 @@ -unit XcpTransport; -//*************************************************************************************** -// Description: XCP transport layer for CAN. -// File Name: XcpTransport.pas -// -//--------------------------------------------------------------------------------------- -// C O P Y R I G H T -//--------------------------------------------------------------------------------------- -// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved -// -// This software has been carefully tested, but is not guaranteed for any particular -// purpose. The author does not offer any warranties and does not guarantee the accuracy, -// adequacy, or completeness of the software and is not responsible for any errors or -// omissions or the results obtained from use of the software. -// -//--------------------------------------------------------------------------------------- -// L I C E N S E -//--------------------------------------------------------------------------------------- -// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or -// modify it under the terms of the GNU General Public License as published by the Free -// Software Foundation, either version 3 of the License, or (at your option) any later -// version. -// -// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -// PURPOSE. See the GNU General Public License for more details. -// -// You have received a copy of the GNU General Public License along with OpenBLT. It -// should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy. -// -//*************************************************************************************** -interface - - -//*************************************************************************************** -// Includes -//*************************************************************************************** -uses - Windows, Messages, SysUtils, Classes, Forms, CANdrvD, IniFiles; - - -//*************************************************************************************** -// Global Constants -//*************************************************************************************** -const kMaxPacketSize = 256; - - -//*************************************************************************************** -// Type Definitions -//*************************************************************************************** -type - TXcpTransportInfo = (kNone, kResponse, kError); - - -type - TXcpTransport = class(TObject) - private - comEventInfo : TXcpTransportInfo; - comEvent : THandle; - packetTxId : LongWord; - packetRxId : Longword; - extendedId : Boolean; - procedure OnCanMessage(Sender: TObject; Direction: TDirection; Message: TCanMsg); - procedure OnBusOff(Sender: TObject; time: LongInt); - function MsgWaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD; - public - packetData : array[0..kMaxPacketSize-1] of Byte; - packetLen : Word; - canDriver : TCanDriver; - constructor Create; - procedure Configure(iniFile : string); - function Connect: Boolean; - function SendPacket(timeOutms: LongWord): Boolean; - function IsComError: Boolean; - procedure Disconnect; - destructor Destroy; override; - end; - - -implementation - -//*************************************************************************************** -// NAME: Create -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Class constructore -// -//*************************************************************************************** -constructor TXcpTransport.Create; -begin - // call inherited constructor - inherited Create; - - // reset can event info - comEventInfo := kNone; - - // create the event that requires manual reset - comEvent := CreateEvent(nil, True, False, nil); - - if comEvent = 0 then - Application.MessageBox( 'Could not obtain event placeholder.', - 'Error', MB_OK or MB_ICONERROR ); - - // create a can driver instance - canDriver := TCanDriver.Create(nil); - - // set can driver event handlers - canDriver.OnMessage := OnCanMessage; - canDriver.OnBusOff := OnBusOff; - - - // reset the packet ids - packetTxId := 0; - packetRxId := 0; - - // use standard id's by default - extendedId := false; - - // reset packet length - packetLen := 0; -end; //*** end of Create *** - - -//*************************************************************************************** -// NAME: Destroy -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Class destructor -// -//*************************************************************************************** -destructor TXcpTransport.Destroy; -begin - // release can driver instances - canDriver.Free; - - // release event handle - CloseHandle(comEvent); - - // call inherited destructor - inherited; -end; //*** end of Destroy *** - - -//*************************************************************************************** -// NAME: Configure -// PARAMETER: filename of the INI -// RETURN VALUE: none -// DESCRIPTION: Configures both this class from the settings in the INI. -// -//*************************************************************************************** -procedure TXcpTransport.Configure(iniFile : string); -var - settingsIni : TIniFile; - hwIndex : integer; -begin - // read XCP configuration from INI - if FileExists(iniFile) then - begin - // create ini file object - settingsIni := TIniFile.Create(iniFile); - - // set message configuration - packetTxId := settingsIni.ReadInteger('can', 'txid', $667); - packetRxId := settingsIni.ReadInteger('can', 'rxid', $7e1); - extendedId := settingsIni.ReadBool('can', 'extended', false); - - // configure can hardware - hwIndex := settingsIni.ReadInteger('can', 'hardware', 0); - canDriver.Hardware := Virtual; // init to virtual channel - case hwIndex of - 0 : canDriver.Hardware := Virtual; - 1 : canDriver.Hardware := CANcardX; - 2 : canDriver.Hardware := CANcardXL; - 3 : canDriver.Hardware := CANcaseXL; - 4 : canDriver.Hardware := CANboardXL; - 5 : canDriver.Hardware := CANboardXL_Compact; - 6 : canDriver.Hardware := CANac2; - 7 : canDriver.Hardware := CANac2Pci; - 8 : canDriver.Hardware := CANpari; - 9 : canDriver.Hardware := CANdongle; - 10: canDriver.Hardware := CANcard; - 11: canDriver.Hardware := CANcardY; - 12: canDriver.Hardware := CANcard2; - 13: canDriver.Hardware := EDICcard; - end; - - // configure baudrate - canDriver.BaudRate := settingsIni.ReadInteger('can', 'baudrate', 500) * 1000; - - if settingsIni.ReadInteger('can', 'channel', 0) = 0 then - canDriver.Channel := channel0 - else - canDriver.Channel := channel1; - - // release ini file object - settingsIni.Free; - end; -end; //*** end of Configure *** - - -//*************************************************************************************** -// NAME: Connect -// PARAMETER: none -// RETURN VALUE: True if successful, False otherwise. -// DESCRIPTION: Connects the transport layer device. -// -//*************************************************************************************** -function TXcpTransport.Connect: Boolean; -begin - result := true; - if not canDriver.Connect then - result := false; -end; //*** end of Connect *** - - -//*************************************************************************************** -// NAME: IsComError -// PARAMETER: none -// RETURN VALUE: True if in error state, False otherwise. -// DESCRIPTION: Determines if the communication interface is in an error state. -// -//*************************************************************************************** -function TXcpTransport.IsComError: Boolean; -begin - result := canDriver.IsComError; -end; //*** end of IsComError *** - - -//*************************************************************************************** -// NAME: SendPacket -// PARAMETER: the time[ms] allowed for the reponse from the slave to come in. -// RETURN VALUE: True if response received from slave, False otherwise -// DESCRIPTION: Sends the XCP packet using the data in 'packetData' and length in -// 'packetLen' and waits for the response to come in. -// -//*************************************************************************************** -function TXcpTransport.SendPacket(timeOutms: LongWord): Boolean; -var - msg: TCanMsg; - cnt : byte; - waitResult: Integer; -begin - // do not send any more data on the network when we are in bus off state. - if IsComError then - begin - result := false; - Exit; - end; - - // prepare the packet - msg.id := LongInt(PacketTxId); - msg.dlc := packetLen; - msg.ext := extendedId; - for cnt := 0 to packetLen-1 do - begin - msg.data[cnt] := packetData[cnt]; - end; - - // make sure the event is reset - ResetEvent(comEvent); - comEventInfo := kNone; - - // submit the packet transmission request - if not canDriver.Transmit(msg) then - begin - // unable to submit tx request - result := False; - Exit; - end; - - // packet is being transmitted. Now wait for the response to come in - waitResult := MsgWaitForSingleObject(comEvent, timeOutms); - - if waitResult <> WAIT_OBJECT_0 then - begin - // no com event triggered so either a timeout or internal error occurred - result := False; - Exit; - end; - - // com event was triggered. now check if the reponse was correctly received - if comEventInfo <> kResponse then - begin - result := False; - Exit; - end; - - // packet successfully transmitted and response packet received - result := True; -end; //*** end of SendPacket *** - - -//*************************************************************************************** -// NAME: Disconnect -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Disconnects the transport layer device. -// -//*************************************************************************************** -procedure TXcpTransport.Disconnect; -begin - canDriver.Disconnect; -end; //*** end of Disconnect *** - - -//*************************************************************************************** -// NAME: OnCanMessage -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Can message event handler -// -//*************************************************************************************** -procedure TXcpTransport.OnCanMessage( Sender: TObject; Direction: TDirection; Message: TCanMsg ); -var - cnt : integer; -begin - // the event we are interested in is the reception of the command response from - // slave. - if Direction = Rx then - begin - if Message.id = LongInt(PacketRxId) then - begin - // store response data - for cnt := 0 to Message.dlc-1 do - begin - packetData[cnt] := Message.data[cnt]; - end; - - // store response length - packetLen := Message.dlc; - - // set event flag - comEventInfo := kResponse; - - // trigger the event - SetEvent(comEvent); - end; - end; -end; //*** end of OnCanMessage *** - - -//*************************************************************************************** -// NAME: OnBusOff -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Bus off event handler -// -//*************************************************************************************** -procedure TXcpTransport.OnBusOff(Sender: TObject; time: LongInt); -begin - // set error event flag - comEventInfo := kError; - - // trigger the event - SetEvent(comEvent); -end; //*** end of OnBusOff *** - - -//*************************************************************************************** -// NAME: MsgWaitForSingleObject -// PRECONDITIONS: none -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Improved version of WaitForSingleObject. This version actually -// processes messages in the queue instead of blocking them. -// -//*************************************************************************************** -function TXcpTransport.MsgWaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD; -var - dwEnd:DWord; -begin - // compute the time when the WaitForSingleObject is supposed to time out - dwEnd := GetTickCount + dwMilliseconds; - - repeat - // wait for an event to happen or a message to be in the queue - result := MsgWaitForMultipleObjects(1, hHandle, False, dwMilliseconds, QS_ALLINPUT); - - // a message was in the queue? - if result = WAIT_OBJECT_0 + 1 then - begin - // process these messages - Application.ProcessMessages; - - // check for timeout manually because if a message in the queue occurred, the - // MsgWaitForMultipleObjects will be called again and the timer will start from - // scratch. we need to make sure the correct timeout time is used. - dwMilliseconds := GetTickCount; - if dwMilliseconds < dwEnd then - begin - dwMilliseconds := dwEnd - dwMilliseconds; - end - else - begin - // timeout occured - result := WAIT_TIMEOUT; - Break; - end; - end - else - // the event occured? - begin - // we can stop - Break; - end; - until True = False; -end; //*** end of MsgWaitForSingleObject *** - - -end. -//******************************** end of XcpTransport.pas ****************************** - diff --git a/Host/Source/MicroBoot/interfaces/can/vector/openblt_can_vector.cfg b/Host/Source/MicroBoot/interfaces/can/vector/openblt_can_vector.cfg deleted file mode 100644 index d2841ff5..00000000 --- a/Host/Source/MicroBoot/interfaces/can/vector/openblt_can_vector.cfg +++ /dev/null @@ -1,35 +0,0 @@ --$A+ --$B- --$C+ --$D+ --$E- --$F- --$G+ --$H+ --$I+ --$J+ --$K- --$L+ --$M- --$N+ --$O+ --$P+ --$Q- --$R- --$S- --$T- --$U- --$V+ --$W- --$X+ --$YD --$Z1 --cg --AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; --H+ --W+ --M --$M16384,1048576 --K$00400000 --E../../../../../ --LNc:\borland\delphi4\Lib diff --git a/Host/Source/MicroBoot/interfaces/can/vector/openblt_can_vector.dof b/Host/Source/MicroBoot/interfaces/can/vector/openblt_can_vector.dof deleted file mode 100644 index 564878ae..00000000 --- a/Host/Source/MicroBoot/interfaces/can/vector/openblt_can_vector.dof +++ /dev/null @@ -1,87 +0,0 @@ -[Compiler] -A=1 -B=0 -C=1 -D=1 -E=0 -F=0 -G=1 -H=1 -I=1 -J=1 -K=0 -L=1 -M=0 -N=1 -O=1 -P=1 -Q=0 -R=0 -S=0 -T=0 -U=0 -V=1 -W=0 -X=1 -Y=1 -Z=1 -ShowHints=1 -ShowWarnings=1 -UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -[Linker] -MapFile=0 -OutputObjs=0 -ConsoleApp=1 -DebugInfo=0 -RemoteSymbols=0 -MinStackSize=16384 -MaxStackSize=1048576 -ImageBase=4194304 -ExeDescription= -[Directories] -OutputDir=../../../../../ -UnitOutputDir= -PackageDLLOutputDir= -PackageDCPOutputDir= -SearchPath= -Packages=Vcl40;Vclx40;Vcldb40;vcldbx40;VclSmp40;Qrpt40 -Conditionals= -DebugSourceDirs= -UsePackages=0 -[Parameters] -RunParams= -HostApplication= -[Version Info] -IncludeVerInfo=0 -AutoIncBuild=0 -MajorVer=1 -MinorVer=0 -Release=0 -Build=0 -Debug=0 -PreRelease=0 -Special=0 -Private=0 -DLL=0 -Locale=1031 -CodePage=1252 -[Version Info Keys] -CompanyName= -FileDescription= -FileVersion=1.0.0.0 -InternalName= -LegalCopyright= -LegalTrademarks= -OriginalFilename= -ProductName= -ProductVersion=1.0.0.0 -Comments= -[Excluded Packages] -$(DELPHI)\Lib\dclusr40.bpl=Borland User -[HistoryLists\hlUnitAliases] -Count=1 -Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -[HistoryLists\hlOutputDirectorry] -Count=2 -Item0=../../../../../ -Item1=../../../../ diff --git a/Host/Source/MicroBoot/interfaces/can/vector/openblt_can_vector.dpr b/Host/Source/MicroBoot/interfaces/can/vector/openblt_can_vector.dpr deleted file mode 100644 index bbdc9133..00000000 --- a/Host/Source/MicroBoot/interfaces/can/vector/openblt_can_vector.dpr +++ /dev/null @@ -1,653 +0,0 @@ -library openblt_can_vector; -//*************************************************************************************** -// Project Name: MicroBoot Interface for Borland Delphi -// Description: XCP - CAN interface for MicroBoot supporting Vector CAN -// File Name: openblt_can_vector.dpr -// -//--------------------------------------------------------------------------------------- -// C O P Y R I G H T -//--------------------------------------------------------------------------------------- -// Copyright (c) 2011 by Feaser http://www.feaser.com All rights reserved -// -// This software has been carefully tested, but is not guaranteed for any particular -// purpose. The author does not offer any warranties and does not guarantee the accuracy, -// adequacy, or completeness of the software and is not responsible for any errors or -// omissions or the results obtained from use of the software. -// -//--------------------------------------------------------------------------------------- -// L I C E N S E -//--------------------------------------------------------------------------------------- -// This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or -// modify it under the terms of the GNU General Public License as published by the Free -// Software Foundation, either version 3 of the License, or (at your option) any later -// version. -// -// OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -// PURPOSE. See the GNU General Public License for more details. -// -// You have received a copy of the GNU General Public License along with OpenBLT. It -// should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy. -// -//*************************************************************************************** - - -//*************************************************************************************** -// Includes -//*************************************************************************************** -uses - Windows, - Messages, - Graphics, - Controls, - Forms, - Dialogs, - SysUtils, - Classes, - Extctrls, - XcpProtection in '..\..\XcpProtection.pas', - SRecReader in '..\..\SRecReader.pas', - XcpDataFile in '..\..\XcpDataFile.pas', - XcpLoader in '..\..\XcpLoader.pas', - XcpTransport in 'XcpTransport.pas', - CANdrvD in 'CANdrvD.pas', - CANlibD in 'CANlibD.pas', - XcpSettings in 'XcpSettings.pas' {XcpSettingsForm}; - - -//*************************************************************************************** -// Global Constants -//*************************************************************************************** -const kMaxProgLen = 256; // maximum number of bytes to progam at one time - - -//*************************************************************************************** -// Type Definitions -//*************************************************************************************** -// DLL Interface Callbacks - modifications requires potential update of all interfaces! -type - TStartedEvent = procedure(length: Longword) of object; - TProgressEvent = procedure(progress: Longword) of object; - TDoneEvent = procedure of object; - TErrorEvent = procedure(error: ShortString) of object; - TLogEvent = procedure(info: ShortString) of object; - TInfoEvent = procedure(info: ShortString) of object; - -type - TEventHandlers = class // create a dummy class - procedure OnTimeout(Sender: TObject); - end; - -//*************************************************************************************** -// Global Variables -//*************************************************************************************** -var - //--- begin of don't change --- - AppOnStarted : TStartedEvent; - AppOnProgress : TProgressEvent; - AppOnDone : TDoneEvent; - AppOnError : TErrorEvent; - AppOnLog : TLogEvent; - AppOnInfo : TInfoEvent; - //--- end of don't change --- - timer : TTimer; - events : TEventHandlers; - loader : TXcpLoader; - datafile : TXcpDataFile; - progdata : array of Byte; - progfile : string; - stopRequest : boolean; - - -//*************************************************************************************** -// NAME: MbiCallbackOnStarted -// PARAMETER: length of the file that is being downloaded. -// RETURN VALUE: none -// DESCRIPTION: Wrapper function for safely calling an application callback -// -//*************************************************************************************** -procedure MbiCallbackOnStarted(length: Longword); -begin - if Assigned(AppOnStarted) then - begin - AppOnStarted(length); - end; -end; //** end of MbiCallbackOnStarted *** - - -//*************************************************************************************** -// NAME: MbiCallbackOnProgress -// PARAMETER: progress of the file download. -// RETURN VALUE: none -// DESCRIPTION: Wrapper function for safely calling an application callback -// -//*************************************************************************************** -procedure MbiCallbackOnProgress(progress: Longword); -begin - if Assigned(AppOnProgress) then - begin - AppOnProgress(progress); - end; -end; //** end of MbiCallbackOnProgress *** - - -//*************************************************************************************** -// NAME: MbiCallbackOnDone -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Wrapper function for safely calling an application callback -// -//*************************************************************************************** -procedure MbiCallbackOnDone; -begin - if Assigned(AppOnDone) then - begin - AppOnDone; - end; -end; //** end of MbiCallbackOnDone *** - - -//*************************************************************************************** -// NAME: MbiCallbackOnError -// PARAMETER: info about the error that occured. -// RETURN VALUE: none -// DESCRIPTION: Wrapper function for safely calling an application callback -// -//*************************************************************************************** -procedure MbiCallbackOnError(error: ShortString); -begin - if Assigned(AppOnError) then - begin - AppOnError(error); - end; -end; //** end of MbiCallbackOnError *** - - -//*************************************************************************************** -// NAME: MbiCallbackOnLog -// PARAMETER: info on the log event. -// RETURN VALUE: none -// DESCRIPTION: Wrapper function for safely calling an application callback -// -//*************************************************************************************** -procedure MbiCallbackOnLog(info: ShortString); -begin - if Assigned(AppOnLog) then - begin - AppOnLog(info); - end; -end; //** end of MbiCallbackOnLog *** - - -//*************************************************************************************** -// NAME: MbiCallbackOnInfo -// PARAMETER: details on the info event. -// RETURN VALUE: none -// DESCRIPTION: Wrapper function for safely calling an application callback -// -//*************************************************************************************** -procedure MbiCallbackOnInfo(info: ShortString); -begin - if Assigned(AppOnInfo) then - begin - AppOnInfo(info); - end; -end; //** end of MbiCallbackOnLog *** - - -//*************************************************************************************** -// NAME: LogData -// PARAMETER: pointer to byte array and the data length -// RETURN VALUE: none -// DESCRIPTION: Writes the program data formatted to the logfile -// -//*************************************************************************************** -procedure LogData(data : PByteArray; len : longword); stdcall; -var - currentWriteCnt : byte; - cnt : byte; - logStr : string; - bufferOffset : longword; -begin - bufferOffset := 0; - - while len > 0 do - begin - // set the current write length optimized to log 32 bytes per line - currentWriteCnt := len mod 32; - if currentWriteCnt = 0 then currentWriteCnt := 32; - logStr := ''; - - // prepare the line to add to the log - for cnt := 0 to currentWriteCnt-1 do - begin - logStr := logStr + Format('%2.2x ', [data[bufferOffset+cnt]]); - end; - - // update the log - MbiCallbackOnLog(logStr); - - // update loop variables - len := len - currentWriteCnt; - bufferOffset := bufferOffset + currentWriteCnt; - end; -end; //*** end of LogData *** - - -//*************************************************************************************** -// NAME: OnTimeout -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Timer event handler. A timer is used in this example to simulate the -// progress of a file download. It also demonstrates how to use the -// application callbacks to keep the application informed. -// -//*************************************************************************************** -procedure TEventHandlers.OnTimeout(Sender: TObject); -var - errorInfo : string; - progress : longword; - regionCnt : longword; - currentWriteCnt : word; - sessionStartResult : byte; - bufferOffset : longword; - addr : longword; - len : longword; - dataSizeKB : real; -begin - timer.Enabled := False; - - // connect the transport layer - MbiCallbackOnInfo('Connecting to the CAN interface.'); - MbiCallbackOnLog('Connecting to the CAN interface. t='+TimeToStr(Time)); - Application.ProcessMessages; - if not loader.Connect then - begin - // update the user info - MbiCallbackOnError('Could not connect to CAN interface. Check your configuration.'); - MbiCallbackOnLog('Could not connect to CAN interface. Check your configuration and try again. t='+TimeToStr(Time)); - Exit; - end; - - //---------------- start the programming session -------------------------------------- - MbiCallbackOnLog('Starting the programming session. t='+TimeToStr(Time)); - - // try initial connect via XCP. if the user program is able to reactivate the bootloader - // it will do so now - sessionStartResult := loader.StartProgrammingSession; - if sessionStartResult = kProgSessionUnlockError then - begin - MbiCallbackOnLog('Security issue. Could not unprotect the programming resource. Check your configured XCP protection DLL. t='+TimeToStr(Time)); - MbiCallbackOnError('Security issue. Could not unprotect the programming resource.'); - loader.Disconnect; - Exit; - end; - // try initial connect via XCP - if sessionStartResult <> kProgSessionStarted then - begin - // update the user info - MbiCallbackOnInfo('Could not connect. Retrying. Reset your target if this takes a long time.'); - MbiCallbackOnLog('Connect failed. Switching to backdoor entry mode. t='+TimeToStr(Time)); - Application.ProcessMessages; - // possible that the bootloader is being activated, which means that the target's - // CAN controller is being reinitialized. We should not send any data on the CAN - // network for this to finish. 200ms should do it. not that the backdoor entry time - // should be at least 2.5x this. - Sleep(200); - // continuously try to connect via XCP true the backdoor - sessionStartResult := kProgSessionGenericError; - while sessionStartResult <> kProgSessionStarted do - begin - sessionStartResult := loader.StartProgrammingSession; - Application.ProcessMessages; - Sleep(5); - // if the is in reset of otherwise does not have the CAN controller synchronized to - // the CAN bus, we will be generating error frames, possibly leading to a bus off. - // check for this - if loader.IsComError then - begin - // bus off state, so try to recover. - MbiCallbackOnLog('Communication error detected. Trying automatic recovery. t='+TimeToStr(Time)); - loader.Disconnect; - if not loader.Connect then - begin - MbiCallbackOnLog('Could not connect to CAN interface. Check your configuration and try again. t='+TimeToStr(Time)); - MbiCallbackOnError('Could not connect to CAN interface. Check your configuration.'); - Exit; - end; - Sleep(200); - end; - // don't retry if the error was caused by not being able to unprotect the programming resource - if sessionStartResult = kProgSessionUnlockError then - begin - MbiCallbackOnLog('Security issue. Could not unprotect the programming resource. Check your configured XCP protection DLL. t='+TimeToStr(Time)); - MbiCallbackOnError('Security issue. Could not unprotect the programming resource.'); - Exit; - end; - - // check if the user cancelled - if stopRequest then - begin - MbiCallbackOnError('Programming session cancelled by user.'); - Exit; - end; - end; - end; - - // still here so programming session was started - MbiCallbackOnLog('Programming session started. t='+TimeToStr(Time)); - - // create the datafile object - datafile := TXcpDataFile.Create(progfile); - - // compute the size in kbytes - dataSizeKB := datafile.GetDataCnt / 1024; - - // Call application callback when we start the actual download - MbiCallbackOnStarted(datafile.GetDataCnt); - - // Init progress to 0 progress - progress := 0; - MbiCallbackOnProgress(progress); - - //---------------- next clear the memory regions -------------------------------------- - // update the user info - MbiCallbackOnInfo('Erasing memory...'); - - for regionCnt := 0 to datafile.GetRegionCnt-1 do - begin - // obtain the region info - datafile.GetRegionInfo(regionCnt, addr, len); - - // erase the memory - MbiCallbackOnLog('Clearing Memory '+Format('addr:0x%x,len:0x%x',[addr,len])+'. t='+TimeToStr(Time)); - if not loader.ClearMemory(addr, len) then - begin - loader.GetLastError(errorInfo); - MbiCallbackOnLog('Could not clear memory ('+errorInfo+'). t='+TimeToStr(Time)); - MbiCallbackOnError('Could not clear memory ('+errorInfo+').'); - datafile.Free; - Exit; - end; - MbiCallbackOnLog('Memory cleared. t='+TimeToStr(Time)); - end; - - //---------------- next program the memory regions ------------------------------------ - for regionCnt := 0 to datafile.GetRegionCnt-1 do - begin - // update the user info - MbiCallbackOnInfo('Reading file...'); - - // obtain the region info - datafile.GetRegionInfo(regionCnt, addr, len); - // dynamically allocated buffer memory - SetLength(progdata, len); - // obtain the regiond data - datafile.GetRegionData(regionCnt, progdata); - - bufferOffset := 0; - while len > 0 do - begin - // set the current write length taking into account kMaxProgLen - currentWriteCnt := len mod kMaxProgLen; - if currentWriteCnt = 0 then currentWriteCnt := kMaxProgLen; - - // program the data - MbiCallbackOnLog('Programming Data '+Format('addr:0x%x,len:0x%x',[addr,currentWriteCnt])+'. t='+TimeToStr(Time)); - LogData(@progdata[bufferOffset], currentWriteCnt); - - if not loader.WriteData(addr, currentWriteCnt, @progdata[bufferOffset]) then - begin - loader.GetLastError(errorInfo); - MbiCallbackOnLog('Could not program data ('+errorInfo+'). t='+TimeToStr(Time)); - MbiCallbackOnError('Could not program data ('+errorInfo+').'); - datafile.Free; - Exit; - end; - MbiCallbackOnLog('Data Programmed. t='+TimeToStr(Time)); - - // update progress - progress := progress + currentWriteCnt; - MbiCallbackOnProgress(progress); - - // update loop variables - len := len - currentWriteCnt; - addr := addr + currentWriteCnt; - bufferOffset := bufferOffset + currentWriteCnt; - - // update the user info - MbiCallbackOnInfo('Programming data... ' + Format('(%.1n of %.1n Kbytes)',[(progress/1024), dataSizeKB])); - - end; - end; - - //---------------- stop the programming session --------------------------------------- - MbiCallbackOnLog('Stopping the programming session. t='+TimeToStr(Time)); - if not loader.StopProgrammingSession then - begin - loader.GetLastError(errorInfo); - MbiCallbackOnLog('Could not stop the programming session ('+errorInfo+'). t='+TimeToStr(Time)); - MbiCallbackOnError('Could not stop the programming session ('+errorInfo+').'); - datafile.Free; - Exit; - end; - MbiCallbackOnLog('Programming session stopped. t='+TimeToStr(Time)); - - // all done so set progress to 100% and finish up - progress := datafile.GetDataCnt; - datafile.Free; - MbiCallbackOnProgress(progress); - MbiCallbackOnLog('File successfully downloaded t='+TimeToStr(Time)); - MbiCallbackOnDone; - -end; //*** end of OnTimeout *** - - -//*************************************************************************************** -// NAME: MbiInit -// PARAMETER: callback function pointers -// RETURN VALUE: none -// DESCRIPTION: Called by the application to initialize the interface library. -// -//*************************************************************************************** -procedure MbiInit(cbStarted: TStartedEvent; cbProgress: TProgressEvent; - cbDone: TDoneEvent; cbError: TErrorEvent; cbLog: TLogEvent; - cbInfo: TInfoEvent); stdcall; -begin - //--- begin of don't change --- - AppOnStarted := cbStarted; - AppOnProgress := cbProgress; - AppOnDone := cbDone; - AppOnLog := cbLog; - AppOnInfo := cbInfo; - AppOnError := cbError; - //--- end of don't change --- - - // create xcp loader object - loader := TXcpLoader.Create; - - // update to the latest configuration - loader.Configure(ExtractFilePath(ParamStr(0))+'openblt_can_vector.ini'); - - // create and init a timer - events := TEventHandlers.Create; - timer := TTimer.Create(nil); - timer.Enabled := False; - timer.Interval := 100; - timer.OnTimer := events.OnTimeout; -end; //*** end of MbiInit *** - - -//*************************************************************************************** -// NAME: MbiStart -// PARAMETER: filename of the file that is to be downloaded. -// RETURN VALUE: none -// DESCRIPTION: Called by the application to request the interface library to download -// the file that is passed as a parameter. -// -//*************************************************************************************** -procedure MbiStart(fileName: ShortString); stdcall; -begin - // update the user info - MbiCallbackOnInfo(''); - - // start the log - MbiCallbackOnLog('--- Downloading "'+fileName+'" ---'); - - // reset stop request - stopRequest := false; - - // start the startup timer which gives microBoot a chance to paint itself - timer.Enabled := True; - - // store the program's filename - progfile := fileName; -end; //*** end of MbiStart *** - - -//*************************************************************************************** -// NAME: MbiStop -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Called by the application to request the interface library to stop -// a download that could be in progress. -// -//*************************************************************************************** -procedure MbiStop; stdcall; -begin - // set stop request - stopRequest := true; - - // disconnect the transport layer - MbiCallbackOnLog('Disconnecting the transport layer. t='+TimeToStr(Time)); - loader.Disconnect; -end; //*** end of MbiStop *** - - -//*************************************************************************************** -// NAME: MbiDeInit -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Called by the application to uninitialize the interface library. -// -//*************************************************************************************** -procedure MbiDeInit; stdcall; -begin - // release xcp loader object - loader.Free; - - // release the timer and events object - timer.Free; - events.Free; - - //--- begin of don't change --- - AppOnStarted := nil; - AppOnProgress := nil; - AppOnDone := nil; - AppOnLog := nil; - AppOnInfo := nil; - AppOnError := nil; - //--- end of don't change --- -end; //*** end of MbiDeInit *** - - -//*************************************************************************************** -// NAME: MbiName -// PARAMETER: none -// RETURN VALUE: name of the interface library -// DESCRIPTION: Called by the application to obtain the name of the interface library. -// -//*************************************************************************************** -function MbiName : ShortString; stdcall; -begin - Result := 'OpenBLT CAN Vector'; -end; //*** end of MbiName *** - - -//*************************************************************************************** -// NAME: MbiDescription -// PARAMETER: none -// RETURN VALUE: description of the interface library -// DESCRIPTION: Called by the application to obtain the description of the interface -// library. -// -//*************************************************************************************** -function MbiDescription : ShortString; stdcall; -begin - Result := 'OpenBLT using Vector CAN Interface'; -end; //*** end of MbiDescription *** - - -//*************************************************************************************** -// NAME: MbiVersion -// PARAMETER: none -// RETURN VALUE: version number -// DESCRIPTION: Called by the application to obtain the version number of the -// interface library. -// -//*************************************************************************************** -function MbiVersion : Longword; stdcall; -begin - Result := 10000; // v1.00.00 -end; //*** end of MbiVersion *** - - -//*************************************************************************************** -// NAME: MbiVInterface -// PARAMETER: none -// RETURN VALUE: version number of the supported interface -// DESCRIPTION: Called by the application to obtain the version number of the -// Mbi interface uBootInterface.pas (not the interface library). This can -// be used by the application for backward compatibility. -// -//*************************************************************************************** -function MbiVInterface : Longword; stdcall; -begin - Result := 10001; // v1.00.01 -end; //*** end of MbiVInterface *** - - -//*************************************************************************************** -// NAME: MbiConfigure -// PARAMETER: none -// RETURN VALUE: none -// DESCRIPTION: Called by the application to enable the user to configure the inter- -// face library through the application. -// -//*************************************************************************************** -procedure MbiConfigure; stdcall; -var - settings : TXcpSettings; -begin - // create xcp settings object - settings := TXcpSettings.Create(ExtractFilePath(ParamStr(0))+'openblt_can_vector.ini'); - - // display the modal configuration dialog - settings.Configure; - - // release the xcp settings object - settings.Free; - - // update to the latest configuration - loader.Configure(ExtractFilePath(ParamStr(0))+'openblt_can_vector.ini'); -end; //*** end of MbiConfigure *** - - -//*************************************************************************************** -// External Declarations -//*************************************************************************************** -exports - //--- begin of don't change --- - MbiInit index 1, - MbiStart index 2, - MbiStop index 3, - MbiDeInit index 4, - MbiName index 5, - MbiDescription index 6, - MbiVersion index 7, - MbiConfigure index 8, - MbiVInterface index 9; - //--- end of don't change --- - -end. -//********************************** end of openblt_can_vector.dpr ********************** diff --git a/Host/Source/MicroBoot/interfaces/net/WSockets.pas b/Host/Source/MicroBoot/interfaces/net/WSockets.pas index db7c5c76..e81d36d9 100644 --- a/Host/Source/MicroBoot/interfaces/net/WSockets.pas +++ b/Host/Source/MicroBoot/interfaces/net/WSockets.pas @@ -425,8 +425,8 @@ begin with WSAData do begin FVersion:= Concat(IntToStr(Hi(wVersion)),'.',(IntToStr(Lo(wVersion)))); - FDescription:= StrPas(szDescription); - FSystemStatus:= StrPas(szSystemStatus); + FDescription:= String(szDescription); + FSystemStatus:= String(szSystemStatus); FMaxSockets:= iMaxSockets; FMaxUDPSize:= iMaxUDPDg; end; @@ -462,16 +462,16 @@ begin Exit; end; - ServEnt:= getservbyname(PChar(Port), ProtoEnt^.p_name); + ServEnt:= getservbyname(PAnsiChar(AnsiString(Port)), ProtoEnt^.p_name); if ServEnt = nil then SockAddrIn.sin_port:= htons(StrToInt(Port)) else SockAddrIn.sin_port:= ServEnt^.s_port; - SockAddrIn.sin_addr.s_addr:= inet_addr(PChar(Host)); - if SockAddrIn.sin_addr.s_addr = INADDR_NONE then + SockAddrIn.sin_addr.s_addr:= inet_addr(PAnsiChar(AnsiString(Host))); + if SockAddrIn.sin_addr.s_addr = Integer(INADDR_NONE) then begin - HostEnt:= gethostbyname(PChar(Host)); + HostEnt:= gethostbyname(PAnsiChar(AnsiString(Host))); if HostEnt = nil then begin SocketError(WSAGetLastError); @@ -495,7 +495,7 @@ begin if ProtoEnt = nil then Exit; - ServEnt:= getservbyname(PChar(Port), ProtoEnt^.p_name); + ServEnt:= getservbyname(PAnsiChar(AnsiString(Port)), ProtoEnt^.p_name); if ServEnt = nil then SockAddrIn.sin_port:= htons(StrToInt(Port)) else @@ -518,13 +518,13 @@ begin if ProtoEnt = nil then Exit; - ServEnt:= getservbyname(PChar(Port), ProtoEnt^.p_name); + ServEnt:= getservbyname(PAnsiChar(AnsiString(Port)), ProtoEnt^.p_name); if ServEnt = nil then SockAddrIn.sin_port:= htons(StrToInt(Port)) else SockAddrIn.sin_port:= ServEnt^.s_port; - SockAddrIn.sin_addr.s_addr:= INADDR_BROADCAST; + SockAddrIn.sin_addr.s_addr:= Integer(INADDR_BROADCAST); Result:= true; end; @@ -534,12 +534,12 @@ var begin HostEnt:= gethostbyaddr(@SockAddrIn.sin_addr.S_addr, 4, AF_INET); if HostEnt <> nil then - Result:= HostEnt.h_name; + Result:= String(AnsiString(HostEnt.h_name)); end; function TCustomWSocket.SockAddrInToAddress(SockAddrIn: TSockAddrIn): string; begin - Result:= inet_ntoa(SockAddrIn.sin_addr); + Result:= String(AnsiString(inet_ntoa(SockAddrIn.sin_addr))); end; function TCustomWSocket.SockAddrInToPort(SockAddrIn: TSockAddrIn): string; @@ -560,7 +560,7 @@ begin begin HostEnt:= gethostbyaddr(@SockAddrIn.sin_addr.S_addr, 4, AF_INET); if HostEnt <> nil then - Result:= HostEnt.h_name; + Result:= String(AnsiString(HostEnt.h_name)); end; end; end; @@ -574,7 +574,7 @@ begin begin Len:= SizeOf(SockAddrIn); if getsockname(Socket, SockAddrIn, Len) <> SOCKET_ERROR then - Result:= inet_ntoa(SockAddrIn.sin_addr); + Result:= String(AnsiString(inet_ntoa(SockAddrIn.sin_addr))); end; end; @@ -604,7 +604,7 @@ begin begin HostEnt:= gethostbyaddr(@SockAddrIn.sin_addr.S_addr, 4, AF_INET); if HostEnt <> nil then - Result:= HostEnt.h_name; + Result:= String(AnsiString(HostEnt.h_name)); end; end; end; @@ -618,7 +618,7 @@ begin begin Len:= SizeOf(SockAddrIn); if getpeername(Socket, SockAddrIn, Len) <> SOCKET_ERROR then - Result:= inet_ntoa(SockAddrIn.sin_addr); + Result:= String(AnsiString(inet_ntoa(SockAddrIn.sin_addr))); end; end; @@ -881,7 +881,7 @@ function TCustomWSocket.GetLocalHostAddress: string; var SockAddrIn: TSockAddrIn; HostEnt: PHostEnt; - szHostName: array[0..128] of char; + szHostName: array[0..128] of ansichar; begin if gethostname(szHostName, 128) = 0 then begin @@ -891,7 +891,7 @@ begin else begin SockAddrIn.sin_addr.S_addr:= longint(plongint(HostEnt^.h_addr_list^)^); - Result:= inet_ntoa(SockAddrIn.sin_addr); + Result:= String(AnsiString(inet_ntoa(SockAddrIn.sin_addr))); end; end else @@ -900,10 +900,10 @@ end; function TCustomWSocket.GetLocalHostName: string; var - szHostName: array[0..128] of char; + szHostName: array[0..128] of ansichar; begin if gethostname(szHostName, 128) = 0 then - Result:= szHostName + Result:= String(AnsiString(szHostName)) else SocketError(WSAGetLastError); end; @@ -1019,7 +1019,7 @@ begin end; SockOpt:= true; {Enable OOB Data inline} - if setsockopt(FLocalSocket, SOL_SOCKET, SO_OOBINLINE, PChar(@SockOpt), SizeOf(SockOpt)) <> 0 then + if setsockopt(FLocalSocket, SOL_SOCKET, SO_OOBINLINE, PAnsiChar(@SockOpt), SizeOf(SockOpt)) <> 0 then begin SocketError(WSAGetLastError); closesocket(FLocalSocket); @@ -1136,7 +1136,7 @@ begin end; SockOpt:= true; {Enable OOB Data inline} - if setsockopt(NewSocket, SOL_SOCKET, SO_OOBINLINE , PChar(@SockOpt), SizeOf(SockOpt)) <> 0 then + if setsockopt(NewSocket, SOL_SOCKET, SO_OOBINLINE , PAnsiChar(@SockOpt), SizeOf(SockOpt)) <> 0 then begin SocketError(WSAGetLastError); closesocket(NewSocket); @@ -1495,7 +1495,7 @@ begin end; SockOpt:= true; {Enable Broadcasting on this Socket} - if setsockopt(FLocalSocket, SOL_SOCKET, SO_BROADCAST, PChar(@SockOpt), SizeOf(SockOpt)) <> 0 then + if setsockopt(FLocalSocket, SOL_SOCKET, SO_BROADCAST, PAnsiChar(@SockOpt), SizeOf(SockOpt)) <> 0 then begin SocketError(WSAGetLastError); closesocket(FLocalSocket); diff --git a/Host/Source/MicroBoot/interfaces/net/XcpSettings.dfm b/Host/Source/MicroBoot/interfaces/net/XcpSettings.dfm index 47615e4b..b35a68d2 100644 Binary files a/Host/Source/MicroBoot/interfaces/net/XcpSettings.dfm and b/Host/Source/MicroBoot/interfaces/net/XcpSettings.dfm differ diff --git a/Host/Source/MicroBoot/interfaces/net/XcpSettings.pas b/Host/Source/MicroBoot/interfaces/net/XcpSettings.pas index 98a0339a..ea11d0a0 100644 --- a/Host/Source/MicroBoot/interfaces/net/XcpSettings.pas +++ b/Host/Source/MicroBoot/interfaces/net/XcpSettings.pas @@ -36,7 +36,7 @@ interface //*************************************************************************************** uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, - StdCtrls, ComCtrls, ExtCtrls, IniFiles; + StdCtrls, ComCtrls, ExtCtrls, IniFiles, Vcl.Imaging.pngimage; //*************************************************************************************** @@ -76,7 +76,6 @@ type edtPort: TEdit; edtTconnect: TEdit; lblTconnect: TLabel; - chbSocketRetry: TCheckBox; procedure btnOKClick(Sender: TObject); procedure btnCancelClick(Sender: TObject); procedure btnBrowseClick(Sender: TObject); @@ -203,7 +202,6 @@ begin // NET related elements FSettingsForm.edtHostname.Text := settingsIni.ReadString('net', 'hostname', '169.254.19.63'); FSettingsForm.edtPort.Text := settingsIni.ReadString('net', 'port', '1000'); - FSettingsForm.chbSocketRetry.Checked := settingsIni.ReadBool('net', 'retry', false); // XCP related elements FSettingsForm.edtSeedKey.Text := settingsIni.ReadString('xcp', 'seedkey', ExtractFilePath(ParamStr(0))+''); @@ -223,7 +221,6 @@ begin // NET related elements FSettingsForm.edtHostname.Text := '169.254.19.63'; FSettingsForm.edtPort.Text := '1000'; - FSettingsForm.chbSocketRetry.Checked := false; // XCP related elements FSettingsForm.edtSeedKey.Text := ExtractFilePath(ParamStr(0))+''; @@ -246,7 +243,6 @@ begin // NET related elements settingsIni.WriteString('net', 'hostname', FSettingsForm.edtHostname.Text); settingsIni.WriteString('net', 'port', FSettingsForm.edtPort.Text); - settingsIni.WriteBool('net', 'retry', FSettingsForm.chbSocketRetry.Checked); // XCP related elements settingsIni.WriteString('xcp', 'seedkey', FSettingsForm.edtSeedKey.Text); diff --git a/Host/Source/MicroBoot/interfaces/net/XcpTransport.pas b/Host/Source/MicroBoot/interfaces/net/XcpTransport.pas index df1bdd7d..79bd37cc 100644 --- a/Host/Source/MicroBoot/interfaces/net/XcpTransport.pas +++ b/Host/Source/MicroBoot/interfaces/net/XcpTransport.pas @@ -61,7 +61,6 @@ type socket : TTCPClient; hostname : string; port : string; - connectRetry : Boolean; croCounter : LongWord; procedure OnSocketDataAvailable(Sender: TObject; WinSocket: TSocket); function MsgWaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD; @@ -156,9 +155,6 @@ begin // configure port port := settingsIni.ReadString('net', 'port', '1000'); - // configure the connection retry feature - connectRetry := settingsIni.ReadBool('net', 'retry', false); - // release ini file object settingsIni.Free; end @@ -169,9 +165,6 @@ begin // configure default port port := '1000'; - - // configure default connection retry feature setting - connectRetry := false; end; end; //*** end of Configure *** @@ -208,15 +201,11 @@ begin // wait for the connection to be established while socket.SocketState <> ssConnected do begin - // check timeout if connection retry feature is enabled - if connectRetry then + // check for timeout + if GetTickCount > connectTimeout then begin - // check for timeout - if GetTickCount > connectTimeout then - begin - result := false; - Exit; - end; + result := false; + Exit; end; Application.ProcessMessages; diff --git a/Host/Source/MicroBoot/interfaces/net/openblt_net.cfg b/Host/Source/MicroBoot/interfaces/net/openblt_net.cfg deleted file mode 100644 index 7e67a882..00000000 --- a/Host/Source/MicroBoot/interfaces/net/openblt_net.cfg +++ /dev/null @@ -1,35 +0,0 @@ --$A+ --$B- --$C+ --$D+ --$E- --$F- --$G+ --$H+ --$I+ --$J+ --$K- --$L+ --$M- --$N+ --$O+ --$P+ --$Q- --$R- --$S- --$T- --$U- --$V+ --$W- --$X+ --$YD --$Z1 --cg --AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; --H+ --W+ --M --$M16384,1048576 --K$00400000 --E../../../../ --LNc:\borland\delphi4\Lib diff --git a/Host/Source/MicroBoot/interfaces/net/openblt_net.dof b/Host/Source/MicroBoot/interfaces/net/openblt_net.dof deleted file mode 100644 index 5d0ef50e..00000000 --- a/Host/Source/MicroBoot/interfaces/net/openblt_net.dof +++ /dev/null @@ -1,85 +0,0 @@ -[Compiler] -A=1 -B=0 -C=1 -D=1 -E=0 -F=0 -G=1 -H=1 -I=1 -J=1 -K=0 -L=1 -M=0 -N=1 -O=1 -P=1 -Q=0 -R=0 -S=0 -T=0 -U=0 -V=1 -W=0 -X=1 -Y=1 -Z=1 -ShowHints=1 -ShowWarnings=1 -UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -[Linker] -MapFile=0 -OutputObjs=0 -ConsoleApp=1 -DebugInfo=0 -RemoteSymbols=0 -MinStackSize=16384 -MaxStackSize=1048576 -ImageBase=4194304 -ExeDescription= -[Directories] -OutputDir=../../../../ -UnitOutputDir= -PackageDLLOutputDir= -PackageDCPOutputDir= -SearchPath= -Packages=Vcl40;Vclx40;Vcldb40;vcldbx40;VclSmp40;Qrpt40;IcsDel40 -Conditionals= -DebugSourceDirs= -UsePackages=0 -[Parameters] -RunParams= -HostApplication= -[Version Info] -IncludeVerInfo=0 -AutoIncBuild=0 -MajorVer=1 -MinorVer=0 -Release=0 -Build=0 -Debug=0 -PreRelease=0 -Special=0 -Private=0 -DLL=0 -Locale=1043 -CodePage=1252 -[Version Info Keys] -CompanyName= -FileDescription= -FileVersion=1.0.0.0 -InternalName= -LegalCopyright= -LegalTrademarks= -OriginalFilename= -ProductName= -ProductVersion=1.0.0.0 -Comments= -[HistoryLists\hlUnitAliases] -Count=1 -Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -[HistoryLists\hlOutputDirectorry] -Count=2 -Item0=../../../../ -Item1=../../../ diff --git a/Host/Source/MicroBoot/interfaces/net/openblt_net.dpr b/Host/Source/MicroBoot/interfaces/net/openblt_net.dpr index 6471202c..13f96c10 100644 --- a/Host/Source/MicroBoot/interfaces/net/openblt_net.dpr +++ b/Host/Source/MicroBoot/interfaces/net/openblt_net.dpr @@ -224,7 +224,7 @@ begin end; // update the log - MbiCallbackOnLog(logStr); + MbiCallbackOnLog(ShortString(logStr)); // update loop variables len := len - currentWriteCnt; @@ -258,14 +258,14 @@ begin // connect the transport layer MbiCallbackOnInfo('Connecting to target via TCP/IP. Reset your target if this takes a long time.'); - MbiCallbackOnLog('Connecting to target via TCP/IP. t='+TimeToStr(Time)); + MbiCallbackOnLog('Connecting to target via TCP/IP. t='+ShortString(TimeToStr(Time))); Application.ProcessMessages; if not loader.Connect then begin // update the user info MbiCallbackOnInfo('Could not connect via TCP/IP. Retrying. Reset your target if this takes a long time.'); - MbiCallbackOnLog('Transport layer connection failed. Check the configured IP address and port. t='+TimeToStr(Time)); - MbiCallbackOnLog('Retrying transport layer connection. Reset your target if this takes a long time. t='+TimeToStr(Time)); + MbiCallbackOnLog('Transport layer connection failed. Check the configured IP address and port. t='+ShortString(TimeToStr(Time))); + MbiCallbackOnLog('Retrying transport layer connection. Reset your target if this takes a long time. t='+ShortString(TimeToStr(Time))); Application.ProcessMessages; // continuously try to connect the transport layer while not loader.Connect do @@ -282,11 +282,11 @@ begin // we now have a socket connected to the target. next attempt to connect to the target // via XCP. - MbiCallbackOnLog('Starting the programming session. t='+TimeToStr(Time)); + MbiCallbackOnLog('Starting the programming session. t='+ShortString(TimeToStr(Time))); sessionStartResult := loader.StartProgrammingSession; if sessionStartResult = kProgSessionUnlockError then begin - MbiCallbackOnLog('Security issue. Could not unprotect the programming resource. Check your configured XCP protection DLL. t='+TimeToStr(Time)); + MbiCallbackOnLog('Security issue. Could not unprotect the programming resource. Check your configured XCP protection DLL. t='+ShortString(TimeToStr(Time))); MbiCallbackOnError('Security issue. Could not unprotect the programming resource.'); loader.Disconnect; Exit; @@ -299,18 +299,18 @@ begin // ration of the ethernet controller so we need to disconnect the socket here and // wait for it to reconnect. MbiCallbackOnInfo('No response from target. Disconnecting TCP/IP socket.'); - MbiCallbackOnLog('No response from target. Disconnecting TCP/IP socket. t='+TimeToStr(Time)); + MbiCallbackOnLog('No response from target. Disconnecting TCP/IP socket. t='+ShortString(TimeToStr(Time))); loader.Disconnect; // connect the transport layer MbiCallbackOnInfo('Connecting to target via TCP/IP. Reset your target if this takes a long time.'); - MbiCallbackOnLog('Connecting to target via TCP/IP. t='+TimeToStr(Time)); + MbiCallbackOnLog('Connecting to target via TCP/IP. t='+ShortString(TimeToStr(Time))); Application.ProcessMessages; if not loader.Connect then begin // update the user info MbiCallbackOnInfo('Could not connect via TCP/IP. Retrying. Reset your target if this takes a long time.'); - MbiCallbackOnLog('Transport layer connection failed. Check the configured IP address and port. t='+TimeToStr(Time)); - MbiCallbackOnLog('Retrying transport layer connection. Reset your target if this takes a long time. t='+TimeToStr(Time)); + MbiCallbackOnLog('Transport layer connection failed. Check the configured IP address and port. t='+ShortString(TimeToStr(Time))); + MbiCallbackOnLog('Retrying transport layer connection. Reset your target if this takes a long time. t='+ShortString(TimeToStr(Time))); Application.ProcessMessages; // continuously try to connect the transport layer while not loader.Connect do @@ -325,12 +325,12 @@ begin end; end; //---------------- start the programming session -------------------------------------- - MbiCallbackOnLog('Starting the programming session. t='+TimeToStr(Time)); + MbiCallbackOnLog('Starting the programming session. t='+ShortString(TimeToStr(Time))); // try initial connect via XCP sessionStartResult := loader.StartProgrammingSession; if sessionStartResult = kProgSessionUnlockError then begin - MbiCallbackOnLog('Security issue. Could not unprotect the programming resource. Check your configured XCP protection DLL. t='+TimeToStr(Time)); + MbiCallbackOnLog('Security issue. Could not unprotect the programming resource. Check your configured XCP protection DLL. t='+ShortString(TimeToStr(Time))); MbiCallbackOnError('Security issue. Could not unprotect the programming resource.'); loader.Disconnect; Exit; @@ -341,7 +341,7 @@ begin begin // update the user info MbiCallbackOnInfo('Could not connect. Please reset your target...'); - MbiCallbackOnLog('Connect failed. Switching to backdoor entry mode. t='+TimeToStr(Time)); + MbiCallbackOnLog('Connect failed. Switching to backdoor entry mode. t='+ShortString(TimeToStr(Time))); Application.ProcessMessages; // continuously try to connect via XCP true the backdoor sessionStartResult := kProgSessionGenericError; @@ -353,7 +353,7 @@ begin // don't retry if the error was caused by not being able to unprotect the programming resource if sessionStartResult = kProgSessionUnlockError then begin - MbiCallbackOnLog('Security issue. Could not unprotect the programming resource. Check your configured XCP protection DLL. t='+TimeToStr(Time)); + MbiCallbackOnLog('Security issue. Could not unprotect the programming resource. Check your configured XCP protection DLL. t='+ShortString(TimeToStr(Time))); MbiCallbackOnError('Security issue. Could not unprotect the programming resource.'); Exit; end; @@ -369,7 +369,7 @@ begin end; // still here so programming session was started - MbiCallbackOnLog('Programming session started. t='+TimeToStr(Time)); + MbiCallbackOnLog('Programming session started. t='+ShortString(TimeToStr(Time))); // create the datafile object datafile := TXcpDataFile.Create(progfile); @@ -394,16 +394,16 @@ begin datafile.GetRegionInfo(regionCnt, addr, len); // erase the memory - MbiCallbackOnLog('Clearing Memory '+Format('addr:0x%x,len:0x%x',[addr,len])+'. t='+TimeToStr(Time)); + MbiCallbackOnLog('Clearing Memory '+ShortString(Format('addr:0x%x,len:0x%x',[addr,len]))+'. t='+ShortString(TimeToStr(Time))); if not loader.ClearMemory(addr, len) then begin loader.GetLastError(errorInfo); - MbiCallbackOnLog('Could not clear memory ('+errorInfo+'). t='+TimeToStr(Time)); - MbiCallbackOnError('Could not clear memory ('+errorInfo+').'); + MbiCallbackOnLog('Could not clear memory ('+ShortString(errorInfo)+'). t='+ShortString(TimeToStr(Time))); + MbiCallbackOnError('Could not clear memory ('+ShortString(errorInfo)+').'); datafile.Free; Exit; end; - MbiCallbackOnLog('Memory cleared. t='+TimeToStr(Time)); + MbiCallbackOnLog('Memory cleared. t='+ShortString(TimeToStr(Time))); end; //---------------- next program the memory regions ------------------------------------ @@ -427,18 +427,18 @@ begin if currentWriteCnt = 0 then currentWriteCnt := kMaxProgLen; // program the data - MbiCallbackOnLog('Programming Data '+Format('addr:0x%x,len:0x%x',[addr,currentWriteCnt])+'. t='+TimeToStr(Time)); + MbiCallbackOnLog('Programming Data '+ShortString(Format('addr:0x%x,len:0x%x',[addr,currentWriteCnt]))+'. t='+ShortString(TimeToStr(Time))); LogData(@progdata[bufferOffset], currentWriteCnt); if not loader.WriteData(addr, currentWriteCnt, @progdata[bufferOffset]) then begin loader.GetLastError(errorInfo); - MbiCallbackOnLog('Could not program data ('+errorInfo+'). t='+TimeToStr(Time)); - MbiCallbackOnError('Could not program data ('+errorInfo+').'); + MbiCallbackOnLog('Could not program data ('+ShortString(errorInfo)+'). t='+ShortString(TimeToStr(Time))); + MbiCallbackOnError('Could not program data ('+ShortString(errorInfo)+').'); datafile.Free; Exit; end; - MbiCallbackOnLog('Data Programmed. t='+TimeToStr(Time)); + MbiCallbackOnLog('Data Programmed. t='+ShortString(TimeToStr(Time))); // update progress progress := progress + currentWriteCnt; @@ -450,28 +450,28 @@ begin bufferOffset := bufferOffset + currentWriteCnt; // update the user info - MbiCallbackOnInfo('Programming data... ' + Format('(%.1n of %.1n Kbytes)',[(progress/1024), dataSizeKB])); + MbiCallbackOnInfo('Programming data... ' + ShortString(Format('(%.1n of %.1n Kbytes)',[(progress/1024), dataSizeKB]))); end; end; //---------------- stop the programming session --------------------------------------- - MbiCallbackOnLog('Stopping the programming session. t='+TimeToStr(Time)); + MbiCallbackOnLog('Stopping the programming session. t='+ShortString(TimeToStr(Time))); if not loader.StopProgrammingSession then begin loader.GetLastError(errorInfo); - MbiCallbackOnLog('Could not stop the programming session ('+errorInfo+'). t='+TimeToStr(Time)); - MbiCallbackOnError('Could not stop the programming session ('+errorInfo+').'); + MbiCallbackOnLog('Could not stop the programming session ('+ShortString(errorInfo)+'). t='+ShortString(TimeToStr(Time))); + MbiCallbackOnError('Could not stop the programming session ('+ShortString(errorInfo)+').'); datafile.Free; Exit; end; - MbiCallbackOnLog('Programming session stopped. t='+TimeToStr(Time)); + MbiCallbackOnLog('Programming session stopped. t='+ShortString(TimeToStr(Time))); // all done so set progress to 100% and finish up progress := datafile.GetDataCnt; datafile.Free; MbiCallbackOnProgress(progress); - MbiCallbackOnLog('File successfully downloaded t='+TimeToStr(Time)); + MbiCallbackOnLog('File successfully downloaded t='+ShortString(TimeToStr(Time))); MbiCallbackOnDone; end; //*** end of OnTimeout *** @@ -535,7 +535,7 @@ begin timer.Enabled := True; // store the program's filename - progfile := fileName; + progfile := String(fileName); end; //*** end of MbiStart *** @@ -553,7 +553,7 @@ begin stopRequest := true; // disconnect the transport layer - MbiCallbackOnLog('Disconnecting the transport layer. t='+TimeToStr(Time)); + MbiCallbackOnLog('Disconnecting the transport layer. t='+ShortString(TimeToStr(Time))); loader.Disconnect; end; //*** end of MbiStop *** @@ -672,15 +672,15 @@ end; //*** end of MbiConfigure *** //*************************************************************************************** exports //--- begin of don't change --- - MbiInit index 1, - MbiStart index 2, - MbiStop index 3, - MbiDeInit index 4, - MbiName index 5, - MbiDescription index 6, - MbiVersion index 7, - MbiConfigure index 8, - MbiVInterface index 9; + MbiInit, + MbiStart, + MbiStop, + MbiDeInit, + MbiName, + MbiDescription, + MbiVersion, + MbiConfigure, + MbiVInterface; //--- end of don't change --- end. diff --git a/Host/Source/MicroBoot/interfaces/net/openblt_net.dproj b/Host/Source/MicroBoot/interfaces/net/openblt_net.dproj new file mode 100644 index 00000000..4116efa5 --- /dev/null +++ b/Host/Source/MicroBoot/interfaces/net/openblt_net.dproj @@ -0,0 +1,120 @@ + + + {B16E2683-DC28-4FA8-9418-7F3350903FA7} + openblt_net.dpr + True + Debug + 1 + Library + VCL + 18.1 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + true + true + Vcl40;Vclx40;Vcldb40;vcldbx40;VclSmp40;Qrpt40;IcsDel40;$(DCC_UsePackage) + false + false + 1 + 1 + false + openblt_net + 1 + false + true + ../../../../ + 00400000 + 1043 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace) + + + 1033 + System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + true + + + 0 + 0 + false + RELEASE;$(DCC_Define) + + + true + DEBUG;$(DCC_Define) + false + + + (None) + 1033 + C:\Work\software\OpenBLT\Host\MicroBoot.exe + true + + + + MainSource + + + + + + + +
XcpSettingsForm
+
+ + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + +
+ + Delphi.Personality.12 + + + + + openblt_net.dpr + + + + True + + + 12 + + + +
diff --git a/Host/Source/MicroBoot/interfaces/uart/CPDrv.pas b/Host/Source/MicroBoot/interfaces/uart/CPDrv.pas deleted file mode 100644 index c3d08f2d..00000000 --- a/Host/Source/MicroBoot/interfaces/uart/CPDrv.pas +++ /dev/null @@ -1,1158 +0,0 @@ -//*************************************************************************************** -// 20060225: Updated by Frank Voorburg - Feaser -// -// - When using ReadXxx the windows messages are now being processed -// - When using ReadXxx the loop will stop (FCancel) upon disconnect -//*************************************************************************************** - -//------------------------------------------------------------------------ -// UNIT : CPDrv.pas -// CONTENTS : TCommPortDriver component -// VERSION : 2.1 -// TARGET : (Inprise's) Borland Delphi 4.0 -// AUTHOR : Marco Cocco -// STATUS : Freeware -// INFOS : Implementation of TCommPortDriver component: -// - non multithreaded serial I/O -// KNOWN BUGS : none -// COMPATIBILITY : Windows 95/98/NT/2000 -// REPLACES : TCommPortDriver v2.00 (Delphi 4.0) -// TCommPortDriver v1.08/16 (Delphi 1.0) -// TCommPortDriver v1.08/32 (Delphi 2.0/3.0) -// BACK/COMPAT. : partial - a lot of properties have been renamed -// RELEASE DATE : 06/06/2000 -// (Replaces v2.0 released on 30/NOV/1998) -//------------------------------------------------------------------------ -// FOR UPDATES : - sorry, no home page - -// BUGS REPORT : mail to : mcocco@libero.it -// or: ditrek@tiscalinet.it -//------------------------------------------------------------------------ -// -// Copyright (c) 1996-2000 by Marco Cocco. All rights reseved. -// Copyright (c) 1996-2000 by d3k Software Company. All rights reserved. -// -//****************************************************************************** -//* Permission to use, copy, modify, and distribute this software and its * -//* documentation without fee for any purpose is hereby granted, * -//* provided that the above copyright notice appears on all copies and that * -//* both that copyright notice and this permission notice appear in all * -//* supporting documentation. * -//* * -//* NO REPRESENTATIONS ARE MADE ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY * -//* PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. * -//* NEITHER MARCO COCCO OR D3K SHALL BE LIABLE FOR ANY DAMAGES SUFFERED BY * -//* THE USE OF THIS SOFTWARE. * -//****************************************************************************** - -unit CPDrv; - -interface - -uses - // Delphi units - Windows, Messages, SysUtils, Forms, Classes - // ComDrv32 units - ; - -//------------------------------------------------------------------------ -// Property types -//------------------------------------------------------------------------ - -type - // Baud Rates (custom or 110...256k bauds) - TBaudRate = ( brCustom, - br110, br300, br600, br1200, br2400, br4800, - br9600, br14400, br19200, br38400, br56000, - br57600, br115200, br128000, br256000 ); - // Port Numbers ( custom or COM1..COM16 ) - TPortNumber = ( pnCustom, - pnCOM1, pnCOM2, pnCOM3, pnCOM4, pnCOM5, pnCOM6, pnCOM7, - pnCOM8, pnCOM9, pnCOM10, pnCOM11, pnCOM12, pnCOM13, - pnCOM14, pnCOM15, pnCOM16 ); - // Data bits ( 5, 6, 7, 8 ) - TDataBits = ( db5BITS, db6BITS, db7BITS, db8BITS ); - // Stop bits ( 1, 1.5, 2 ) - TStopBits = ( sb1BITS, sb1HALFBITS, sb2BITS ); - // Parity ( None, odd, even, mark, space ) - TParity = ( ptNONE, ptODD, ptEVEN, ptMARK, ptSPACE ); - // Hardware Flow Control ( None, None + RTS always on, RTS/CTS ) - THwFlowControl = ( hfNONE, hfNONERTSON, hfRTSCTS ); - // Software Flow Control ( None, XON/XOFF ) - TSwFlowControl = ( sfNONE, sfXONXOFF ); - // What to do with incomplete (incoming) packets ( Discard, Pass ) - TPacketMode = ( pmDiscard, pmPass ); - -//------------------------------------------------------------------------ -// Event types -//------------------------------------------------------------------------ - -type - // RX event ( packet mode disabled ) - TReceiveDataEvent = procedure( Sender: TObject; DataPtr: pointer; DataSize: DWORD ) of object; - // RX event ( packed mode enabled ) - TReceivePacketEvent = procedure( Sender: TObject; Packet: pointer; DataSize: DWORD ) of object; - -//------------------------------------------------------------------------ -// Other types -//------------------------------------------------------------------------ - -type - // Line status ( Clear To Send, Data Set Ready, Ring, Carrier Detect ) - TLineStatus = ( lsCTS, lsDSR, lsRING, lsCD ); - // Set of line status - TLineStatusSet = set of TLineStatus; - -//------------------------------------------------------------------------ -// Constants -//------------------------------------------------------------------------ - -const - RELEASE_NOCLOSE_PORT = HFILE(INVALID_HANDLE_VALUE-1); - -//------------------------------------------------------------------------ -// TCommPortDriver component -//------------------------------------------------------------------------ - -type - TCommPortDriver = class( TComponent ) - protected - // Device Handle ( File Handle ) - FHandle : HFILE; - // # of the COM port to use, or pnCustom to use custom port name - FPort : TPortNumber; - // Custom port name ( usually '\\.\COMn', with n = 1..x ) - FPortName : string; - // COM Port speed (brXXX) - FBaudRate : TBaudRate; - // Baud rate ( actual numeric value ) - FBaudRateValue : DWORD; - // Data bits size (dbXXX) - FDataBits : TDataBits; - // How many stop bits to use (sbXXX) - FStopBits : TStopBits; - // Type of parity to use (ptXXX) - FParity : TParity; - // Type of hw handshaking (hw flow control) to use (hfXXX) - FHwFlow : THwFlowControl; - // Type of sw handshaking (sw flow control) to use (sFXXX) - FSwFlow : TSwFlowControl; - // Size of the input buffer - FInBufSize : DWORD; - // Size of the output buffer - FOutBufSize : DWORD; - // Size of a data packet - FPacketSize : smallint; - // ms to wait for a complete packet (<=0 = disabled) - FPacketTimeout : integer; - // What to do with incomplete packets (pmXXX) - FPacketMode : TPacketMode; - // Event to raise on data reception (asynchronous) - FOnReceiveData : TReceiveDataEvent; - // Event to raise on packet reception (asynchronous) - FOnReceivePacket : TReceivePacketEvent; - // ms of delay between COM port pollings - FPollingDelay : word; - // Specifies if the DTR line must be enabled/disabled on connect - FEnableDTROnOpen : boolean; - // Output timeout - milliseconds - FOutputTimeout : word; - // Timeout for ReadData - FInputTimeout : DWORD; - // Set to TRUE to prevent hangs when no device connected or - // device is OFF - FCkLineStatus : boolean; - // This is used for the timer - FNotifyWnd : HWND; - // Temporary buffer (RX) - used internally - FTempInBuffer : pointer; - // Time of the first byte of current RX packet - FFirstByteOfPacketTime : DWORD; - // Number of RX polling timer pauses - FRXPollingPauses : integer; - - FCancel : Boolean; - - // Sets the COM port handle - procedure SetHandle( Value: HFILE ); - // Selects the COM port to use - procedure SetPort( Value: TPortNumber ); - // Sets the port name - procedure SetPortName( Value: string ); - // Selects the baud rate - procedure SetBaudRate( Value: TBaudRate ); - // Selects the baud rate ( actual baud rate value ) - procedure SetBaudRateValue( Value: DWORD ); - // Selects the number of data bits - procedure SetDataBits( Value: TDataBits ); - // Selects the number of stop bits - procedure SetStopBits( Value: TStopBits ); - // Selects the kind of parity - procedure SetParity( Value: TParity ); - // Selects the kind of hardware flow control - procedure SetHwFlowControl( Value: THwFlowControl ); - // Selects the kind of software flow control - procedure SetSwFlowControl( Value: TSwFlowControl ); - // Sets the RX buffer size - procedure SetInBufSize( Value: DWORD ); - // Sets the TX buffer size - procedure SetOutBufSize( Value: DWORD ); - // Sets the size of incoming packets - procedure SetPacketSize( Value: smallint ); - // Sets the timeout for incoming packets - procedure SetPacketTimeout( Value: integer ); - // Sets the delay between polling checks - procedure SetPollingDelay( Value: word ); - // Applies current settings to open COM port - function ApplyCOMSettings: boolean; - // Polling proc - procedure TimerWndProc( var msg: TMessage ); - public - // Constructor - constructor Create( AOwner: TComponent ); override; - // Destructor - destructor Destroy; override; - - // Opens the COM port and takes of it. Returns false if something - // goes wrong. - function Connect: boolean; - // Closes the COM port and releases control of it - procedure Disconnect; - // Returns true if COM port has been opened - function Connected: boolean; - // Returns the current state of CTS, DSR, RING and RLSD (CD) lines. - // The function fails if the hardware does not support the control-register - // values (that is, returned set is always empty). - function GetLineStatus: TLineStatusSet; - // Returns true if polling has not been paused - function IsPolling: boolean; - // Pauses polling - procedure PausePolling; - // Re-starts polling (after pause) - procedure ContinuePolling; - // Flushes the rx/tx buffers - function FlushBuffers( inBuf, outBuf: boolean ): boolean; - // Returns number of received bytes in the RX buffer - function CountRX: integer; - // Returns the output buffer free space or 65535 if not connected - function OutFreeSpace: word; - // Sends binary data - function SendData( DataPtr: pointer; DataSize: DWORD ): DWORD; - // Sends binary data. Returns number of bytes sent. Timeout overrides - // the value specifiend in the OutputTimeout property - function SendDataEx( DataPtr: pchar; DataSize, Timeout: DWORD ): DWORD; - // Sends a byte. Returns true if the byte has been sent - function SendByte( Value: byte ): boolean; - // Sends a char. Returns true if the char has been sent - function SendChar( Value: char ): boolean; - // Sends a pascal string (NULL terminated if $H+ (default)) - function SendString( s: string ): boolean; - // Sends a C-style strings (NULL terminated) - function SendZString( s: pchar ): boolean; - // Reads binary data. Returns number of bytes read - function ReadData( DataPtr: pchar; MaxDataSize: DWORD ): DWORD; - // Reads a byte. Returns true if the byte has been read - function ReadByte( var Value: byte ): boolean; - // Reads a char. Returns true if char has been read - function ReadChar( var Value: char ): boolean; - // Set DTR line high (onOff=TRUE) or low (onOff=FALSE). - // You must not use HW handshaking. - procedure ToggleDTR( onOff: boolean ); - // Set RTS line high (onOff=TRUE) or low (onOff=FALSE). - // You must not use HW handshaking. - procedure ToggleRTS( onOff: boolean ); - - // Make the Handle of the COM port public (for TAPI...) [read/write] - property Handle: HFILE read FHandle write SetHandle; - published - // # of the COM Port to use ( or pnCustom for port by name ) - property Port: TPortNumber read FPort write SetPort default pnCOM2; - // Name of COM port - property PortName: string read FPortName write SetPortName; - // Speed ( Baud Rate ) - property BaudRate: TBaudRate read FBaudRate write SetBaudRate default br9600; - // Speed ( Actual Baud Rate value ) - property BaudRateValue: DWORD read FBaudRateValue write SetBaudRateValue default 9600; - // Data bits to use (5..8, for the 8250 the use of 5 data bits with 2 stop - // bits is an invalid combination, as is 6, 7, or 8 data bits with 1.5 stop - // bits) - property DataBits: TDataBits read FDataBits write SetDataBits default db8BITS; - // Stop bits to use (1, 1.5, 2) - property StopBits: TStopBits read FStopBits write SetStopBits default sb1BITS; - // Kind of Parity to use (none,odd,even,mark,space) - property Parity: TParity read FParity write SetParity default ptNONE; - // Kind of Hardware Flow Control to use: - // hfNONE none - // hfNONERTSON no flow control but keep RTS line on - // hfRTSCTS Request-To-Send/Clear-To-Send - property HwFlow: THwFlowControl read FHwFlow write SetHwFlowControl default hfNONERTSON; - // Kind of Software Flow Control to use: - // sfNONE none - // sfXONXOFF XON/XOFF - property SwFlow: TSwFlowControl read FSwFlow write SetSwFlowControl default sfNONE; - // Input Buffer size ( suggested - driver might ignore this setting ! ) - property InBufSize: DWORD read FInBufSize write SetInBufSize default 2048; - // Output Buffer size ( suggested - driver usually ignores this setting ! ) - property OutBufSize: DWORD read FOutBufSize write SetOutBufSize default 2048; - // RX packet size ( this value must be less than InBufSize ) - // A value <= 0 means "no packet mode" ( i.e. standard mode enabled ) - property PacketSize: smallint read FPacketSize write SetPacketSize default -1; - // Timeout (ms) for a complete packet (in RX) - property PacketTimeout: integer read FPacketTimeout write SetPacketTimeout default -1; - // What to do with incomplete packets (in RX) - property PacketMode: TPacketMode read FPacketMode write FPacketMode default pmDiscard; - // ms of delay between COM port pollings - property PollingDelay: word read FPollingDelay write SetPollingDelay default 50; - // Set to TRUE to enable DTR line on connect and to leave it on until disconnect. - // Set to FALSE to disable DTR line on connect. - property EnableDTROnOpen: boolean read FEnableDTROnOpen write FEnableDTROnOpen default true; - // Output timeout (milliseconds) - property OutputTimeout: word read FOutputTimeOut write FOutputTimeout default 500; - // Input timeout (milliseconds) - property InputTimeout: DWORD read FInputTimeOut write FInputTimeout default 200; - // Set to TRUE to prevent hangs when no device connected or device is OFF - property CheckLineStatus: boolean read FCkLineStatus write FCkLineStatus default false; - // Event to raise when there is data available (input buffer has data) - // (called only if PacketSize <= 0) - property OnReceiveData: TReceiveDataEvent read FOnReceiveData write FOnReceiveData; - // Event to raise when there is data packet available (called only if PacketSize > 0) - property OnReceivePacket: TReceivePacketEvent read FOnReceivePacket write FOnReceivePacket; - end; - -function BaudRateOf( bRate: TBaudRate ): DWORD; -function DelayForRX( bRate: TBaudRate; DataSize: DWORD ): DWORD; - -implementation - -const - Win32BaudRates: array[br110..br256000] of DWORD = - ( CBR_110, CBR_300, CBR_600, CBR_1200, CBR_2400, CBR_4800, CBR_9600, - CBR_14400, CBR_19200, CBR_38400, CBR_56000, CBR_57600, CBR_115200, - CBR_128000, CBR_256000 ); - -const - dcb_Binary = $00000001; - dcb_ParityCheck = $00000002; - dcb_OutxCtsFlow = $00000004; - dcb_OutxDsrFlow = $00000008; - dcb_DtrControlMask = $00000030; - dcb_DtrControlDisable = $00000000; - dcb_DtrControlEnable = $00000010; - dcb_DtrControlHandshake = $00000020; - dcb_DsrSensivity = $00000040; - dcb_TXContinueOnXoff = $00000080; - dcb_OutX = $00000100; - dcb_InX = $00000200; - dcb_ErrorChar = $00000400; - dcb_NullStrip = $00000800; - dcb_RtsControlMask = $00003000; - dcb_RtsControlDisable = $00000000; - dcb_RtsControlEnable = $00001000; - dcb_RtsControlHandshake = $00002000; - dcb_RtsControlToggle = $00003000; - dcb_AbortOnError = $00004000; - dcb_Reserveds = $FFFF8000; - -function GetWinPlatform: string; -var ov: TOSVERSIONINFO; -begin - ov.dwOSVersionInfoSize := sizeof(ov); - if GetVersionEx( ov ) then - begin - case ov.dwPlatformId of - VER_PLATFORM_WIN32s: // Win32s on Windows 3.1 - Result := 'W32S'; - VER_PLATFORM_WIN32_WINDOWS: // Win32 on Windows 95/98 - Result := 'W95'; - VER_PLATFORM_WIN32_NT: // Windows NT - Result := 'WNT'; - end; - end - else - Result := '??'; -end; - -function GetWinVersion: DWORD; -var ov: TOSVERSIONINFO; -begin - ov.dwOSVersionInfoSize := sizeof(ov); - if GetVersionEx( ov ) then - Result := MAKELONG( ov.dwMinorVersion, ov.dwMajorVersion ) - else - Result := $00000000; -end; - -function BaudRateOf( bRate: TBaudRate ): DWORD; -begin - if bRate = brCustom then - Result := 0 - else - Result := Win32BaudRates[ bRate ]; -end; - -function DelayForRX( bRate: TBaudRate; DataSize: DWORD ): DWORD; -begin - Result := round( DataSize / (BaudRateOf(bRate) / 10) * 1000 ); -end; - -constructor TCommPortDriver.Create( AOwner: TComponent ); -begin - inherited Create( AOwner ); - // Initialize to default values ----------------------- - // not canceled - FCancel := false; - // Not connected - FHandle := INVALID_HANDLE_VALUE; - // COM 2 - FPort := pnCOM2; - FPortName := '\\.\COM2'; - // 9600 bauds - FBaudRate := br9600; - FBaudRateValue := BaudRateOf( br9600 ); - // 8 data bits - FDataBits := db8BITS; - // 1 stop bit - FStopBits := sb1BITS; - // no parity - FParity := ptNONE; - // No hardware flow control but RTS on - FHwFlow := hfNONERTSON; - // No software flow control - FSwFlow := sfNONE; - // Input buffer of 2048 bytes - FInBufSize := 2048; - // Output buffer of 2048 bytes - FOutBufSize := 2048; - // Don't pack data - FPacketSize := -1; - // Packet timeout disabled - FPacketTimeout := -1; - // Discard incomplete packets - FPacketMode := pmDiscard; - // Poll COM port every 50ms - FPollingDelay := 50; - // Output timeout of 500ms - FOutputTimeout := 500; - // Timeout for ReadData(), 200ms - FInputTimeout := 200; - // DTR high on connect - FEnableDTROnOpen := true; - // Time not valid ( used by the packing routines ) - FFirstByteOfPacketTime := DWORD(-1); - // Don't check of off-line devices - FCkLineStatus := false; - // Init number of RX polling timer pauses - not paused - FRXPollingPauses := 0; - // Temporary buffer for received data - FTempInBuffer := AllocMem( FInBufSize ); - // Allocate a window handle to catch timer's notification messages - if not (csDesigning in ComponentState) then - FNotifyWnd := AllocateHWnd( TimerWndProc ); -end; - -destructor TCommPortDriver.Destroy; -begin - // Be sure to release the COM port - Disconnect; - // Free the temporary buffer - FreeMem( FTempInBuffer, FInBufSize ); - // Destroy the timer's window - if not (csDesigning in ComponentState) then - DeallocateHWnd( FNotifyWnd ); - // Call inherited destructor - inherited Destroy; -end; - -// The COM port handle made public and writeable. -// This lets you connect to external opened com port. -// Setting ComPortHandle to INVALID_PORT_HANDLE acts as Disconnect. -procedure TCommPortDriver.SetHandle( Value: HFILE ); -begin - // If same COM port then do nothing - if FHandle = Value then - exit; - // If value is RELEASE_NOCLOSE_PORT then stop controlling the COM port - // without closing in - if Value = RELEASE_NOCLOSE_PORT then - begin - // Stop the timer - if Connected then - KillTimer( FNotifyWnd, 1 ); - // No more connected - FHandle := INVALID_HANDLE_VALUE; - end - else - begin - // Disconnect - Disconnect; - // If Value is INVALID_HANDLE_VALUE then exit now - if Value = INVALID_HANDLE_VALUE then - exit; - // Set COM port handle - FHandle := Value; - // Start the timer ( used for polling ) - SetTimer( FNotifyWnd, 1, FPollingDelay, nil ); - end; -end; - -// Selects the COM port to use -procedure TCommPortDriver.SetPort( Value: TPortNumber ); -begin - // Be sure we are not using any COM port - if Connected then - exit; - // Change COM port - FPort := Value; - // Update the port name - if FPort <> pnCustom then - FPortName := Format( '\\.\COM%d', [ord(FPort)] ); -end; - -// Sets the port name -procedure TCommPortDriver.SetPortName( Value: string ); -begin - // Be sure we are not using any COM port - if Connected then - exit; - // Change COM port - FPort := pnCustom; - // Update the port name - FPortName := Value; -end; - -// Selects the baud rate -procedure TCommPortDriver.SetBaudRate( Value: TBaudRate ); -begin - // Set new COM speed - FBaudRate := Value; - if FBaudRate <> brCustom then - FBaudRateValue := BaudRateOf( FBaudRate ); - // Apply changes - if Connected then - ApplyCOMSettings; -end; - -// Selects the baud rate ( actual baud rate value ) -procedure TCommPortDriver.SetBaudRateValue( Value: DWORD ); -begin - // Set new COM speed - FBaudRate := brCustom; - FBaudRateValue := Value; - // Apply changes - if Connected then - ApplyCOMSettings; -end; - -// Selects the number of data bits -procedure TCommPortDriver.SetDataBits( Value: TDataBits ); -begin - // Set new data bits - FDataBits := Value; - // Apply changes - if Connected then - ApplyCOMSettings; -end; - -// Selects the number of stop bits -procedure TCommPortDriver.SetStopBits( Value: TStopBits ); -begin - // Set new stop bits - FStopBits := Value; - // Apply changes - if Connected then - ApplyCOMSettings; -end; - -// Selects the kind of parity -procedure TCommPortDriver.SetParity( Value: TParity ); -begin - // Set new parity - FParity := Value; - // Apply changes - if Connected then - ApplyCOMSettings; -end; - -// Selects the kind of hardware flow control -procedure TCommPortDriver.SetHwFlowControl( Value: THwFlowControl ); -begin - // Set new hardware flow control - FHwFlow := Value; - // Apply changes - if Connected then - ApplyCOMSettings; -end; - -// Selects the kind of software flow control -procedure TCommPortDriver.SetSwFlowControl( Value: TSwFlowControl ); -begin - // Set new software flow control - FSwFlow := Value; - // Apply changes - if Connected then - ApplyCOMSettings; -end; - -// Sets the RX buffer size -procedure TCommPortDriver.SetInBufSize( Value: DWORD ); -begin - // Do nothing if connected - if Connected then - exit; - // Free the temporary input buffer - FreeMem( FTempInBuffer, FInBufSize ); - // Set new input buffer size - if Value > 8192 then - Value := 8192 - else if Value < 128 then - Value := 128; - FInBufSize := Value; - // Allocate the temporary input buffer - FTempInBuffer := AllocMem( FInBufSize ); - // Adjust the RX packet size - SetPacketSize( FPacketSize ); -end; - -// Sets the TX buffer size -procedure TCommPortDriver.SetOutBufSize( Value: DWORD ); -begin - // Do nothing if connected - if Connected then - exit; - // Set new output buffer size - if Value > 8192 then - Value := 8192 - else if Value < 128 then - Value := 128; - FOutBufSize := Value; -end; - -// Sets the size of incoming packets -procedure TCommPortDriver.SetPacketSize( Value: smallint ); -begin - // PackeSize <= 0 if data isn't to be 'packetized' - if Value <= 0 then - FPacketSize := -1 - // If the PacketSize if greater than then RX buffer size then - // increase the RX buffer size - else if DWORD(Value) > FInBufSize then - begin - FPacketSize := Value; - SetInBufSize( FPacketSize ); - end; -end; - -// Sets the timeout for incoming packets -procedure TCommPortDriver.SetPacketTimeout( Value: integer ); -begin - // PacketTimeout <= 0 if packet timeout is to be disabled - if Value < 1 then - FPacketTimeout := -1 - // PacketTimeout cannot be less than polling delay + some extra ms - else if Value < FPollingDelay then - FPacketTimeout := FPollingDelay + (FPollingDelay*40) div 100; -end; - -// Sets the delay between polling checks -procedure TCommPortDriver.SetPollingDelay( Value: word ); -begin - // Make it greater than 4 ms - if Value < 5 then - Value := 5; - // If new delay is not equal to previous value... - if Value <> FPollingDelay then - begin - // Stop the timer - if Connected then - KillTimer( FNotifyWnd, 1 ); - // Store new delay value - FPollingDelay := Value; - // Restart the timer - if Connected then - SetTimer( FNotifyWnd, 1, FPollingDelay, nil ); - // Adjust the packet timeout - SetPacketTimeout( FPacketTimeout ); - end; -end; - -// Apply COM settings -function TCommPortDriver.ApplyCOMSettings: boolean; -var dcb: TDCB; -begin - // Do nothing if not connected - Result := false; - if not Connected then - exit; - - // ** Setup DCB (Device Control Block) fields ****************************** - - // Clear all - fillchar( dcb, sizeof(dcb), 0 ); - // DCB structure size - dcb.DCBLength := sizeof(dcb); - // Baud rate - dcb.BaudRate := FBaudRateValue; - // Set fBinary: Win32 does not support non binary mode transfers - // (also disable EOF check) - dcb.Flags := dcb_Binary; - // Enables the DTR line when the device is opened and leaves it on - if EnableDTROnOpen then - dcb.Flags := dcb.Flags or dcb_DtrControlEnable; - // Kind of hw flow control to use - case FHwFlow of - // No hw flow control - hfNONE:; - // No hw flow control but set RTS high and leave it high - hfNONERTSON: - dcb.Flags := dcb.Flags or dcb_RtsControlEnable; - // RTS/CTS (request-to-send/clear-to-send) flow control - hfRTSCTS: - dcb.Flags := dcb.Flags or dcb_OutxCtsFlow or dcb_RtsControlHandshake; - end; - // Kind of sw flow control to use - case FSwFlow of - // No sw flow control - sfNONE:; - // XON/XOFF sw flow control - sfXONXOFF: - dcb.Flags := dcb.Flags or dcb_OutX or dcb_InX; - end; - // Set XONLim: specifies the minimum number of bytes allowed in the input - // buffer before the XON character is sent (or CTS is set). - if (GetWinPlatform = 'WNT') and (GetWinVersion >= $00040000) then - begin - // WinNT 4.0 + Service Pack 3 needs XONLim to be less than or - // equal to 4096 bytes. Win95/98 doesn't have such limit. - if FInBufSize div 4 > 4096 then - dcb.XONLim := 4096 - else - dcb.XONLim := FInBufSize div 4; - end - else - dcb.XONLim := FInBufSize div 4; - // Specifies the maximum number of bytes allowed in the input buffer before - // the XOFF character is sent (or CTS is set low). The maximum number of bytes - // allowed is calculated by subtracting this value from the size, in bytes, of - // the input buffer. - dcb.XOFFLim := dcb.XONLim; - // How many data bits to use - dcb.ByteSize := 5 + ord(FDataBits); - // Kind of parity to use - dcb.Parity := ord(FParity); - // How many stop bits to use - dcb.StopBits := ord(FStopbits); - // XON ASCII char - DC1, Ctrl-Q, ASCII 17 - dcb.XONChar := #17; - // XOFF ASCII char - DC3, Ctrl-S, ASCII 19 - dcb.XOFFChar := #19; - - // Apply new settings - Result := SetCommState( FHandle, dcb ); - if not Result then - exit; - // Flush buffers - Result := FlushBuffers( true, true ); - if not Result then - exit; - // Setup buffers size - Result := SetupComm( FHandle, FInBufSize, FOutBufSize ); -end; - -function TCommPortDriver.Connect: boolean; -var tms: TCOMMTIMEOUTS; -begin - // not canceled - FCancel := false; - - // Do nothing if already connected - Result := Connected; - if Result then - exit; - // Open the COM port - FHandle := CreateFile( pchar(FPortName), - GENERIC_READ or GENERIC_WRITE, - 0, // Not shared - nil, // No security attributes - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - 0 // No template - ) ; - Result := Connected; - if not Result then - exit; - // Apply settings - Result := ApplyCOMSettings; - if not Result then - begin - Disconnect; - exit; - end; - // Set ReadIntervalTimeout: Specifies the maximum time, in milliseconds, - // allowed to elapse between the arrival of two characters on the - // communications line. - // We disable timeouts because we are polling the com port! - tms.ReadIntervalTimeout := 1; - // Set ReadTotalTimeoutMultiplier: Specifies the multiplier, in milliseconds, - // used to calculate the total time-out period for read operations. - tms.ReadTotalTimeoutMultiplier := 0; - // Set ReadTotalTimeoutConstant: Specifies the constant, in milliseconds, - // used to calculate the total time-out period for read operations. - tms.ReadTotalTimeoutConstant := 1; - // Set WriteTotalTimeoutMultiplier: Specifies the multiplier, in milliseconds, - // used to calculate the total time-out period for write operations. - tms.WriteTotalTimeoutMultiplier := 0; - // Set WriteTotalTimeoutConstant: Specifies the constant, in milliseconds, - // used to calculate the total time-out period for write operations. - tms.WriteTotalTimeoutConstant := 10; - // Apply timeouts - SetCommTimeOuts( FHandle, tms ); - // Start the timer (used for polling) - SetTimer( FNotifyWnd, 1, FPollingDelay, nil ); -end; - -procedure TCommPortDriver.Disconnect; -begin - // not canceled - FCancel := true; - - - if Connected then - begin - // Stop the timer (used for polling) - KillTimer( FNotifyWnd, 1 ); - // Release the COM port - CloseHandle( FHandle ); - // No more connected - FHandle := INVALID_HANDLE_VALUE; - end; -end; - -// Returns true if connected -function TCommPortDriver.Connected: boolean; -begin - Result := FHandle <> INVALID_HANDLE_VALUE; -end; - -// Returns CTS, DSR, RING and RLSD (CD) signals status -function TCommPortDriver.GetLineStatus: TLineStatusSet; -var dwS: DWORD; -begin - Result := []; - if not Connected then - exit; - // Retrieves modem control-register values. - // The function fails if the hardware does not support the control-register - // values. - if not GetCommModemStatus( FHandle, dwS ) then - exit; - if dwS and MS_CTS_ON <> 0 then Result := Result + [lsCTS]; - if dwS and MS_DSR_ON <> 0 then Result := Result + [lsDSR]; - if dwS and MS_RING_ON <> 0 then Result := Result + [lsRING]; - if dwS and MS_RLSD_ON <> 0 then Result := Result + [lsCD]; -end; - -// Returns true if polling has not been paused -function TCommPortDriver.IsPolling: boolean; -begin - Result := FRXPollingPauses <= 0; -end; - -// Pauses polling -procedure TCommPortDriver.PausePolling; -begin - // Inc. RX polling pauses counter - inc( FRXPollingPauses ); -end; - -// Re-starts polling (after pause) -procedure TCommPortDriver.ContinuePolling; -begin - // Dec. RX polling pauses counter - dec( FRXPollingPauses ); -end; - -// Flush rx/tx buffers -function TCommPortDriver.FlushBuffers( inBuf, outBuf: boolean ): boolean; -var dwAction: DWORD; -begin - // Do nothing if not connected - Result := false; - if not Connected then - exit; - // Flush the RX data buffer - dwAction := 0; - if outBuf then - dwAction := dwAction or PURGE_TXABORT or PURGE_TXCLEAR; - // Flush the TX data buffer - if inBuf then - dwAction := dwAction or PURGE_RXABORT or PURGE_RXCLEAR; - Result := PurgeComm( FHandle, dwAction ); - // Used by the RX packet mechanism - if Result then - FFirstByteOfPacketTime := DWORD(-1); -end; - -// Returns number of received bytes in the RX buffer -function TCommPortDriver.CountRX: integer; -var stat: TCOMSTAT; - errs: DWORD; -begin - // Do nothing if port has not been opened - Result := 65535; - if not Connected then - exit; - // Get count - ClearCommError( FHandle, errs, @stat ); - Result := stat.cbInQue; -end; - -// Returns the output buffer free space or 65535 if not connected -function TCommPortDriver.OutFreeSpace: word; -var stat: TCOMSTAT; - errs: DWORD; -begin - if not Connected then - Result := 65535 - else - begin - ClearCommError( FHandle, errs, @stat ); - Result := FOutBufSize - stat.cbOutQue; - end; -end; - -// Sends binary data. Returns number of bytes sent. Timeout overrides -// the value specifiend in the OutputTimeout property -function TCommPortDriver.SendDataEx( DataPtr: pchar; DataSize, Timeout: DWORD ): DWORD; -var nToSend, nSent, t1: DWORD; -begin - // Do nothing if port has not been opened - Result := 0; - if not Connected then - exit; - // Current time - t1 := GetTickCount; - // Loop until all data sent or timeout occurred - while DataSize > 0 do - begin - // Get TX buffer free space - nToSend := OutFreeSpace; - // If output buffer has some free space... - if nToSend > 0 then - begin - // Check signals - if FCkLineStatus and (GetLineStatus = []) then - exit; - // Don't send more bytes than we actually have to send - if nToSend > DataSize then - nToSend := DataSize; - // Send - WriteFile( FHandle, DataPtr^, nToSend, nSent, nil ); - nSent := abs( nSent ); - if nSent > 0 then - begin - // Update number of bytes sent - Result := Result + nSent; - // Decrease the count of bytes to send - DataSize := DataSize - nSent; - // Inc. data pointer - DataPtr := DataPtr + nSent; - // Get current time - t1 := GetTickCount; - // Continue. This skips the time check below (don't stop - // trasmitting if the Timeout is set too low) - continue; - end; - end; - // Buffer is full. If we are waiting too long then exit - if DWORD(GetTickCount-t1) > Timeout then - exit; - end; -end; - -// Send data (breaks the data in small packets if it doesn't fit in the output -// buffer) -function TCommPortDriver.SendData( DataPtr: pointer; DataSize: DWORD ): DWORD; -begin - Result := SendDataEx( DataPtr, DataSize, FOutputTimeout ); -end; - -// Sends a byte. Returns true if the byte has been sent -function TCommPortDriver.SendByte( Value: byte ): boolean; -begin - Result := SendData( @Value, 1 ) = 1; -end; - -// Sends a char. Returns true if the char has been sent -function TCommPortDriver.SendChar( Value: char ): boolean; -begin - Result := SendData( @Value, 1 ) = 1; -end; - -// Sends a pascal string (NULL terminated if $H+ (default)) -function TCommPortDriver.SendString( s: string ): boolean; -var len: DWORD; -begin - len := length( s ); - {$IFOPT H+} // New syle pascal string (NULL terminated) - Result := SendData( pchar(s), len ) = len; - {$ELSE} // Old style pascal string (s[0] = length) - Result := SendData( pchar(@s[1]), len ) = len; - {$ENDIF} -end; - -// Sends a C-style string (NULL terminated) -function TCommPortDriver.SendZString( s: pchar ): boolean; -var len: DWORD; -begin - len := strlen( s ); - Result := SendData( s, len ) = len; -end; - -// Reads binary data. Returns number of bytes read -function TCommPortDriver.ReadData( DataPtr: pchar; MaxDataSize: DWORD ): DWORD; -var nToRead, nRead, t1: DWORD; -begin - // Do nothing if port has not been opened - Result := 0; - if not Connected then - exit; - // Pause polling - PausePolling; - // Current time - t1 := GetTickCount; - // Loop until all requested data read or timeout occurred - while MaxDataSize > 0 do - begin - Application.ProcessMessages; // ##Vg process these messages - - if FCancel then exit; - - // Get data bytes count in RX buffer - nToRead := CountRX; - // If input buffer has some data... - if nToRead > 0 then - begin - // Don't read more bytes than we actually have to read - if nToRead > MaxDataSize then - nToRead := MaxDataSize; - // Read - ReadFile( FHandle, DataPtr^, nToRead, nRead, nil ); - // Update number of bytes read - Result := Result + nRead; - // Decrease the count of bytes to read - MaxDataSize := MaxDataSize - nRead; - // Inc. data pointer - DataPtr := DataPtr + nRead; - // Get current time - t1 := GetTickCount; - // Continue. This skips the time check below (don't stop - // reading if the FInputTimeout is set too low) - continue; - end; - // Buffer is empty. If we are waiting too long then exit - if (GetTickCount-t1) > FInputTimeout then - break; - end; - // Continue polling - ContinuePolling; -end; - -// Reads a byte. Returns true if the byte has been read -function TCommPortDriver.ReadByte( var Value: byte ): boolean; -begin - Result := ReadData( @Value, 1 ) = 1; -end; - -// Reads a char. Returns true if char has been read -function TCommPortDriver.ReadChar( var Value: char ): boolean; -begin - Result := ReadData( @Value, 1 ) = 1; -end; - -// Set DTR line high (onOff=TRUE) or low (onOff=FALSE). -// You must not use HW handshaking. -procedure TCommPortDriver.ToggleDTR( onOff: boolean ); -const funcs: array[boolean] of integer = (CLRDTR,SETDTR); -begin - if Connected then - EscapeCommFunction( FHandle, funcs[onOff] ); -end; - -// Set RTS line high (onOff=TRUE) or low (onOff=FALSE). -// You must not use HW handshaking. -procedure TCommPortDriver.ToggleRTS( onOff: boolean ); -const funcs: array[boolean] of integer = (CLRRTS,SETRTS); -begin - if Connected then - EscapeCommFunction( FHandle, funcs[onOff] ); -end; - -// COM port polling proc -procedure TCommPortDriver.TimerWndProc( var msg: TMessage ); -var nRead, nToRead, dummy: DWORD; - comStat: TCOMSTAT; -begin - if (msg.Msg = WM_TIMER) and Connected then - begin - // Do nothing if RX polling has been paused - if FRXPollingPauses > 0 then - exit; - // If PacketSize is > 0 then raise the OnReceiveData event only if the RX - // buffer has at least PacketSize bytes in it. - ClearCommError( FHandle, dummy, @comStat ); - if FPacketSize > 0 then - begin - // Complete packet received ? - if DWORD(comStat.cbInQue) >= DWORD(FPacketSize) then - begin - repeat - // Read the packet and pass it to the app - nRead := 0; - if ReadFile( FHandle, FTempInBuffer^, FPacketSize, nRead, nil ) then - if (nRead <> 0) and Assigned(FOnReceivePacket) then - FOnReceivePacket( Self, FTempInBuffer, nRead ); - // Adjust time - //if comStat.cbInQue >= FPacketSize then - FFirstByteOfPacketTime := FFirstByteOfPacketTime + - DelayForRX( FBaudRate, FPacketSize ); - comStat.cbInQue := comStat.cbInQue - WORD(FPacketSize); - if comStat.cbInQue = 0 then - FFirstByteOfPacketTime := DWORD(-1); - until DWORD(comStat.cbInQue) < DWORD(FPacketSize); - // Done - exit; - end; - // Handle packet timeouts - if (FPacketTimeout > 0) and (FFirstByteOfPacketTime <> DWORD(-1)) and - (GetTickCount - FFirstByteOfPacketTime > DWORD(FPacketTimeout)) then - begin - nRead := 0; - // Read the "incomplete" packet - if ReadFile( FHandle, FTempInBuffer^, comStat.cbInQue, nRead, nil ) then - // If PacketMode is not pmDiscard then pass the packet to the app - if (FPacketMode <> pmDiscard) and (nRead <> 0) and Assigned(FOnReceivePacket) then - FOnReceivePacket( Self, FTempInBuffer, nRead ); - // Restart waiting for a packet - FFirstByteOfPacketTime := DWORD(-1); - // Done - exit; - end; - // Start time - if (comStat.cbInQue > 0) and (FFirstByteOfPacketTime = DWORD(-1)) then - FFirstByteOfPacketTime := GetTickCount; - // Done - exit; - end; - - // Standard data handling - nRead := 0; - nToRead := comStat.cbInQue; - if (nToRead > 0) and ReadFile( FHandle, FTempInBuffer^, nToRead, nRead, nil ) then - if (nRead <> 0) and Assigned(FOnReceiveData) then - FOnReceiveData( Self, FTempInBuffer, nRead ); - end - // Let Windows handle other messages - else - Msg.Result := DefWindowProc( FNotifyWnd, Msg.Msg, Msg.wParam, Msg.lParam ) ; -end; - -end. diff --git a/Host/Source/MicroBoot/interfaces/uart/CPort.inc b/Host/Source/MicroBoot/interfaces/uart/CPort.inc new file mode 100644 index 00000000..eb736695 --- /dev/null +++ b/Host/Source/MicroBoot/interfaces/uart/CPort.inc @@ -0,0 +1,227 @@ +{ ComPort Library global definitions } + +{ Fixed up for Delphi 2009 by W.Postma. } + +{$B-} +{$X+} +{$H+} + +{$IFDEF VER110} { C++ Builder 3 } + {$ObjExportAll On} + {$DEFINE VER_RECOGNIZED} +{$ENDIF} + +{$IFDEF VER120} { Delphi 4 } + {$DEFINE DELPHI_4_OR_HIGHER} + {$DEFINE DELPHI_4} + {$DEFINE VER_RECOGNIZED} +{$ENDIF} + +{$IFDEF VER125} { C++ Builder 4 } + {$DEFINE DELPHI_4_OR_HIGHER} + {$DEFINE DELPHI_4} + {$ObjExportAll On} + {$DEFINE VER_RECOGNIZED} +{$ENDIF} + +{$IFDEF VER130} { Delphi 5 and C++ Builder 5 } + {$DEFINE DELPHI_4_OR_HIGHER} + {$DEFINE DELPHI_5_OR_HIGHER} + {$DEFINE DELPHI_5} + {$IFDEF BCBNOTDELPHI} + {$ObjExportAll On} + {$ENDIF} + {$DEFINE VER_RECOGNIZED} +{$ENDIF} + +{$IFDEF VER140} { Delphi 6 and C++ Builder 6} + {$DEFINE DELPHI_4_OR_HIGHER} + {$DEFINE DELPHI_5_OR_HIGHER} + {$DEFINE DELPHI_6_OR_HIGHER} + {$DEFINE DELPHI_6} + {$IFDEF BCBNOTDELPHI} + {$ObjExportAll On} + {$ENDIF} + {$DEFINE VER_RECOGNIZED} +{$ENDIF} + +{$IFDEF VER150} { Delphi 7 } + {$DEFINE DELPHI_4_OR_HIGHER} + {$DEFINE DELPHI_5_OR_HIGHER} + {$DEFINE DELPHI_6_OR_HIGHER} + {$DEFINE DELPHI_7_OR_HIGHER} + {$DEFINE DELPHI_7} + {$IFDEF BCBNOTDELPHI} + {$ObjExportAll On} + {$ENDIF} + {$WARN UNSAFE_TYPE OFF} + {$WARN UNSAFE_CODE OFF} + {$WARN UNSAFE_CAST OFF} + {$DEFINE VER_RECOGNIZED} +{$ENDIF} + +{$IFDEF VER160} { Delphi 8 } + {$DEFINE DELPHI_4_OR_HIGHER} + {$DEFINE DELPHI_5_OR_HIGHER} + {$DEFINE DELPHI_6_OR_HIGHER} + {$DEFINE DELPHI_7_OR_HIGHER} + {$DEFINE DELPHI_8_OR_HIGHER} + {$DEFINE DELPHI_8} + {$IFDEF BCBNOTDELPHI} + {$ObjExportAll On} + {$ENDIF} + {$WARN UNSAFE_TYPE OFF} + {$WARN UNSAFE_CODE OFF} + {$WARN UNSAFE_CAST OFF} + {$DEFINE VER_RECOGNIZED} +{$ENDIF} + +{$IFDEF VER170} { Delphi 9 (2005) } + {$DEFINE DELPHI_4_OR_HIGHER} + {$DEFINE DELPHI_5_OR_HIGHER} + {$DEFINE DELPHI_6_OR_HIGHER} + {$DEFINE DELPHI_7_OR_HIGHER} + {$DEFINE DELPHI_8_OR_HIGHER} + {$DEFINE DELPHI_2005_OR_HIGHER} + {$DEFINE DELPHI_2005} + {$IFDEF BCBNOTDELPHI} + {$ObjExportAll On} + {$ENDIF} + {$WARN UNSAFE_TYPE OFF} + {$WARN UNSAFE_CODE OFF} + {$WARN UNSAFE_CAST OFF} + {$DEFINE VER_RECOGNIZED} +{$ENDIF} + +{$IFDEF VER180} { Delphi 10 (2006) } + {$DEFINE DELPHI_4_OR_HIGHER} + {$DEFINE DELPHI_5_OR_HIGHER} + {$DEFINE DELPHI_6_OR_HIGHER} + {$DEFINE DELPHI_7_OR_HIGHER} + {$DEFINE DELPHI_8_OR_HIGHER} + {$DEFINE DELPHI_2005_OR_HIGHER} + {$DEFINE DELPHI_2006_OR_HIGHER} + {$DEFINE DELPHI_2006} + {$IFDEF BCBNOTDELPHI} + {$ObjExportAll On} + {$ENDIF} + {$WARN UNSAFE_TYPE OFF} + {$WARN UNSAFE_CODE OFF} + {$WARN UNSAFE_CAST OFF} + {$DEFINE VER_RECOGNIZED} +{$ENDIF} + +{$IFDEF VER185} { Delphi 11 - 2007 } + {$DEFINE DELPHI_4_OR_HIGHER} + {$DEFINE DELPHI_5_OR_HIGHER} + {$DEFINE DELPHI_6_OR_HIGHER} + {$DEFINE DELPHI_7_OR_HIGHER} + {$DEFINE DELPHI_8_OR_HIGHER} + {$DEFINE DELPHI_2005_OR_HIGHER} + {$DEFINE DELPHI_2006_OR_HIGHER} + {$DEFINE DELPHI_2007_OR_HIGHER} + {$DEFINE DELPHI_2007} + {$WARN UNSAFE_TYPE OFF} + {$WARN UNSAFE_CODE OFF} + {$WARN UNSAFE_CAST OFF} + {$IFDEF BCB} + {$DEFINE BCB11} + {$ObjExportAll On} + {$ENDIF} + {$DEFINE VER_RECOGNIZED} +{$ENDIF} + + +{$IFDEF VER190} { Delphi 12 2008 } + {$DEFINE DELPHI_4_OR_HIGHER} + {$DEFINE DELPHI_5_OR_HIGHER} + {$DEFINE DELPHI_6_OR_HIGHER} + {$DEFINE DELPHI_7_OR_HIGHER} + {$DEFINE DELPHI_8_OR_HIGHER} + {$DEFINE DELPHI_2005_OR_HIGHER} + {$DEFINE DELPHI_2006_OR_HIGHER} + {$DEFINE DELPHI_2007_OR_HIGHER} + {$DEFINE DELPHI_2008_OR_HIGHER} + {$DEFINE DELPHI_2008} + {$DEFINE DELPHI_UNICODE} + {$IFDEF BCBNOTDELPHI} + {$ObjExportAll On} + {$ENDIF} + {$WARN UNSAFE_TYPE OFF} + {$WARN UNSAFE_CODE OFF} + {$WARN UNSAFE_CAST OFF} + {$DEFINE VER_RECOGNIZED} +{$ENDIF} + + + +{$IFDEF VER200} { Delphi 14 2009 UNICODE } + {$DEFINE DELPHI_4_OR_HIGHER} + {$DEFINE DELPHI_5_OR_HIGHER} + {$DEFINE DELPHI_6_OR_HIGHER} + {$DEFINE DELPHI_7_OR_HIGHER} + {$DEFINE DELPHI_8_OR_HIGHER} + {$DEFINE DELPHI_2005_OR_HIGHER} + {$DEFINE DELPHI_2006_OR_HIGHER} + {$DEFINE DELPHI_2007_OR_HIGHER} + {$DEFINE DELPHI_2008_OR_HIGHER} + {$DEFINE DELPHI_2009_OR_HIGHER} + {$DEFINE DELPHI_2009} + {$DEFINE DELPHI_UNICODE} + {$IFDEF BCBNOTDELPHI} + {$ObjExportAll On} + {$ENDIF} + {$WARN UNSAFE_TYPE OFF} + {$WARN UNSAFE_CODE OFF} + {$WARN UNSAFE_CAST OFF} + {$DEFINE VER_RECOGNIZED} +{$ENDIF} + + + + +{$IFDEF VER210} { Delphi 15 XE 2010 UNICODE } + {$DEFINE DELPHI_4_OR_HIGHER} + {$DEFINE DELPHI_5_OR_HIGHER} + {$DEFINE DELPHI_6_OR_HIGHER} + {$DEFINE DELPHI_7_OR_HIGHER} + {$DEFINE DELPHI_8_OR_HIGHER} + {$DEFINE DELPHI_2005_OR_HIGHER} + {$DEFINE DELPHI_2006_OR_HIGHER} + {$DEFINE DELPHI_2007_OR_HIGHER} + {$DEFINE DELPHI_2008_OR_HIGHER} + {$DEFINE DELPHI_2009_OR_HIGHER} + {$DEFINE DELPHI_2010_OR_HIGHER} + {$DEFINE DELPHI_2010} + {$DEFINE DELPHI_UNICODE} + {$IFDEF BCBNOTDELPHI} + {$ObjExportAll On} + {$ENDIF} + {$WARN UNSAFE_TYPE OFF} + {$WARN UNSAFE_CODE OFF} + {$WARN UNSAFE_CAST OFF} + {$DEFINE VER_RECOGNIZED} +{$ENDIF} + + +{... Lets try to make it work, for Delphi 2011 and later, right now...} +{$IFNDEF VER_RECOGNIZED} + {$DEFINE DELPHI_4_OR_HIGHER} + {$DEFINE DELPHI_5_OR_HIGHER} + {$DEFINE DELPHI_6_OR_HIGHER} + {$DEFINE DELPHI_7_OR_HIGHER} + {$DEFINE DELPHI_8_OR_HIGHER} + {$DEFINE DELPHI_2005_OR_HIGHER} + {$DEFINE DELPHI_2006_OR_HIGHER} + {$DEFINE DELPHI_2007_OR_HIGHER} + {$DEFINE DELPHI_2009_OR_HIGHER} + {$DEFINE DELPHI_2010_OR_HIGHER} + {$DEFINE DELPHI_UNICODE} + {$WARN UNSAFE_TYPE OFF} + {$WARN UNSAFE_CODE OFF} + {$WARN UNSAFE_CAST OFF} +{$ENDIF} + + +{$UNDEF VER_RECOGNIZED} + diff --git a/Host/Source/MicroBoot/interfaces/uart/CPort.pas b/Host/Source/MicroBoot/interfaces/uart/CPort.pas new file mode 100644 index 00000000..286cbcc1 --- /dev/null +++ b/Host/Source/MicroBoot/interfaces/uart/CPort.pas @@ -0,0 +1,3652 @@ +(****************************************************** + * ComPort Library ver. 4.11 * + * for Delphi 5, 6, 7, 2007-2010,XE and * + * C++ Builder 3, 4, 5, 6 * + * written by Dejan Crnila, 1998 - 2002 * + * maintained by Lars B. Dybdahl, 2003 * + * Homepage: http://comport.sf.net/ * + * * + * Brian Gochnauer Oct 2010 * + * Removed ansi references for backward compat * + * Made unicode ready * + *****************************************************) + + +unit CPort; +{$Warnings OFF} +{$I CPort.inc} +{$DEFINE No_Dialogs} //removes forms setup/config code +interface + +uses + Windows, Messages, Classes, SysUtils, IniFiles, Registry, Types; + +type + TComExceptions = ( CE_OpenFailed , CE_WriteFailed , + CE_ReadFailed , CE_InvalidAsync , + CE_PurgeFailed , CE_AsyncCheck , + CE_SetStateFailed , CE_TimeoutsFailed , + CE_SetupComFailed , CE_ClearComFailed , + CE_ModemStatFailed , CE_EscapeComFailed , + CE_TransmitFailed , CE_ConnChangeProp , + CE_EnumPortsFailed , CE_StoreFailed , + CE_LoadFailed , CE_RegFailed , + CE_LedStateFailed , CE_ThreadCreated , + CE_WaitFailed , CE_HasLink , + CE_RegError , CEPortNotOpen ); + + + + + // various types + TPort = string; + TBaudRate = (brCustom, br110, br300, br600, br1200, br2400, br4800, br9600, br14400, + br19200, br38400, br56000, br57600, br115200, br128000, br256000); + TStopBits = (sbOneStopBit, sbOne5StopBits, sbTwoStopBits); + TDataBits = (dbFive, dbSix, dbSeven, dbEight); + TParityBits = (prNone, prOdd, prEven, prMark, prSpace); + TDTRFlowControl = (dtrDisable, dtrEnable, dtrHandshake); + TRTSFlowControl = (rtsDisable, rtsEnable, rtsHandshake, rtsToggle); + TFlowControl = (fcHardware, fcSoftware, fcNone, fcCustom); + TComEvent = (evRxChar, evTxEmpty, evRxFlag, evRing, evBreak, evCTS, evDSR, evError, evRLSD, evRx80Full); + TComEvents = set of TComEvent; + TComSignal = (csCTS, csDSR, csRing, csRLSD); + TComSignals = set of TComSignal; + TComError = (ceFrame, ceRxParity, ceOverrun, ceBreak, ceIO, ceMode, ceRxOver, ceTxFull); + TComErrors = set of TComError; + TSyncMethod = (smThreadSync, smWindowSync, smNone); + TStoreType = (stRegistry, stIniFile); + TStoredProp = (spBasic, spFlowControl, spBuffer, spTimeouts, spParity, spOthers); + TStoredProps = set of TStoredProp; + TComLinkEvent = (leConn, leCTS, leDSR, leRLSD, leRing, leRx, leTx, leTxEmpty, leRxFlag); + TRxCharEvent = procedure(Sender: TObject; Count: Integer) of object; + TRxBufEvent = procedure(Sender: TObject; const Buffer; Count: Integer) of object; + TComErrorEvent = procedure(Sender: TObject; Errors: TComErrors) of object; + TComSignalEvent = procedure(Sender: TObject; OnOff: Boolean) of object; + TComExceptionEvent = procedure(Sender:TObject; + TComException:TComExceptions; ComportMessage:String; + WinError:Int64; WinMessage:String) of object; + + // types for asynchronous calls + TOperationKind = (okWrite, okRead); + TAsync = record + Overlapped: TOverlapped; + Kind: TOperationKind; + Data: Pointer; + Size: Integer; + end; + PAsync = ^TAsync; + + {$IFNDEF Unicode} + UnicodeString = Widestring; + {$ENDIF} + + // TComPort component and asistant classes + TCustomComPort = class; // forward declaration + + // class that links TCustomComPort events to other components + TComLink = class + private + FOnConn: TComSignalEvent; + FOnRxBuf: TRxBufEvent; + FOnTxBuf: TRxBufEvent; + FOnTxEmpty: TNotifyEvent; + FOnRxFlag: TNotifyEvent; + FOnCTSChange: TComSignalEvent; + FOnDSRChange: TComSignalEvent; + FOnRLSDChange: TComSignalEvent; + FOnRing: TNotifyEvent; + FOnTx: TComSignalEvent; + FOnRx: TComSignalEvent; + public + property OnConn: TComSignalEvent read FOnConn write FOnConn; + property OnRxBuf: TRxBufEvent read FOnRxBuf write FOnRxBuf; + property OnTxBuf: TRxBufEvent read FOnTxBuf write FOnTxBuf; + property OnTxEmpty: TNotifyEvent read FOnTxEmpty write FOnTxEmpty; + property OnRxFlag: TNotifyEvent read FOnRxFlag write FOnRxFlag; + property OnCTSChange: TComSignalEvent read FOnCTSChange write FOnCTSChange; + property OnDSRChange: TComSignalEvent read FOnDSRChange write FOnDSRChange; + property OnRLSDChange: TComSignalEvent read FOnRLSDChange write FOnRLSDChange; + property OnRing: TNotifyEvent read FOnRing write FOnRing; + property OnTx: TComSignalEvent read FOnTx write FOnTx; + property OnRx: TComSignalEvent read FOnRx write FOnRx; + end; + + // thread for background monitoring of port events + TComThread = class(TThread) + private + FComPort: TCustomComPort; + FStopEvent: THandle; + FEvents: TComEvents; + protected + procedure DispatchComMsg; + procedure DoEvents; + procedure Execute; override; + procedure SendEvents; + procedure Stop; + public + constructor Create(AComPort: TCustomComPort); + destructor Destroy; override; + end; + + // timoeout properties for read/write operations + TComTimeouts = class(TPersistent) + private + FComPort: TCustomComPort; + FReadInterval: Integer; + FReadTotalM: Integer; + FReadTotalC: Integer; + FWriteTotalM: Integer; + FWriteTotalC: Integer; + procedure SetComPort(const AComPort: TCustomComPort); + procedure SetReadInterval(const Value: Integer); + procedure SetReadTotalM(const Value: Integer); + procedure SetReadTotalC(const Value: Integer); + procedure SetWriteTotalM(const Value: Integer); + procedure SetWriteTotalC(const Value: Integer); + protected + procedure AssignTo(Dest: TPersistent); override; + public + constructor Create; + property ComPort: TCustomComPort read FComPort; + published + property ReadInterval: Integer read FReadInterval write SetReadInterval default -1; + property ReadTotalMultiplier: Integer read FReadTotalM write SetReadTotalM default 0; + property ReadTotalConstant: Integer read FReadTotalC write SetReadTotalC default 0; + property WriteTotalMultiplier: Integer + read FWriteTotalM write SetWriteTotalM default 100; + property WriteTotalConstant: Integer + read FWriteTotalC write SetWriteTotalC default 1000; + end; + + // flow control settings + TComFlowControl = class(TPersistent) + private + FComPort: TCustomComPort; + FOutCTSFlow: Boolean; + FOutDSRFlow: Boolean; + FControlDTR: TDTRFlowControl; + FControlRTS: TRTSFlowControl; + FXonXoffOut: Boolean; + FXonXoffIn: Boolean; + FDSRSensitivity: Boolean; + FTxContinueOnXoff: Boolean; + FXonChar: Char; + FXoffChar: Char; + procedure SetComPort(const AComPort: TCustomComPort); + procedure SetOutCTSFlow(const Value: Boolean); + procedure SetOutDSRFlow(const Value: Boolean); + procedure SetControlDTR(const Value: TDTRFlowControl); + procedure SetControlRTS(const Value: TRTSFlowControl); + procedure SetXonXoffOut(const Value: Boolean); + procedure SetXonXoffIn(const Value: Boolean); + procedure SetDSRSensitivity(const Value: Boolean); + procedure SetTxContinueOnXoff(const Value: Boolean); + procedure SetXonChar(const Value: Char); + procedure SetXoffChar(const Value: Char); + procedure SetFlowControl(const Value: TFlowControl); + function GetFlowControl: TFlowControl; + protected + procedure AssignTo(Dest: TPersistent); override; + public + constructor Create; + property ComPort: TCustomComPort read FComPort; + published + property FlowControl: TFlowControl read GetFlowControl write SetFlowControl stored False; + property OutCTSFlow: Boolean read FOutCTSFlow write SetOutCTSFlow; + property OutDSRFlow: Boolean read FOutDSRFlow write SetOutDSRFlow; + property ControlDTR: TDTRFlowControl read FControlDTR write SetControlDTR; + property ControlRTS: TRTSFlowControl read FControlRTS write SetControlRTS; + property XonXoffOut: Boolean read FXonXoffOut write SetXonXoffOut; + property XonXoffIn: Boolean read FXonXoffIn write SetXonXoffIn; + property DSRSensitivity: Boolean + read FDSRSensitivity write SetDSRSensitivity default False; + property TxContinueOnXoff: Boolean + read FTxContinueOnXoff write SetTxContinueOnXoff default False; + property XonChar: Char read FXonChar write SetXonChar default #17; + property XoffChar: Char read FXoffChar write SetXoffChar default #19; + end; + + // parity settings + TComParity = class(TPersistent) + private + FComPort: TCustomComPort; + FBits: TParityBits; + FCheck: Boolean; + FReplace: Boolean; + FReplaceChar: Char; + procedure SetComPort(const AComPort: TCustomComPort); + procedure SetBits(const Value: TParityBits); + procedure SetCheck(const Value: Boolean); + procedure SetReplace(const Value: Boolean); + procedure SetReplaceChar(const Value: Char); + protected + procedure AssignTo(Dest: TPersistent); override; + public + constructor Create; + property ComPort: TCustomComPort read FComPort; + published + property Bits: TParityBits read FBits write SetBits; + property Check: Boolean read FCheck write SetCheck default False; + property Replace: Boolean read FReplace write SetReplace default False; + property ReplaceChar: Char read FReplaceChar write SetReplaceChar default #0; + end; + + // buffer size settings + TComBuffer = class(TPersistent) + private + FComPort: TCustomComPort; + FInputSize: Integer; + FOutputSize: Integer; + procedure SetComPort(const AComPort: TCustomComPort); + procedure SetInputSize(const Value: Integer); + procedure SetOutputSize(const Value: Integer); + protected + procedure AssignTo(Dest: TPersistent); override; + public + constructor Create; + property ComPort: TCustomComPort read FComPort; + published + property InputSize: Integer read FInputSize write SetInputSize default 1024; + property OutputSize: Integer read FOutputSize write SetOutputSize default 1024; + end; + + // main component + TCustomComPort = class(TComponent) + private + FEventThread: TComThread; + FThreadCreated: Boolean; + FHandle: THandle; + FWindow: THandle; + FUpdateCount: Integer; + FLinks: TList; + FTriggersOnRxChar: Boolean; + FEventThreadPriority: TThreadPriority; + FHasLink: Boolean; + FConnected: Boolean; + FBaudRate: TBaudRate; + FCustomBaudRate: Integer; + FPort: TPort; + FStopBits: TStopBits; + FDataBits: TDataBits; + FDiscardNull: Boolean; + FEventChar: Char; + FEvents: TComEvents; + FBuffer: TComBuffer; + FParity: TComParity; + FTimeouts: TComTimeouts; + FFlowControl: TComFlowControl; + FSyncMethod: TSyncMethod; + FStoredProps: TStoredProps; + FOnRxChar: TRxCharEvent; + FOnRxBuf: TRxBufEvent; + FOnTxEmpty: TNotifyEvent; + FOnBreak: TNotifyEvent; + FOnRing: TNotifyEvent; + FOnCTSChange: TComSignalEvent; + FOnDSRChange: TComSignalEvent; + FOnRLSDChange: TComSignalEvent; + FOnError: TComErrorEvent; + FOnRxFlag: TNotifyEvent; + FOnAfterOpen: TNotifyEvent; + FOnAfterClose: TNotifyEvent; + FOnBeforeOpen: TNotifyEvent; + FOnBeforeClose: TNotifyEvent; + FOnRx80Full : TNotifyEvent; + FOnException :TComExceptionEvent; + FCodePage : Cardinal; + function GetTriggersOnRxChar: Boolean; + procedure SetTriggersOnRxChar(const Value: Boolean); + procedure SetConnected(const Value: Boolean); + procedure SetBaudRate(const Value: TBaudRate); + procedure SetCustomBaudRate(const Value: Integer); + procedure SetPort(const Value: TPort); + procedure SetStopBits(const Value: TStopBits); + procedure SetDataBits(const Value: TDataBits); + procedure SetDiscardNull(const Value: Boolean); + procedure SetEventChar(const Value: Char); + procedure SetSyncMethod(const Value: TSyncMethod); + procedure SetEventThreadPriority(const Value: TThreadPriority); + procedure SetParity(const Value: TComParity); + procedure SetTimeouts(const Value: TComTimeouts); + procedure SetBuffer(const Value: TComBuffer); + procedure SetFlowControl(const Value: TComFlowControl); + function HasLink: Boolean; + procedure TxNotifyLink(const Buffer; Count: Integer); + procedure NotifyLink(FLinkEvent: TComLinkEvent); + procedure SendSignalToLink(Signal: TComLinkEvent; OnOff: Boolean); + procedure CheckSignals(Open: Boolean); + procedure WindowMethod(var Message: TMessage); + procedure CallAfterOpen; + procedure CallAfterClose; + procedure CallBeforeOpen; + procedure CallBeforeClose; + procedure CallRxChar; + procedure CallTxEmpty; + procedure CallBreak; + procedure CallRing; + procedure CallRxFlag; + procedure CallCTSChange; + procedure CallDSRChange; + procedure CallError; + procedure CallRLSDChange; + procedure CallRx80Full; + procedure CallException(AnException: Word; const WinError: Int64 =0); + protected + procedure Loaded; override; + procedure DoAfterClose; dynamic; + procedure DoAfterOpen; dynamic; + procedure DoBeforeClose; dynamic; + procedure DoBeforeOpen; dynamic; + procedure DoRxChar(Count: Integer); dynamic; + procedure DoRxBuf(const Buffer; Count: Integer); dynamic; + procedure DoTxEmpty; dynamic; + procedure DoBreak; dynamic; + procedure DoRing; dynamic; + procedure DoRxFlag; dynamic; + procedure DoCTSChange(OnOff: Boolean); dynamic; + procedure DoDSRChange(OnOff: Boolean); dynamic; + procedure DoError(Errors: TComErrors); dynamic; + procedure DoRLSDChange(OnOff: Boolean); dynamic; + procedure DoRx80Full; dynamic; + procedure StoreRegistry(Reg: TRegistry); virtual; + procedure StoreIniFile(IniFile: TIniFile); virtual; + procedure LoadRegistry(Reg: TRegistry); virtual; + procedure LoadIniFile(IniFile: TIniFile); virtual; + procedure CreateHandle; virtual; + procedure DestroyHandle; virtual; + procedure ApplyDCB; dynamic; + procedure ApplyTimeouts; dynamic; + procedure ApplyBuffer; dynamic; + procedure SetupComPort; virtual; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure BeginUpdate; + procedure EndUpdate; + procedure StoreSettings(StoreType: TStoreType; StoreTo: string); + procedure LoadSettings(StoreType: TStoreType; LoadFrom: string); + procedure Open; + procedure Close; + {$IFNDEF No_Dialogs}procedure ShowSetupDialog;{$ENDIF} + function InputCount: Integer; + function OutputCount: Integer; + function Signals: TComSignals; + function StateFlags: TComStateFlags; + procedure SetDTR(OnOff: Boolean); + procedure SetRTS(OnOff: Boolean); + procedure SetXonXoff(OnOff: Boolean); + procedure SetBreak(OnOff: Boolean); + procedure ClearBuffer(Input, Output: Boolean); + function LastErrors: TComErrors; + + function Write(const Buffer; Count: Integer): Integer; + function WriteStr( Str: string): Integer; + function Read(var Buffer; Count: Integer): Integer; + function ReadStr(var Str: string; Count: Integer): Integer; + function WriteAsync(const Buffer; Count: Integer; var AsyncPtr: PAsync): Integer; + function WriteStrAsync(var Str: string; var AsyncPtr: PAsync): Integer; + function ReadAsync(var Buffer; Count: Integer; var AsyncPtr: PAsync): Integer; + function ReadStrAsync(var Str: Ansistring; Count: Integer; var AsyncPtr: PAsync): Integer; + function WriteUnicodeString(const Str: Unicodestring): Integer; + function ReadUnicodeString(var Str: UnicodeString; Count: Integer): Integer; + + function WaitForAsync(var AsyncPtr: PAsync): Integer; + function IsAsyncCompleted(AsyncPtr: PAsync): Boolean; + procedure WaitForEvent(var Events: TComEvents; StopEvent: THandle; Timeout: Integer); + procedure AbortAllAsync; + procedure TransmitChar(Ch: Char); + procedure RegisterLink(AComLink: TComLink); + procedure UnRegisterLink(AComLink: TComLink); + property Handle: THandle read FHandle; + property TriggersOnRxChar: Boolean read GetTriggersOnRxChar write SetTriggersOnRxChar; + property EventThreadPriority: TThreadPriority read FEventThreadPriority write SetEventThreadPriority; + property StoredProps: TStoredProps read FStoredProps write FStoredProps; + property Connected: Boolean read FConnected write SetConnected default False; + property BaudRate: TBaudRate read FBaudRate write SetBaudRate; + property CustomBaudRate: Integer read FCustomBaudRate write SetCustomBaudRate; + property Port: TPort read FPort write SetPort; + property Parity: TComParity read FParity write SetParity; + property StopBits: TStopBits read FStopBits write SetStopBits; + property DataBits: TDataBits read FDataBits write SetDataBits; + property DiscardNull: Boolean read FDiscardNull write SetDiscardNull default False; + property EventChar: Char read FEventChar write SetEventChar default #0; + property Events: TComEvents read FEvents write FEvents; + property Buffer: TComBuffer read FBuffer write SetBuffer; + property FlowControl: TComFlowControl read FFlowControl write SetFlowControl; + property Timeouts: TComTimeouts read FTimeouts write SetTimeouts; + property SyncMethod: TSyncMethod read FSyncMethod write SetSyncMethod default smThreadSync; + property OnAfterOpen: TNotifyEvent read FOnAfterOpen write FOnAfterOpen; + property OnAfterClose: TNotifyEvent read FOnAfterClose write FOnAfterClose; + property OnBeforeOpen: TNotifyEvent read FOnBeforeOpen write FOnBeforeOpen; + property OnBeforeClose: TNotifyEvent read FOnBeforeClose write FOnBeforeClose; + property OnRxChar: TRxCharEvent read FOnRxChar write FOnRxChar; + property OnRxBuf: TRxBufEvent read FOnRxBuf write FOnRxBuf; + property OnTxEmpty: TNotifyEvent read FOnTxEmpty write FOnTxEmpty; + property OnBreak: TNotifyEvent read FOnBreak write FOnBreak; + property OnRing: TNotifyEvent read FOnRing write FOnRing; + property OnCTSChange: TComSignalEvent read FOnCTSChange write FOnCTSChange; + property OnDSRChange: TComSignalEvent read FOnDSRChange write FOnDSRChange; + property OnRLSDChange: TComSignalEvent read FOnRLSDChange write FOnRLSDChange; + property OnRxFlag: TNotifyEvent read FOnRxFlag write FOnRxFlag; + property OnError: TComErrorEvent read FOnError write FOnError; + property OnRx80Full: TNotifyEvent read FOnRx80Full write FOnRx80Full; + property OnException: TComExceptionEvent read FOnException write FOnException; + // Translate strings between ANSI charsets + property CodePage: Cardinal read FCodePage write FCodePage default 0; + end; + + // publish the properties + TComPort = class(TCustomComPort) + property Connected; + property BaudRate; + property Port; + property Parity; + property StopBits; + property DataBits; + property DiscardNull; + property EventChar; + property Events; + property Buffer; + property FlowControl; + property Timeouts; + property StoredProps; + property TriggersOnRxChar; + property SyncMethod; + property OnAfterOpen; + property OnAfterClose; + property OnBeforeOpen; + property OnBeforeClose; + property OnRxChar; + property OnRxBuf; + property OnTxEmpty; + property OnBreak; + property OnRing; + property OnCTSChange; + property OnDSRChange; + property OnRLSDChange; + property OnRxFlag; + property OnError; + property OnRx80Full; + property OnException; + property CodePage; + end; + + TComStrEvent = procedure(Sender: TObject; const Str: string) of object; + TCustPacketEvent = procedure(Sender: TObject; const Str: string; + var Pos: Integer) of object; + + // component for reading data in packets + TComDataPacket = class(TComponent) + private + FComLink: TComLink; + FComPort: TCustomComPort; + FStartString: string; + FStopString: string; + FMaxBufferSize: Integer; + FSize: Integer; + FIncludeStrings: Boolean; + FCaseInsensitive: Boolean; + FInPacket: Boolean; + FBuffer: string; + FOnPacket: TComStrEvent; + FOnDiscard: TComStrEvent; + FOnCustomStart: TCustPacketEvent; + FOnCustomStop: TCustPacketEvent; + procedure SetComPort(const Value: TCustomComPort); + procedure SetCaseInsensitive(const Value: Boolean); + procedure SetSize(const Value: Integer); + procedure SetStartString(const Value: string); + procedure SetStopString(const Value: string); + procedure RxBuf(Sender: TObject; const Buffer; Count: Integer); + procedure CheckIncludeStrings(var Str: string); + function Upper(const Str: string): string; + procedure EmptyBuffer; + function ValidStop: Boolean; + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure DoDiscard(const Str: string); dynamic; + procedure DoPacket(const Str: string); dynamic; + procedure DoCustomStart(const Str: string; var Pos: Integer); dynamic; + procedure DoCustomStop(const Str: string; var Pos: Integer); dynamic; + procedure HandleBuffer; virtual; + property Buffer: string read FBuffer write FBuffer; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure AddData(const Str: string); + published + procedure ResetBuffer; + property ComPort: TCustomComPort read FComPort write SetComPort; + property CaseInsensitive: Boolean read FCaseInsensitive write SetCaseInsensitive default False; + property IncludeStrings: Boolean read FIncludeStrings write FIncludeStrings default False; + property MaxBufferSize: Integer read FMaxBufferSize write FMaxBufferSize default 1024; + property StartString: string read FStartString write SetStartString; + property StopString: string read FStopString write SetStopString; + property Size: Integer read FSize write SetSize default 0; + property OnDiscard: TComStrEvent read FOnDiscard write FOnDiscard; + property OnPacket: TComStrEvent read FOnPacket write FOnPacket; + property OnCustomStart: TCustPacketEvent read FOnCustomStart write FOnCustomStart; + property OnCustomStop: TCustPacketEvent read FOnCustomStop write FOnCustomStop; + end; + + // com port stream + TComStream = class(TStream) + private + FComPort: TCustomComPort; + public + constructor Create(AComPort: TCustomComPort); + function Read(var Buffer; Count: Longint): Longint; override; + function Write(const Buffer; Count: Longint): Longint; override; + function Seek(Offset: Longint; Origin: Word): Longint; override; + end; + + // exception class for ComPort Library errors + EComPort = class(Exception) + private + FWinCode: Integer; + FCode: Integer; + public + constructor Create(ACode: Integer; AWinCode: Integer); + constructor CreateNoWinCode(ACode: Integer); + property WinCode: Integer read FWinCode write FWinCode; + property Code: Integer read FCode write FCode; + end; + +// aditional procedures +procedure InitAsync(var AsyncPtr: PAsync); +procedure DoneAsync(var AsyncPtr: PAsync); +procedure EnumComPorts(Ports: TStrings); + +// conversion functions +function StrToBaudRate(Str: string): TBaudRate; +function StrToStopBits(Str: string): TStopBits; +function StrToDataBits(Str: string): TDataBits; +function StrToParity(Str: string): TParityBits; +function StrToFlowControl(Str: string): TFlowControl; +function BaudRateToStr(BaudRate: TBaudRate): string; +function StopBitsToStr(StopBits: TStopBits): string; +function DataBitsToStr(DataBits: TDataBits): string; +function ParityToStr(Parity: TParityBits): string; +function FlowControlToStr(FlowControl: TFlowControl): string; +function ComErrorsToStr(Errors:TComErrors):String; + +const + // infinite wait + WaitInfinite = Integer(INFINITE); + + // error codes + CError_OpenFailed = 1; + CError_WriteFailed = 2; + CError_ReadFailed = 3; + CError_InvalidAsync = 4; + CError_PurgeFailed = 5; + CError_AsyncCheck = 6; + CError_SetStateFailed = 7; + CError_TimeoutsFailed = 8; + CError_SetupComFailed = 9; + CError_ClearComFailed = 10; + CError_ModemStatFailed = 11; + CError_EscapeComFailed = 12; + CError_TransmitFailed = 13; + CError_ConnChangeProp = 14; + CError_EnumPortsFailed = 15; + CError_StoreFailed = 16; + CError_LoadFailed = 17; + CError_RegFailed = 18; + CError_LedStateFailed = 19; + CError_ThreadCreated = 20; + CError_WaitFailed = 21; + CError_HasLink = 22; + CError_RegError = 23; + CError_PortNotOpen = 24; + +implementation + +uses + {$IFNDEF No_Dialogs} CPortSetup, {$ENDIF} + Controls, Forms, WinSpool; + +var + // error messages + ComErrorMessages: array[1..24] of widestring; + +const + // auxilary constants used not defined in windows.pas + dcb_Binary = $00000001; + dcb_Parity = $00000002; + dcb_OutxCTSFlow = $00000004; + dcb_OutxDSRFlow = $00000008; + dcb_DTRControl = $00000030; + dcb_DSRSensivity = $00000040; + dcb_TxContinueOnXoff = $00000080; + dcb_OutX = $00000100; + dcb_InX = $00000200; + dcb_ErrorChar = $00000400; + dcb_Null = $00000800; + dcb_RTSControl = $00003000; + dcb_AbortOnError = $00004000; + + // com port window message + CM_COMPORT = WM_USER + 1; + +(***************************************** + * auxilary functions and procedures * + *****************************************) +function ComErrorsToStr(Errors:TComErrors):String; + procedure e(msg:String); + begin + if result='' then + result := msg + else + result := result+','+msg; + end; +begin + result := ''; + if ceFrame in Errors then e('Frame'); + if ceRxParity in Errors then e('Parity'); + if ceOverrun in Errors then e('Overrun'); + if ceBreak in Errors then e('Break'); + if ceIO in Errors then e('IO'); + if ceMode in Errors then e('Mode'); + if ceRxOver in Errors then e('RxOver'); + if ceTxFull in Errors then e('TxFull'); + if result = '' then + result := '' + else + result := ''; +end; + +// converts TComEvents type to Integer +function EventsToInt(const Events: TComEvents): Integer; +begin + Result := 0; + if evRxChar in Events then + Result := Result or EV_RXCHAR; + if evRxFlag in Events then + Result := Result or EV_RXFLAG; + if evTxEmpty in Events then + Result := Result or EV_TXEMPTY; + if evRing in Events then + Result := Result or EV_RING; + if evCTS in Events then + Result := Result or EV_CTS; + if evDSR in Events then + Result := Result or EV_DSR; + if evRLSD in Events then + Result := Result or EV_RLSD; + if evError in Events then + Result := Result or EV_ERR; + if evBreak in Events then + Result := Result or EV_BREAK; + if evRx80Full in Events then + Result := Result or EV_RX80FULL; +end; + +function IntToEvents(Mask: Integer): TComEvents; +begin + Result := []; + if (EV_RXCHAR and Mask) <> 0 then + Result := Result + [evRxChar]; + if (EV_TXEMPTY and Mask) <> 0 then + Result := Result + [evTxEmpty]; + if (EV_BREAK and Mask) <> 0 then + Result := Result + [evBreak]; + if (EV_RING and Mask) <> 0 then + Result := Result + [evRing]; + if (EV_CTS and Mask) <> 0 then + Result := Result + [evCTS]; + if (EV_DSR and Mask) <> 0 then + Result := Result + [evDSR]; + if (EV_RXFLAG and Mask) <> 0 then + Result := Result + [evRxFlag]; + if (EV_RLSD and Mask) <> 0 then + Result := Result + [evRLSD]; + if (EV_ERR and Mask) <> 0 then + Result := Result + [evError]; + if (EV_RX80FULL and Mask) <> 0 then + Result := Result + [evRx80Full]; +end; + +(***************************************** + * TComThread class * + *****************************************) + +// create thread +constructor TComThread.Create(AComPort: TCustomComPort); +begin + inherited Create(false); + FStopEvent := CreateEvent(nil, True, False, nil); + FComPort := AComPort; + // set thread priority + Priority := FComPort.EventThreadPriority; + // select which events are monitored + SetCommMask(FComPort.Handle, EventsToInt(FComPort.Events)); + // execute thread + //{$IFDEF Unicode}Start; {$ELSE} Resume; {$ENDIF} +end; + +// destroy thread +destructor TComThread.Destroy; +begin + Stop; + inherited Destroy; +end; + +// thread action +procedure TComThread.Execute; +var + EventHandles: array[0..1] of THandle; + Overlapped: TOverlapped; + Signaled, BytesTrans, Mask: DWORD; +begin + FillChar(Overlapped, SizeOf(Overlapped), 0); + Overlapped.hEvent := CreateEvent(nil, True, True, nil); + EventHandles[0] := FStopEvent; + EventHandles[1] := Overlapped.hEvent; + repeat + // wait for event to occur on serial port + WaitCommEvent(FComPort.Handle, Mask, @Overlapped); + Signaled := WaitForMultipleObjects(2, @EventHandles, False, INFINITE); + // if event occurs, dispatch it + if (Signaled = WAIT_OBJECT_0 + 1) + and GetOverlappedResult(FComPort.Handle, Overlapped, BytesTrans, False) + then + begin + FEvents := IntToEvents(Mask); + DispatchComMsg; + end; + until Signaled <> (WAIT_OBJECT_0 + 1); + // clear buffers + SetCommMask(FComPort.Handle, 0); + PurgeComm(FComPort.Handle, PURGE_TXCLEAR or PURGE_RXCLEAR); + CloseHandle(Overlapped.hEvent); + CloseHandle(FStopEvent); +end; + +// stop thread +procedure TComThread.Stop; +begin + SetEvent(FStopEvent); + Sleep(0); +end; + +// dispatch events +procedure TComThread.DispatchComMsg; +begin + case FComPort.SyncMethod of + smThreadSync: Synchronize(DoEvents); // call events in main thread + smWindowSync: SendEvents; // call events in thread that opened the port + smNone: DoEvents; // call events inside monitoring thread + end; +end; + +// send events to TCustomComPort component using window message +procedure TComThread.SendEvents; +begin + if evError in FEvents then + SendMessage(FComPort.FWindow, CM_COMPORT, EV_ERR, 0); + if evRxChar in FEvents then + SendMessage(FComPort.FWindow, CM_COMPORT, EV_RXCHAR, 0); + if evTxEmpty in FEvents then + SendMessage(FComPort.FWindow, CM_COMPORT, EV_TXEMPTY, 0); + if evBreak in FEvents then + SendMessage(FComPort.FWindow, CM_COMPORT, EV_BREAK, 0); + if evRing in FEvents then + SendMessage(FComPort.FWindow, CM_COMPORT, EV_RING, 0); + if evCTS in FEvents then + SendMessage(FComPort.FWindow, CM_COMPORT, EV_CTS, 0); + if evDSR in FEvents then + SendMessage(FComPort.FWindow, CM_COMPORT, EV_DSR, 0); + if evRxFlag in FEvents then + SendMessage(FComPort.FWindow, CM_COMPORT, EV_RXFLAG, 0); + if evRing in FEvents then + SendMessage(FComPort.FWindow, CM_COMPORT, EV_RLSD, 0); + if evRx80Full in FEvents then + SendMessage(FComPort.FWindow, CM_COMPORT, EV_RX80FULL, 0); +end; + +// call events +procedure TComThread.DoEvents; +begin + if evError in FEvents then + FComPort.CallError; + if evRxChar in FEvents then + FComPort.CallRxChar; + if evTxEmpty in FEvents then + FComPort.CallTxEmpty; + if evBreak in FEvents then + FComPort.CallBreak; + if evRing in FEvents then + FComPort.CallRing; + if evCTS in FEvents then + FComPort.CallCTSChange; + if evDSR in FEvents then + FComPort.CallDSRChange; + if evRxFlag in FEvents then + FComPort.CallRxFlag; + if evRLSD in FEvents then + FComPort.CallRLSDChange; + if evRx80Full in FEvents then + FComPort.CallRx80Full; +end; + +(***************************************** + * TComTimeouts class * + *****************************************) + +// create class +constructor TComTimeouts.Create; +begin + inherited Create; + FReadInterval := -1; + FWriteTotalM := 100; + FWriteTotalC := 1000; +end; + +// copy properties to other class +procedure TComTimeouts.AssignTo(Dest: TPersistent); +begin + if Dest is TComTimeouts then + begin + with TComTimeouts(Dest) do + begin + FReadInterval := Self.ReadInterval; + FReadTotalM := Self.ReadTotalMultiplier; + FReadTotalC := Self.ReadTotalConstant; + FWriteTotalM := Self.WriteTotalMultiplier; + FWriteTotalC := Self.WriteTotalConstant; + end + end + else + inherited AssignTo(Dest); +end; + +// select TCustomComPort to own this class +procedure TComTimeouts.SetComPort(const AComPort: TCustomComPort); +begin + FComPort := AComPort; +end; + +// set read interval +procedure TComTimeouts.SetReadInterval(const Value: Integer); +begin + if Value <> FReadInterval then + begin + FReadInterval := Value; + // if possible, apply the changes + if FComPort <> nil then + FComPort.ApplyTimeouts; + end; +end; + +// set read total constant +procedure TComTimeouts.SetReadTotalC(const Value: Integer); +begin + if Value <> FReadTotalC then + begin + FReadTotalC := Value; + if FComPort <> nil then + FComPort.ApplyTimeouts; + end; +end; + +// set read total multiplier +procedure TComTimeouts.SetReadTotalM(const Value: Integer); +begin + if Value <> FReadTotalM then + begin + FReadTotalM := Value; + if FComPort <> nil then + FComPort.ApplyTimeouts; + end; +end; + +// set write total constant +procedure TComTimeouts.SetWriteTotalC(const Value: Integer); +begin + if Value <> FWriteTotalC then + begin + FWriteTotalC := Value; + if FComPort <> nil then + FComPort.ApplyTimeouts; + end; +end; + +// set write total multiplier +procedure TComTimeouts.SetWriteTotalM(const Value: Integer); +begin + if Value <> FWriteTotalM then + begin + FWriteTotalM := Value; + if FComPort <> nil then + FComPort.ApplyTimeouts; + end; +end; + +(***************************************** + * TComFlowControl class * + *****************************************) + +// create class +constructor TComFlowControl.Create; +begin + inherited Create; + FXonChar := #17; + FXoffChar := #19; +end; + +// copy properties to other class +procedure TComFlowControl.AssignTo(Dest: TPersistent); +begin + if Dest is TComFlowControl then + begin + with TComFlowControl(Dest) do + begin + FOutCTSFlow := Self.OutCTSFlow; + FOutDSRFlow := Self.OutDSRFlow; + FControlDTR := Self.ControlDTR; + FControlRTS := Self.ControlRTS; + FXonXoffOut := Self.XonXoffOut; + FXonXoffIn := Self.XonXoffIn; + FTxContinueOnXoff := Self.TxContinueOnXoff; + FDSRSensitivity := Self.DSRSensitivity; + FXonChar := Self.XonChar; + FXoffChar := Self.XoffChar; + end + end + else + inherited AssignTo(Dest); +end; + +// select TCustomComPort to own this class +procedure TComFlowControl.SetComPort(const AComPort: TCustomComPort); +begin + FComPort := AComPort; +end; + +// set input flow control for DTR (data-terminal-ready) +procedure TComFlowControl.SetControlDTR(const Value: TDTRFlowControl); +begin + if Value <> FControlDTR then + begin + FControlDTR := Value; + if FComPort <> nil then + FComPort.ApplyDCB; + end; +end; + +// set input flow control for RTS (request-to-send) +procedure TComFlowControl.SetControlRTS(const Value: TRTSFlowControl); +begin + if Value <> FControlRTS then + begin + FControlRTS := Value; + if FComPort <> nil then + FComPort.ApplyDCB; + end; +end; + +// set ouput flow control for CTS (clear-to-send) +procedure TComFlowControl.SetOutCTSFlow(const Value: Boolean); +begin + if Value <> FOutCTSFlow then + begin + FOutCTSFlow := Value; + if FComPort <> nil then + FComPort.ApplyDCB; + end; +end; + +// set output flow control for DSR (data-set-ready) +procedure TComFlowControl.SetOutDSRFlow(const Value: Boolean); +begin + if Value <> FOutDSRFlow then + begin + FOutDSRFlow := Value; + if FComPort <> nil then + FComPort.ApplyDCB; + end; +end; + +// set software input flow control +procedure TComFlowControl.SetXonXoffIn(const Value: Boolean); +begin + if Value <> FXonXoffIn then + begin + FXonXoffIn := Value; + if FComPort <> nil then + FComPort.ApplyDCB; + end; +end; + +// set software ouput flow control +procedure TComFlowControl.SetXonXoffOut(const Value: Boolean); +begin + if Value <> FXonXoffOut then + begin + FXonXoffOut := Value; + if FComPort <> nil then + FComPort.ApplyDCB; + end; +end; + +// set DSR sensitivity +procedure TComFlowControl.SetDSRSensitivity(const Value: Boolean); +begin + if Value <> FDSRSensitivity then + begin + FDSRSensitivity := Value; + if FComPort <> nil then + FComPort.ApplyDCB; + end; +end; + +// set transfer continue when Xoff is sent +procedure TComFlowControl.SetTxContinueOnXoff(const Value: Boolean); +begin + if Value <> FTxContinueOnXoff then + begin + FTxContinueOnXoff := Value; + if FComPort <> nil then + FComPort.ApplyDCB; + end; +end; + +// set Xon char +procedure TComFlowControl.SetXonChar(const Value: Char); +begin + if Value <> FXonChar then + begin + FXonChar := Value; + if FComPort <> nil then + FComPort.ApplyDCB; + end; +end; + +// set Xoff char +procedure TComFlowControl.SetXoffChar(const Value: Char); +begin + if Value <> FXoffChar then + begin + FXoffChar := Value; + if FComPort <> nil then + FComPort.ApplyDCB; + end; +end; + +// get common flow control +function TComFlowControl.GetFlowControl: TFlowControl; +begin + if (FControlRTS = rtsHandshake) and (FOutCTSFlow) + and (not FXonXoffIn) and (not FXonXoffOut) + then + Result := fcHardware + else + if (FControlRTS = rtsDisable) and (not FOutCTSFlow) + and (FXonXoffIn) and (FXonXoffOut) + then + Result := fcSoftware + else + if (FControlRTS = rtsDisable) and (not FOutCTSFlow) + and (not FXonXoffIn) and (not FXonXoffOut) + then + Result := fcNone + else + Result := fcCustom; +end; + +// set common flow control +procedure TComFlowControl.SetFlowControl(const Value: TFlowControl); +begin + if Value <> fcCustom then + begin + FControlRTS := rtsDisable; + FOutCTSFlow := False; + FXonXoffIn := False; + FXonXoffOut := False; + case Value of + fcHardware: + begin + FControlRTS := rtsHandshake; + FOutCTSFlow := True; + end; + fcSoftware: + begin + FXonXoffIn := True; + FXonXoffOut := True; + end; + end; + end; + if FComPort <> nil then + FComPort.ApplyDCB; +end; + +(***************************************** + * TComParity class * + *****************************************) + +// create class +constructor TComParity.Create; +begin + inherited Create; + FBits := prNone; +end; + +// copy properties to other class +procedure TComParity.AssignTo(Dest: TPersistent); +begin + if Dest is TComParity then + begin + with TComParity(Dest) do + begin + FBits := Self.Bits; + FCheck := Self.Check; + FReplace := Self.Replace; + FReplaceChar := Self.ReplaceChar; + end + end + else + inherited AssignTo(Dest); +end; + +// select TCustomComPort to own this class +procedure TComParity.SetComPort(const AComPort: TCustomComPort); +begin + FComPort := AComPort; +end; + +// set parity bits +procedure TComParity.SetBits(const Value: TParityBits); +begin + if Value <> FBits then + begin + FBits := Value; + if FComPort <> nil then + FComPort.ApplyDCB; + end; +end; + +// set check parity +procedure TComParity.SetCheck(const Value: Boolean); +begin + if Value <> FCheck then + begin + FCheck := Value; + if FComPort <> nil then + FComPort.ApplyDCB; + end; +end; + +// set replace on parity error +procedure TComParity.SetReplace(const Value: Boolean); +begin + if Value <> FReplace then + begin + FReplace := Value; + if FComPort <> nil then + FComPort.ApplyDCB; + end; +end; + +// set replace char +procedure TComParity.SetReplaceChar(const Value: Char); +begin + if Value <> FReplaceChar then + begin + FReplaceChar := Value; + if FComPort <> nil then + FComPort.ApplyDCB; + end; +end; + +(***************************************** + * TComBuffer class * + *****************************************) + +// create class +constructor TComBuffer.Create; +begin + inherited Create; + FInputSize := 1024; + FOutputSize := 1024; +end; + +// copy properties to other class +procedure TComBuffer.AssignTo(Dest: TPersistent); +begin + if Dest is TComBuffer then + begin + with TComBuffer(Dest) do + begin + FOutputSize := Self.OutputSize; + FInputSize := Self.InputSize; + end + end + else + inherited AssignTo(Dest); +end; + +// select TCustomComPort to own this class +procedure TComBuffer.SetComPort(const AComPort: TCustomComPort); +begin + FComPort := AComPort; +end; + +// set input size +procedure TComBuffer.SetInputSize(const Value: Integer); +begin + if Value <> FInputSize then + begin + FInputSize := Value; + if (FInputSize mod 2) = 1 then + Dec(FInputSize); + if FComPort <> nil then + FComPort.ApplyBuffer; + end; +end; + +// set ouput size +procedure TComBuffer.SetOutputSize(const Value: Integer); +begin + if Value <> FOutputSize then + begin + FOutputSize := Value; + if (FOutputSize mod 2) = 1 then + Dec(FOutputSize); + if FComPort <> nil then + FComPort.ApplyBuffer; + end; +end; + +(***************************************** + * TCustomComPort component * + *****************************************) + +// create component +constructor TCustomComPort.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + // component cannot reside on inheritable forms + FComponentStyle := FComponentStyle - [csInheritable]; + FLinks := TList.Create; + FTriggersOnRxChar := True; + FEventThreadPriority := tpNormal; + FBaudRate := br9600; + FCustomBaudRate := 9600; + FPort := 'COM1'; + FStopBits := sbOneStopBit; + FDataBits := dbEight; + FEvents := [evRxChar, evTxEmpty, evRxFlag, evRing, evBreak, + evCTS, evDSR, evError, evRLSD, evRx80Full]; + FHandle := INVALID_HANDLE_VALUE; + FStoredProps := [spBasic]; + FParity := TComParity.Create; + FParity.SetComPort(Self); + FFlowControl := TComFlowControl.Create; + FFlowControl.SetComPort(Self); + FTimeouts := TComTimeouts.Create; + FTimeouts.SetComPort(Self); + FBuffer := TComBuffer.Create; + FBuffer.SetComPort(Self); + FCodePage := CP_ACP;//0; // uses default system codepage +end; + +// destroy component +destructor TCustomComPort.Destroy; +begin + Close; + FBuffer.Free; + FFlowControl.Free; + FTimeouts.Free; + FParity.Free; + inherited Destroy; + FLinks.Free; +end; + +//Handle Exceptions +procedure TCustomComPort.CallException(AnException:Word; const WinError:Int64 =0); +var winmessage:string; +begin + if Assigned(FOnException) then + begin + if WinError > 0 then //get windows error string + try Win32Check(winerror = 0); except on E:Exception do WinMessage:=e.message; end; + FOnException(self,TComExceptions(AnException),ComErrorMessages[AnException],WinError, WinMessage); + end + else + if WinError > 0 then raise EComPort.Create(AnException, WinError) + else raise EComPort.CreateNoWinCode(AnException); + +end; +// create handle to serial port +procedure TCustomComPort.CreateHandle; +begin + FHandle := CreateFile( + PChar('\\.\' + FPort), + GENERIC_READ or GENERIC_WRITE, + 0, + nil, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + 0); + + if FHandle = INVALID_HANDLE_VALUE then + //raise EComPort.Create + CallException(CError_OpenFailed, GetLastError); +end; + +// destroy serial port handle +procedure TCustomComPort.DestroyHandle; +begin + if FHandle <> INVALID_HANDLE_VALUE then + begin + if CloseHandle(FHandle) then + FHandle := INVALID_HANDLE_VALUE; + end; +end; + +procedure TCustomComPort.Loaded; +begin + inherited Loaded; + // open port if Connected is True at design-time + if FConnected and not (csDesigning in ComponentState) then + begin + FConnected := False; + try + Open; + except + Application.HandleException(Self); + end; + end; +end; + +// call events which have been dispatch using window message +procedure TCustomComPort.WindowMethod(var Message: TMessage); +begin + with Message do + if Msg = CM_COMPORT then + try + if InSendMessage then + ReplyMessage(0); + if FConnected then + case wParam of + EV_RXCHAR: CallRxChar; + EV_TXEMPTY: CallTxEmpty; + EV_BREAK: CallBreak; + EV_RING: CallRing; + EV_CTS: CallCTSChange; + EV_DSR: CallDSRChange; + EV_RXFLAG: CallRxFlag; + EV_RLSD: CallRLSDChange; + EV_ERR: CallError; + EV_RX80FULL: CallRx80Full; + end + except + Application.HandleException(Self); + end + else + Result := DefWindowProc(FWindow, Msg, wParam, lParam); +end; + +// prevent from applying changes at runtime +procedure TCustomComPort.BeginUpdate; +begin + FUpdateCount := FUpdateCount + 1; +end; + +// apply the changes made since BeginUpdate call +procedure TCustomComPort.EndUpdate; +begin + if FUpdateCount > 0 then + begin + FUpdateCount := FUpdateCount - 1; + if FUpdateCount = 0 then + SetupComPort; + end; +end; + +// open port +procedure TCustomComPort.Open; +begin + // if already connected, do nothing + if not FConnected and not (csDesigning in ComponentState) then + begin + CallBeforeOpen; + // open port + CreateHandle; + FConnected := True; + try + // initialize port + SetupComPort; + except + // error occured during initialization, destroy handle + DestroyHandle; + FConnected := False; + raise; + end; + // if at least one event is set, create special thread to monitor port + if (FEvents = []) then + FThreadCreated := False + else + begin + if (FSyncMethod = smWindowSync) then +{$IFDEF DELPHI_6_OR_HIGHER} + {$WARN SYMBOL_DEPRECATED OFF} +{$ENDIF} + FWindow := AllocateHWnd(WindowMethod); +{$IFDEF DELPHI_6_OR_HIGHER} + {$WARN SYMBOL_DEPRECATED ON} +{$ENDIF} + FEventThread := TComThread.Create(Self); + FThreadCreated := True; + end; + // port is succesfully opened, do any additional initialization + CallAfterOpen; + end; +end; + +// close port +procedure TCustomComPort.Close; +begin + // if already closed, do nothing + if FConnected and not (csDesigning in ComponentState) then + begin + CallBeforeClose; + // abort all pending operations + AbortAllAsync; + // stop monitoring for events + if FThreadCreated then + begin + FEventThread.Free; + FThreadCreated := False; + if FSyncMethod = smWindowSync then +{$IFDEF DELPHI_6_OR_HIGHER} + {$WARN SYMBOL_DEPRECATED OFF} +{$ENDIF} + DeallocateHWnd(FWindow); +{$IFDEF DELPHI_6_OR_HIGHER} + {$WARN SYMBOL_DEPRECATED ON} +{$ENDIF} + end; + // close port + DestroyHandle; + FConnected := False; + // port is closed, do any additional finalization + CallAfterClose; + end; +end; + +// apply port properties +procedure TCustomComPort.ApplyDCB; +const + CParityBits: array[TParityBits] of Integer = + (NOPARITY, ODDPARITY, EVENPARITY, MARKPARITY, SPACEPARITY); + CStopBits: array[TStopBits] of Integer = + (ONESTOPBIT, ONE5STOPBITS, TWOSTOPBITS); + CBaudRate: array[TBaudRate] of Integer = + (0, CBR_110, CBR_300, CBR_600, CBR_1200, CBR_2400, CBR_4800, CBR_9600, + CBR_14400, CBR_19200, CBR_38400, CBR_56000, CBR_57600, CBR_115200, + CBR_128000, CBR_256000); + CDataBits: array[TDataBits] of Integer = (5, 6, 7, 8); + CControlRTS: array[TRTSFlowControl] of Integer = + (RTS_CONTROL_DISABLE shl 12, + RTS_CONTROL_ENABLE shl 12, + RTS_CONTROL_HANDSHAKE shl 12, + RTS_CONTROL_TOGGLE shl 12); + CControlDTR: array[TDTRFlowControl] of Integer = + (DTR_CONTROL_DISABLE shl 4, + DTR_CONTROL_ENABLE shl 4, + DTR_CONTROL_HANDSHAKE shl 4); + +var + DCB: TDCB; + +begin + // if not connected or inside BeginUpdate/EndUpdate block, do nothing + if FConnected and (FUpdateCount = 0) and + not ((csDesigning in ComponentState) or (csLoading in ComponentState)) then + begin + DCB.DCBlength := SizeOf(TDCB); + DCB.XonLim := FBuffer.InputSize div 4; + DCB.XoffLim := DCB.XonLim; + DCB.EvtChar := AnsiChar(FEventChar); + + DCB.Flags := dcb_Binary; + if FDiscardNull then + DCB.Flags := DCB.Flags or dcb_Null; + + with FFlowControl do + begin + DCB.XonChar := AnsiChar(XonChar); + DCB.XoffChar := AnsiChar(XoffChar); + if OutCTSFlow then + DCB.Flags := DCB.Flags or dcb_OutxCTSFlow; + if OutDSRFlow then + DCB.Flags := DCB.Flags or dcb_OutxDSRFlow; + DCB.Flags := DCB.Flags or CControlDTR[ControlDTR] + or CControlRTS[ControlRTS]; + if XonXoffOut then + DCB.Flags := DCB.Flags or dcb_OutX; + if XonXoffIn then + DCB.Flags := DCB.Flags or dcb_InX; + if DSRSensitivity then + DCB.Flags := DCB.Flags or dcb_DSRSensivity; + if TxContinueOnXoff then + DCB.Flags := DCB.Flags or dcb_TxContinueOnXoff; + end; + + DCB.Parity := CParityBits[FParity.Bits]; + DCB.StopBits := CStopBits[FStopBits]; + if FBaudRate <> brCustom then + DCB.BaudRate := CBaudRate[FBaudRate] + else + DCB.BaudRate := FCustomBaudRate; + DCB.ByteSize := CDataBits[FDataBits]; + + if FParity.Check then + begin + DCB.Flags := DCB.Flags or dcb_Parity; + if FParity.Replace then + begin + DCB.Flags := DCB.Flags or dcb_ErrorChar; + DCB.ErrorChar := AnsiChar(FParity.ReplaceChar); + end; + end; + + // apply settings + if not SetCommState(FHandle, DCB) then + //raise EComPort.Create + CallException(CError_SetStateFailed, GetLastError); + end; +end; + +// apply timeout properties +procedure TCustomComPort.ApplyTimeouts; +var + Timeouts: TCommTimeouts; + + function GetTOValue(const Value: Integer): DWORD; + begin + if Value = -1 then + Result := MAXDWORD + else + Result := Value; + end; + +begin + // if not connected or inside BeginUpdate/EndUpdate block, do nothing + if FConnected and (FUpdateCount = 0) and + not ((csDesigning in ComponentState) or (csLoading in ComponentState)) then + begin + Timeouts.ReadIntervalTimeout := GetTOValue(FTimeouts.ReadInterval); + Timeouts.ReadTotalTimeoutMultiplier := GetTOValue(FTimeouts.ReadTotalMultiplier); + Timeouts.ReadTotalTimeoutConstant := GetTOValue(FTimeouts.ReadTotalConstant); + Timeouts.WriteTotalTimeoutMultiplier := GetTOValue(FTimeouts.WriteTotalMultiplier); + Timeouts.WriteTotalTimeoutConstant := GetTOValue(FTimeouts.WriteTotalConstant); + + // apply settings + if not SetCommTimeouts(FHandle, Timeouts) then + //raise EComPort.Create + CallException(CError_TimeoutsFailed, GetLastError); + end; +end; + +// apply buffers +procedure TCustomComPort.ApplyBuffer; +begin + // if not connected or inside BeginUpdate/EndUpdate block, do nothing + if FConnected and (FUpdateCount = 0) and + not ((csDesigning in ComponentState) or (csLoading in ComponentState)) + then + //apply settings + if not SetupComm(FHandle, FBuffer.InputSize, FBuffer.OutputSize) then + //raise EComPort.Create + CallException(CError_SetupComFailed, GetLastError); +end; + +// initialize port +procedure TCustomComPort.SetupComPort; +begin + ApplyBuffer; + ApplyDCB; + ApplyTimeouts; +end; + +// get number of bytes in input buffer +function TCustomComPort.InputCount: Integer; +var + Errors: DWORD; + ComStat: TComStat; +begin + if not ClearCommError(FHandle, Errors, @ComStat) then + //raise EComPort.Create + CallException(CError_ClearComFailed, GetLastError); + Result := ComStat.cbInQue; +end; + +// get number of bytes in output buffer +function TCustomComPort.OutputCount: Integer; +var + Errors: DWORD; + ComStat: TComStat; +begin + if not ClearCommError(FHandle, Errors, @ComStat) then + //raise EComPort.Create + CallException(CError_ClearComFailed, GetLastError); + Result := ComStat.cbOutQue; +end; + +// get signals which are in high state +function TCustomComPort.Signals: TComSignals; +var + Status: DWORD; +begin + if not GetCommModemStatus(FHandle, Status) then + //raise EComPort.Create + CallException(CError_ModemStatFailed, GetLastError); + Result := []; + + if (MS_CTS_ON and Status) <> 0 then + Result := Result + [csCTS]; + if (MS_DSR_ON and Status) <> 0 then + Result := Result + [csDSR]; + if (MS_RING_ON and Status) <> 0 then + Result := Result + [csRing]; + if (MS_RLSD_ON and Status) <> 0 then + Result := Result + [csRLSD]; +end; + +// get port state flags +function TCustomComPort.StateFlags: TComStateFlags; +var + Errors: DWORD; + ComStat: TComStat; +begin + if not ClearCommError(FHandle, Errors, @ComStat) then + //raise EComPort.Create + CallException(CError_ClearComFailed, GetLastError); + Result := ComStat.Flags; +end; + +// set hardware line break +procedure TCustomComPort.SetBreak(OnOff: Boolean); +var + Act: Integer; +begin + if OnOff then + Act := Windows.SETBREAK + else + Act := Windows.CLRBREAK; + + if not EscapeCommFunction(FHandle, Act) then + //raise EComPort.Create + CallException(CError_EscapeComFailed, GetLastError); +end; + +// set DTR signal +procedure TCustomComPort.SetDTR(OnOff: Boolean); +var + Act: DWORD; +begin + if OnOff then + Act := Windows.SETDTR + else + Act := Windows.CLRDTR; + + if not EscapeCommFunction(FHandle, Act) then + //raise EComPort.Create + CallException(CError_EscapeComFailed, GetLastError); +end; + +// set RTS signals +procedure TCustomComPort.SetRTS(OnOff: Boolean); +var + Act: DWORD; +begin + if OnOff then + Act := Windows.SETRTS + else + Act := Windows.CLRRTS; + + if not EscapeCommFunction(FHandle, Act) then + //raise EComPort.Create + CallException(CError_EscapeComFailed, GetLastError); +end; + +// set XonXoff state +procedure TCustomComPort.SetXonXoff(OnOff: Boolean); +var + Act: DWORD; +begin + if OnOff then + Act := Windows.SETXON + else + Act := Windows.SETXOFF; + + if not EscapeCommFunction(FHandle, Act) then + //raise EComPort.Create + CallException(CError_EscapeComFailed, GetLastError); +end; + +// clear input and/or output buffer +procedure TCustomComPort.ClearBuffer(Input, Output: Boolean); +var + Flag: DWORD; +begin + Flag := 0; + if Input then + Flag := PURGE_RXCLEAR; + if Output then + Flag := Flag or PURGE_TXCLEAR; + + if not PurgeComm(FHandle, Flag) then + //raise EComPort.Create + CallException(CError_PurgeFailed, GetLastError); +end; + +// return last errors on port +function TCustomComPort.LastErrors: TComErrors; +var + Errors: DWORD; + ComStat: TComStat; +begin + if not ClearCommError(FHandle, Errors, @ComStat) then + //raise EComPort.Create + CallException(CError_ClearComFailed, GetLastError); + Result := []; + + if (CE_FRAME and Errors) <> 0 then + Result := Result + [ceFrame]; + if ((CE_RXPARITY and Errors) <> 0) and FParity.Check then // get around a bug + Result := Result + [ceRxParity]; + if (CE_OVERRUN and Errors) <> 0 then + Result := Result + [ceOverrun]; + if (CE_RXOVER and Errors) <> 0 then + Result := Result + [ceRxOver]; + if (CE_TXFULL and Errors) <> 0 then + Result := Result + [ceTxFull]; + if (CE_BREAK and Errors) <> 0 then + Result := Result + [ceBreak]; + if (CE_IOE and Errors) <> 0 then + Result := Result + [ceIO]; + if (CE_MODE and Errors) <> 0 then + Result := Result + [ceMode]; +end; + +// prepare PAsync variable for read/write operation +procedure PrepareAsync(AKind: TOperationKind; const Buffer; Count: Integer; AsyncPtr: PAsync); +begin + with AsyncPtr^ do + begin + Kind := AKind; + if Data <> nil then + FreeMem(Data); + GetMem(Data, Count); + Move(Buffer, Data^, Count); + Size := Count; + end; +end; + +// perform asynchronous write operation +function TCustomComPort.WriteAsync(const Buffer; Count: Integer; var AsyncPtr: PAsync): Integer; +var + Success: Boolean; + BytesTrans: DWORD; +begin + if AsyncPtr = nil then + //raise EComPort.CreateNoWinCode + CallException(CError_InvalidAsync); + if FHandle = INVALID_HANDLE_VALUE then + //raise EComPort.Create + CallException(CError_PortNotOpen, -24); + PrepareAsync(okWrite, Buffer, Count, AsyncPtr); + + Success := WriteFile(FHandle, Buffer, Count, BytesTrans, @AsyncPtr^.Overlapped) + or (GetLastError = ERROR_IO_PENDING); + + if not Success then + //raise EComPort.Create + CallException(CError_WriteFailed, GetLastError); + + SendSignalToLink(leTx, True); + Result := BytesTrans; +end; + +// perform synchronous write operation +function TCustomComPort.Write(const Buffer; Count: Integer): Integer; +var + AsyncPtr: PAsync; +begin + InitAsync(AsyncPtr); + try + WriteAsync(Buffer, Count, AsyncPtr); + Result := WaitForAsync(AsyncPtr); + finally + DoneAsync(AsyncPtr); + end; +end; + +// perform asynchronous write operation +function TCustomComPort.WriteStrAsync(var Str: string; var AsyncPtr: PAsync): Integer; +var sa : Ansistring; var i:integer; +begin + if Length(Str) > 0 then + begin + setlength(sa,length(str)); + {$IFDEF Unicode} + if length(sa)>0 then + begin + for i := 1 to length(str) do sa[i] := ansichar(byte(str[i])); + move(sa[1],str[1],length(sa)); + end; + {$ENDIF} + Result := WriteAsync(Str[1], Length(Str), AsyncPtr) + end + else + Result := 0; +end; +// perform synchronous write operation +function TCustomComPort.WriteStr(Str: string): Integer; +var + AsyncPtr: PAsync; +begin + InitAsync(AsyncPtr); + try + WriteStrAsync(Str, AsyncPtr); + Result := WaitForAsync(AsyncPtr); + finally + DoneAsync(AsyncPtr); + end; +end; +//Pierre Yager - includes codepage converstion of strings being sent +function TCustomComPort.WriteUnicodeString(const Str: Unicodestring): Integer; +var + l: Integer; + rb: AnsiString; +begin + l := WideCharToMultiByte(FCodePage, 0, PWideChar(Str), Length(Str), nil, 0, nil, nil); + SetLength(rb, l); + WideCharToMultiByte(FCodePage, 0, PWideChar(Str), Length(Str), PAnsiChar(rb), l, nil, nil); + Result := WriteStr(string(rb)); +end; + +//Pierre Yager - includes codepage converstion of strings received +function TCustomComPort.ReadUnicodeString(var Str: UnicodeString; Count: Integer): Integer; +var + rb: AnsiString; + l: Integer; + AsyncPtr: PAsync; +begin + InitAsync(AsyncPtr); + try + setLength(rb,count); + Result := ReadAsync(rb[1], Count, AsyncPtr); // ReadStr(s, Count); + //{$IFDEF Unicode}rb := UTF8Encode(s);{$ELSE} rb := s; {$ENDIF} + l := MultiByteToWideChar(FCodePage, 0, PAnsiChar(rb), Length(rb), nil, 0); + SetLength(Str, l); + Result := MultiByteToWideChar(FCodePage, 0, PAnsiChar(rb), Length(rb), PWideChar(Str), l); + finally + DoneAsync(AsyncPtr); + end; +end; + +// perform asynchronous read operation +function TCustomComPort.ReadAsync(var Buffer; Count: Integer; var AsyncPtr: PAsync): Integer; +var + Success: Boolean; + BytesTrans: DWORD; +begin + if AsyncPtr = nil then + //raise EComPort.CreateNoWinCode + CallException(CError_InvalidAsync); + AsyncPtr^.Kind := okRead; + if FHandle = INVALID_HANDLE_VALUE then + //raise EComPort.Create + CallException(CError_PortNotOpen, -24); + + Success := ReadFile(FHandle, Buffer, Count, BytesTrans, @AsyncPtr^.Overlapped) + or (GetLastError = ERROR_IO_PENDING); + + if not Success then + //raise EComPort.Create + CallException(CError_ReadFailed, GetLastError); + + Result := BytesTrans; +end; + +// perform synchronous read operation +function TCustomComPort.Read(var Buffer; Count: Integer): Integer; +var + AsyncPtr: PAsync; +begin + InitAsync(AsyncPtr); + try + ReadAsync(Buffer, Count, AsyncPtr); + Result := WaitForAsync(AsyncPtr); + finally + DoneAsync(AsyncPtr); + end; +end; + +// perform asynchronous read operation +function TCustomComPort.ReadStrAsync(var Str: Ansistring; Count: Integer; var AsyncPtr: PAsync): Integer; +begin + setlength(str,count); + if Count > 0 then + Result := ReadAsync(str[1], Count, AsyncPtr) + else + Result := 0; +end; + +// perform synchronous read operation +function TCustomComPort.ReadStr(var Str: string; Count: Integer): Integer; +var + AsyncPtr: PAsync; + sa :ansistring; + i : integer; +begin + InitAsync(AsyncPtr); + try + ReadStrAsync(sa, Count, AsyncPtr); + Result := WaitForAsync(AsyncPtr); + SetLength(sa, Result); + SetLength(str, Result); + {$IFDEF Unicode} + if length(sa)>0 then + for i := 1 to length(sa) do str[i] := char(byte(sa[i])) + {$ELSE} + str := sa; + {$ENDIF} + finally + DoneAsync(AsyncPtr); + end; +end; + +function ErrorCode(AsyncPtr: PAsync): Integer; +begin + Result := 0; + case AsyncPtr^.Kind of + okWrite: Result := CError_WriteFailed; + okRead: Result := CError_ReadFailed; + end; +end; + +// wait for asynchronous operation to end +function TCustomComPort.WaitForAsync(var AsyncPtr: PAsync): Integer; +var + BytesTrans, Signaled: DWORD; + Success: Boolean; +begin + if AsyncPtr = nil then + //raise EComPort.CreateNoWinCode + CallException(CError_InvalidAsync); + + Signaled := WaitForSingleObject(AsyncPtr^.Overlapped.hEvent, INFINITE); + Success := (Signaled = WAIT_OBJECT_0) and + (GetOverlappedResult(FHandle, AsyncPtr^.Overlapped, BytesTrans, False)); + + if not Success then + //raise EComPort.Create + CallException(ErrorCode(AsyncPtr), GetLastError); + + if (AsyncPtr^.Kind = okRead) and (InputCount = 0) then + SendSignalToLink(leRx, False) + else + if AsyncPtr^.Data <> nil then + TxNotifyLink(AsyncPtr^.Data^, AsyncPtr^.Size); + + Result := BytesTrans; +end; + +// abort all asynchronous operations +procedure TCustomComPort.AbortAllAsync; +begin + if not PurgeComm(FHandle, PURGE_TXABORT or PURGE_RXABORT) then + //raise EComPort.Create + CallException(CError_PurgeFailed, GetLastError); +end; + +// detect whether asynchronous operation is completed +function TCustomComPort.IsAsyncCompleted(AsyncPtr: PAsync): Boolean; +var + BytesTrans: DWORD; +begin + if AsyncPtr = nil then + //raise EComPort.CreateNoWinCode + CallException(CError_InvalidAsync); + + Result := GetOverlappedResult(FHandle, AsyncPtr^.Overlapped, BytesTrans, False); + if not Result then + if (GetLastError <> ERROR_IO_PENDING) and (GetLastError <> ERROR_IO_INCOMPLETE) then + //raise EComPort.Create + CallException(CError_AsyncCheck, GetLastError); +end; + +// waits for event to occur on serial port +procedure TCustomComPort.WaitForEvent(var Events: TComEvents; + StopEvent: THandle; Timeout: Integer); +var + Overlapped: TOverlapped; + Mask: DWORD; + Success: Boolean; + Signaled, EventHandleCount: Integer; + EventHandles: array[0..1] of THandle; +begin + // cannot call method if event thread is running + if FThreadCreated then + //raise EComPort.CreateNoWinCode + CallException(CError_ThreadCreated); + + FillChar(Overlapped, SizeOf(TOverlapped), 0); + Overlapped.hEvent := CreateEvent(nil, True, False, nil); + EventHandles[0] := Overlapped.hEvent; + if StopEvent <> 0 then + begin + EventHandles[1] := StopEvent; + EventHandleCount := 2; + end + else + EventHandleCount := 1; + + try + SetCommMask(FHandle, EventsToInt(Events)); + // let's wait for event or timeout + Success := WaitCommEvent(FHandle, Mask, @Overlapped); + + if (Success) or (GetLastError = ERROR_IO_PENDING) then + begin + Signaled := WaitForMultipleObjects(EventHandleCount, @EventHandles, + False, Timeout); + Success := (Signaled = WAIT_OBJECT_0) + or (Signaled = WAIT_OBJECT_0 + 1) or (Signaled = WAIT_TIMEOUT); + SetCommMask(FHandle, 0); + end; + + if not Success then + //raise EComPort.Create + CallException(CError_WaitFailed, GetLastError); + + Events := IntToEvents(Mask); + finally + CloseHandle(Overlapped.hEvent); + end; +end; + +// transmit char ahead of any pending data in ouput buffer +procedure TCustomComPort.TransmitChar(Ch: Char); +begin + if not TransmitCommChar(FHandle, AnsiChar(Ch)) then + //raise EComPort.Create + CallException(CError_TransmitFailed, GetLastError); +end; + +// show port setup dialog +{$IFNDEF No_Dialogs} +procedure TCustomComPort.ShowSetupDialog; +begin + EditComPort(Self); +end; +{$ENDIF} + +// some conversion routines +function BoolToStr(const Value: Boolean): string; +begin + if Value then + Result := 'Yes' + else + Result := 'No'; +end; + +function StrToBool(const Value: string): Boolean; +begin + if UpperCase(Value) = 'YES' then + Result := True + else + Result := False; +end; + +function DTRToStr(DTRFlowControl: TDTRFlowControl): string; +const + DTRStrings: array[TDTRFlowControl] of string = ('Disable', 'Enable', + 'Handshake'); +begin + Result := DTRStrings[DTRFlowControl]; +end; + +function RTSToStr(RTSFlowControl: TRTSFlowControl): string; +const + RTSStrings: array[TRTSFlowControl] of string = ('Disable', 'Enable', + 'Handshake', 'Toggle'); +begin + Result := RTSStrings[RTSFlowControl]; +end; + +function StrToRTS(Str: string): TRTSFlowControl; +var + I: TRTSFlowControl; +begin + I := Low(TRTSFlowControl); + while (I <= High(TRTSFlowControl)) do + begin + if UpperCase(Str) = UpperCase(RTSToStr(I)) then + Break; + I := Succ(I); + end; + if I > High(TRTSFlowControl) then + Result := rtsDisable + else + Result := I; +end; + +function StrToDTR(Str: string): TDTRFlowControl; +var + I: TDTRFlowControl; +begin + I := Low(TDTRFlowControl); + while (I <= High(TDTRFlowControl)) do + begin + if UpperCase(Str) = UpperCase(DTRToStr(I)) then + Break; + I := Succ(I); + end; + if I > High(TDTRFlowControl) then + Result := dtrDisable + else + Result := I; +end; + +function StrToChar(Str: string): Char; +var + A: Integer; +begin + if Length(Str) > 0 then + begin + if (Str[1] = '#') and (Length(Str) > 1) then + begin + try + A := StrToInt(Copy(Str, 2, Length(Str) - 1)); + except + A := 0; + end; + Result := Chr(Byte(A)); + end + else + Result := Str[1]; + end + else + Result := #0; +end; + +function CharToStr(Ch: Char): string; +begin + {$IFDEF Unicode} + if CharInSet(ch,[#33..#127]) then + {$ELSE} + if Ch in [#33..#127] then {$ENDIF} + Result := Ch + else + Result := '#' + IntToStr(Ord(Ch)); +end; + +// store settings to ini file +procedure TCustomComPort.StoreIniFile(IniFile: TIniFile); +begin + if spBasic in FStoredProps then + begin + IniFile.WriteString(Name, 'Port', Port); + IniFile.WriteString(Name, 'BaudRate', BaudRateToStr(BaudRate)); + if BaudRate = brCustom then + IniFile.WriteInteger(Name, 'CustomBaudRate', CustomBaudRate); + IniFile.WriteString(Name, 'StopBits', StopBitsToStr(StopBits)); + IniFile.WriteString(Name, 'DataBits', DataBitsToStr(DataBits)); + IniFile.WriteString(Name, 'Parity', ParityToStr(Parity.Bits)); + IniFile.WriteString(Name, 'FlowControl', FlowControlToStr(FlowControl.FlowControl)); + end; + if spOthers in FStoredProps then + begin + IniFile.WriteString(Name, 'EventChar', CharToStr(EventChar)); + IniFile.WriteString(Name, 'DiscardNull', BoolToStr(DiscardNull)); + end; + if spParity in FStoredProps then + begin + IniFile.WriteString(Name, 'Parity.Check', BoolToStr(Parity.Check)); + IniFile.WriteString(Name, 'Parity.Replace', BoolToStr(Parity.Replace)); + IniFile.WriteString(Name, 'Parity.ReplaceChar', CharToStr(Parity.ReplaceChar)); + end; + if spBuffer in FStoredProps then + begin + IniFile.WriteInteger(Name, 'Buffer.OutputSize', Buffer.OutputSize); + IniFile.WriteInteger(Name, 'Buffer.InputSize', Buffer.InputSize); + end; + if spTimeouts in FStoredProps then + begin + IniFile.WriteInteger(Name, 'Timeouts.ReadInterval', Timeouts.ReadInterval); + IniFile.WriteInteger(Name, 'Timeouts.ReadTotalConstant', Timeouts.ReadTotalConstant); + IniFile.WriteInteger(Name, 'Timeouts.ReadTotalMultiplier', Timeouts.ReadTotalMultiplier); + IniFile.WriteInteger(Name, 'Timeouts.WriteTotalConstant', Timeouts.WriteTotalConstant); + IniFile.WriteInteger(Name, 'Timeouts.WriteTotalMultiplier', Timeouts.WriteTotalMultiplier); + end; + if spFlowControl in FStoredProps then + begin + IniFile.WriteString(Name, 'FlowControl.ControlRTS', RTSToStr(FlowControl.ControlRTS)); + IniFile.WriteString(Name, 'FlowControl.ControlDTR', DTRToStr(FlowControl.ControlDTR)); + IniFile.WriteString(Name, 'FlowControl.DSRSensitivity', BoolToStr(FlowControl.DSRSensitivity)); + IniFile.WriteString(Name, 'FlowControl.OutCTSFlow', BoolToStr(FlowControl.OutCTSFlow)); + IniFile.WriteString(Name, 'FlowControl.OutDSRFlow', BoolToStr(FlowControl.OutDSRFlow)); + IniFile.WriteString(Name, 'FlowControl.TxContinueOnXoff', BoolToStr(FlowControl.TxContinueOnXoff)); + IniFile.WriteString(Name, 'FlowControl.XonXoffIn', BoolToStr(FlowControl.XonXoffIn)); + IniFile.WriteString(Name, 'FlowControl.XonXoffOut', BoolToStr(FlowControl.XonXoffOut)); + IniFile.WriteString(Name, 'FlowControl.XoffChar', CharToStr(FlowControl.XoffChar)); + IniFile.WriteString(Name, 'FlowControl.XonChar', CharToStr(FlowControl.XonChar)); + end; +end; + +// store settings to registry +procedure TCustomComPort.StoreRegistry(Reg: TRegistry); +begin + if spBasic in FStoredProps then + begin + Reg.WriteString('Port', Port); + Reg.WriteString('BaudRate', BaudRateToStr(BaudRate)); + if BaudRate = brCustom then + Reg.WriteInteger('CustomBaudRate', CustomBaudRate); + Reg.WriteString('StopBits', StopBitsToStr(StopBits)); + Reg.WriteString('DataBits', DataBitsToStr(DataBits)); + Reg.WriteString('Parity', ParityToStr(Parity.Bits)); + Reg.WriteString('FlowControl', FlowControlToStr(FlowControl.FlowControl)); + end; + if spOthers in FStoredProps then + begin + Reg.WriteString('EventChar', CharToStr(EventChar)); + Reg.WriteString('DiscardNull', BoolToStr(DiscardNull)); + end; + if spParity in FStoredProps then + begin + Reg.WriteString('Parity.Check', BoolToStr(Parity.Check)); + Reg.WriteString('Parity.Replace', BoolToStr(Parity.Replace)); + Reg.WriteString('Parity.ReplaceChar', CharToStr(Parity.ReplaceChar)); + end; + if spBuffer in FStoredProps then + begin + Reg.WriteInteger('Buffer.OutputSize', Buffer.OutputSize); + Reg.WriteInteger('Buffer.InputSize', Buffer.InputSize); + end; + if spTimeouts in FStoredProps then + begin + Reg.WriteInteger('Timeouts.ReadInterval', Timeouts.ReadInterval); + Reg.WriteInteger('Timeouts.ReadTotalConstant', Timeouts.ReadTotalConstant); + Reg.WriteInteger('Timeouts.ReadTotalMultiplier', Timeouts.ReadTotalMultiplier); + Reg.WriteInteger('Timeouts.WriteTotalConstant', Timeouts.WriteTotalConstant); + Reg.WriteInteger('Timeouts.WriteTotalMultiplier', Timeouts.WriteTotalMultiplier); + end; + if spFlowControl in FStoredProps then + begin + Reg.WriteString('FlowControl.ControlRTS', RTSToStr(FlowControl.ControlRTS)); + Reg.WriteString('FlowControl.ControlDTR', DTRToStr(FlowControl.ControlDTR)); + Reg.WriteString('FlowControl.DSRSensitivity', BoolToStr(FlowControl.DSRSensitivity)); + Reg.WriteString('FlowControl.OutCTSFlow', BoolToStr(FlowControl.OutCTSFlow)); + Reg.WriteString('FlowControl.OutDSRFlow', BoolToStr(FlowControl.OutDSRFlow)); + Reg.WriteString('FlowControl.TxContinueOnXoff', BoolToStr(FlowControl.TxContinueOnXoff)); + Reg.WriteString('FlowControl.XonXoffIn', BoolToStr(FlowControl.XonXoffIn)); + Reg.WriteString('FlowControl.XonXoffOut', BoolToStr(FlowControl.XonXoffOut)); + Reg.WriteString('FlowControl.XoffChar', CharToStr(FlowControl.XoffChar)); + Reg.WriteString('FlowControl.XonChar', CharToStr(FlowControl.XonChar)); + end; +end; + +// load settings from ini file +procedure TCustomComPort.LoadIniFile(IniFile: TIniFile); +begin + if spBasic in FStoredProps then + begin + Port := IniFile.ReadString(Name, 'Port', Port); + BaudRate := StrToBaudRate(IniFile.ReadString(Name, 'BaudRate', BaudRateToStr(BaudRate))); + if BaudRate = brCustom then + CustomBaudRate := IniFile.ReadInteger(Name, 'CustomBaudRate', 9600); + StopBits := StrToStopBits(IniFile.ReadString(Name, 'StopBits', StopBitsToStr(StopBits))); + DataBits := StrToDataBits(IniFile.ReadString(Name, 'DataBits', DataBitsToStr(DataBits))); + Parity.Bits := StrToParity(IniFile.ReadString(Name, 'Parity', ParityToStr(Parity.Bits))); + FlowControl.FlowControl := StrToFlowControl( + IniFile.ReadString(Name, 'FlowControl', FlowControlToStr(FlowControl.FlowControl))); + end; + if spOthers in FStoredProps then + begin + EventChar := StrToChar(IniFile.ReadString(Name, 'EventChar', CharToStr(EventChar))); + DiscardNull := StrToBool(IniFile.ReadString(Name, 'DiscardNull', BoolToStr(DiscardNull))); + end; + if spParity in FStoredProps then + begin + Parity.Check := StrToBool(IniFile.ReadString(Name, 'Parity.Check', BoolToStr(Parity.Check))); + Parity.Replace := StrToBool(IniFile.ReadString(Name, 'Parity.Replace', BoolToStr(Parity.Replace))); + Parity.ReplaceChar := StrToChar(IniFile.ReadString(Name, 'Parity.ReplaceChar', CharToStr(Parity.ReplaceChar))); + end; + if spBuffer in FStoredProps then + begin + Buffer.OutputSize := IniFile.ReadInteger(Name, 'Buffer.OutputSize', Buffer.OutputSize); + Buffer.InputSize := IniFile.ReadInteger(Name, 'Buffer.InputSize', Buffer.InputSize); + end; + if spTimeouts in FStoredProps then + begin + Timeouts.ReadInterval := IniFile.ReadInteger(Name, 'Timeouts.ReadInterval', Timeouts.ReadInterval); + Timeouts.ReadTotalConstant := IniFile.ReadInteger(Name, 'Timeouts.ReadTotalConstant', Timeouts.ReadTotalConstant); + Timeouts.ReadTotalMultiplier := IniFile.ReadInteger(Name, 'Timeouts.ReadTotalMultiplier', Timeouts.ReadTotalMultiplier); + Timeouts.WriteTotalConstant := IniFile.ReadInteger(Name, 'Timeouts.WriteTotalConstant', Timeouts.WriteTotalConstant); + Timeouts.WriteTotalMultiplier := IniFile.ReadInteger(Name, 'Timeouts.WriteTotalMultiplier', Timeouts.WriteTotalMultiplier); + end; + if spFlowControl in FStoredProps then + begin + FlowControl.ControlRTS := StrToRTS(IniFile.ReadString(Name, 'FlowControl.ControlRTS', RTSToStr(FlowControl.ControlRTS))); + FlowControl.ControlDTR := StrToDTR(IniFile.ReadString(Name, 'FlowControl.ControlDTR', DTRToStr(FlowControl.ControlDTR))); + FlowControl.DSRSensitivity := StrToBool(IniFile.ReadString(Name, 'FlowControl.DSRSensitivity', BoolToStr(FlowControl.DSRSensitivity))); + FlowControl.OutCTSFlow := StrToBool(IniFile.ReadString(Name, 'FlowControl.OutCTSFlow', BoolToStr(FlowControl.OutCTSFlow))); + FlowControl.OutDSRFlow := StrToBool(IniFile.ReadString(Name, 'FlowControl.OutDSRFlow', BoolToStr(FlowControl.OutCTSFlow))); + FlowControl.TxContinueOnXoff := StrToBool(IniFile.ReadString(Name, 'FlowControl.TxContinueOnXoff', BoolToStr(FlowControl.TxContinueOnXoff))); + FlowControl.XonXoffIn := StrToBool(IniFile.ReadString(Name, 'FlowControl.XonXoffIn', BoolToStr(FlowControl.XonXoffIn))); + FlowControl.XonXoffOut := StrToBool(IniFile.ReadString(Name, 'FlowControl.XonXoffOut', BoolToStr(FlowControl.XonXoffOut))); + FlowControl.XoffChar := StrToChar(IniFile.ReadString(Name, 'FlowControl.XoffChar', CharToStr(FlowControl.XoffChar))); + FlowControl.XonChar := StrToChar(IniFile.ReadString(Name, 'FlowControl.XonChar', CharToStr(FlowControl.XonChar))); + end; +end; + +// load settings from registry +procedure TCustomComPort.LoadRegistry(Reg: TRegistry); +begin + if spBasic in FStoredProps then + begin + Port := Reg.ReadString('Port'); + BaudRate := StrToBaudRate(Reg.ReadString('BaudRate')); + if BaudRate = brCustom then + CustomBaudRate := Reg.ReadInteger('CustomBaudRate'); + StopBits := StrToStopBits(Reg.ReadString('StopBits')); + DataBits := StrToDataBits(Reg.ReadString('DataBits')); + Parity.Bits := StrToParity(Reg.ReadString('Parity')); + FlowControl.FlowControl := StrToFlowControl(Reg.ReadString('FlowControl')); + end; + if spOthers in FStoredProps then + begin + EventChar := StrToChar(Reg.ReadString('EventChar')); + DiscardNull := StrToBool(Reg.ReadString('DiscardNull')); + end; + if spParity in FStoredProps then + begin + Parity.Check := StrToBool(Reg.ReadString('Parity.Check')); + Parity.Replace := StrToBool(Reg.ReadString('Parity.Replace')); + Parity.ReplaceChar := StrToChar(Reg.ReadString('Parity.ReplaceChar')); + end; + if spBuffer in FStoredProps then + begin + Buffer.OutputSize := Reg.ReadInteger('Buffer.OutputSize'); + Buffer.InputSize := Reg.ReadInteger('Buffer.InputSize'); + end; + if spTimeouts in FStoredProps then + begin + Timeouts.ReadInterval := Reg.ReadInteger('Timeouts.ReadInterval'); + Timeouts.ReadTotalConstant := Reg.ReadInteger('Timeouts.ReadTotalConstant'); + Timeouts.ReadTotalMultiplier := Reg.ReadInteger('Timeouts.ReadTotalMultiplier'); + Timeouts.WriteTotalConstant := Reg.ReadInteger('Timeouts.WriteTotalConstant'); + Timeouts.WriteTotalMultiplier := Reg.ReadInteger('Timeouts.WriteTotalMultiplier'); + end; + if spFlowControl in FStoredProps then + begin + FlowControl.ControlRTS := StrToRTS(Reg.ReadString('FlowControl.ControlRTS')); + FlowControl.ControlDTR := StrToDTR(Reg.ReadString('FlowControl.ControlDTR')); + FlowControl.DSRSensitivity := StrToBool(Reg.ReadString('FlowControl.DSRSensitivity')); + FlowControl.OutCTSFlow := StrToBool(Reg.ReadString('FlowControl.OutCTSFlow')); + FlowControl.OutDSRFlow := StrToBool(Reg.ReadString('FlowControl.OutDSRFlow')); + FlowControl.TxContinueOnXoff := StrToBool(Reg.ReadString('FlowControl.TxContinueOnXoff')); + FlowControl.XonXoffIn := StrToBool(Reg.ReadString('FlowControl.XonXoffIn')); + FlowControl.XonXoffOut := StrToBool(Reg.ReadString('FlowControl.XonXoffOut')); + FlowControl.XoffChar := StrToChar(Reg.ReadString('FlowControl.XoffChar')); + FlowControl.XonChar := StrToChar(Reg.ReadString('FlowControl.XonChar')); + end; +end; + +// initialize registry +procedure SetRegistry(Reg: TRegistry; Key: string; Name: string); +var + I: Integer; + Temp: string; +begin + I := Pos('\', Key); + if I > 0 then + begin + Temp := Copy(Key, 1, I - 1); + if UpperCase(Temp) = 'HKEY_LOCAL_MACHINE' then + Reg.RootKey := HKEY_LOCAL_MACHINE + else + if UpperCase(Temp) = 'HKEY_CURRENT_USER' then + Reg.RootKey := HKEY_CURRENT_USER; + Key := Copy(Key, I + 1, Length(Key) - I); + if Key[Length(Key)] <> '\' then + Key := Key + '\'; + Key := Key + Name; + Reg.OpenKey(Key, True); + end; +end; + +// store settings +procedure TCustomComPort.StoreSettings(StoreType: TStoreType; StoreTo: string); +var + IniFile: TIniFile; + Reg: TRegistry; +begin + try + if StoreType = stRegistry then + begin + Reg := TRegistry.Create; + try + SetRegistry(Reg, StoreTo, Name); + StoreRegistry(Reg); + finally + Reg.Free; + end + end else + begin + IniFile := TIniFile.Create(StoreTo); + try + StoreIniFile(IniFile); + finally + IniFile.Free; + end + end; + except + //raise EComPort.CreateNoWinCode + CallException(CError_StoreFailed); + end; +end; + +// load settings +procedure TCustomComPort.LoadSettings(StoreType: TStoreType; LoadFrom: string); +var + IniFile: TIniFile; + Reg: TRegistry; +begin + BeginUpdate; + try + try + if StoreType = stRegistry then + begin + Reg := TRegistry.Create; + try + SetRegistry(Reg, LoadFrom, Name); + LoadRegistry(Reg); + finally + Reg.Free; + end + end else + begin + IniFile := TIniFile.Create(LoadFrom); + try + LoadIniFile(IniFile); + finally + IniFile.Free; + end + end; + finally + EndUpdate; + end; + except + //raise EComPort.CreateNoWinCode + CallException(CError_LoadFailed); + end; +end; + +// register link from other component to TCustomComPort +procedure TCustomComPort.RegisterLink(AComLink: TComLink); +begin + if FLinks.IndexOf(Pointer(AComLink)) > -1 then + //raise EComPort.CreateNoWinCode + CallException(CError_RegFailed) + else + FLinks.Add(Pointer(AComLink)); + FHasLink := HasLink; +end; + +// unregister link from other component to TCustomComPort +procedure TCustomComPort.UnRegisterLink(AComLink: TComLink); +begin + if FLinks.IndexOf(Pointer(AComLink)) = -1 then + //raise EComPort.CreateNoWinCode + CallException(CError_RegFailed) + else + FLinks.Remove(Pointer(AComLink)); + FHasLink := HasLink; +end; + +// default actions on port events + +procedure TCustomComPort.DoBeforeClose; +begin + if Assigned(FOnBeforeClose) then + FOnBeforeClose(Self); +end; + +procedure TCustomComPort.DoBeforeOpen; +begin + if Assigned(FOnBeforeOpen) then + FOnBeforeOpen(Self); +end; + +procedure TCustomComPort.DoAfterOpen; +begin + if Assigned(FOnAfterOpen) then + FOnAfterOpen(Self); +end; + +procedure TCustomComPort.DoAfterClose; +begin + if Assigned(FOnAfterClose) then + FOnAfterClose(Self); +end; + +procedure TCustomComPort.DoRxChar(Count: Integer); +begin + if Assigned(FOnRxChar) then + FOnRxChar(Self, Count); +end; + +procedure TCustomComPort.DoRxBuf(const Buffer; Count: Integer); +begin + if Assigned(FOnRxBuf) then + FOnRxBuf(Self, Buffer, Count); +end; + +procedure TCustomComPort.DoBreak; +begin + if Assigned(FOnBreak) then + FOnBreak(Self); +end; + +procedure TCustomComPort.DoTxEmpty; +begin + if Assigned(FOnTxEmpty) + then FOnTxEmpty(Self); +end; + +procedure TCustomComPort.DoRing; +begin + if Assigned(FOnRing) then + FOnRing(Self); +end; + +procedure TCustomComPort.DoCTSChange(OnOff: Boolean); +begin + if Assigned(FOnCTSChange) then + FOnCTSChange(Self, OnOff); +end; + +procedure TCustomComPort.DoDSRChange(OnOff: Boolean); +begin + if Assigned(FOnDSRChange) then + FOnDSRChange(Self, OnOff); +end; + +procedure TCustomComPort.DoRLSDChange(OnOff: Boolean); +begin + if Assigned(FOnRLSDChange) then + FOnRLSDChange(Self, OnOff); +end; + +procedure TCustomComPort.DoError(Errors: TComErrors); +begin + if Assigned(FOnError) then + FOnError(Self, Errors); +end; + +procedure TCustomComPort.DoRxFlag; +begin + if Assigned(FOnRxFlag) then + FOnRxFlag(Self); +end; + +procedure TCustomComPort.DoRx80Full; +begin + if Assigned(FOnRx80Full) then + FOnRx80Full(Self); +end; + +// set signals to false on close, and to proper value on open, +// because OnXChange events are not called automatically +procedure TCustomComPort.CheckSignals(Open: Boolean); +begin + if Open then + begin + CallCTSChange; + CallDSRChange; + CallRLSDChange; + end else + begin + SendSignalToLink(leCTS, False); + SendSignalToLink(leDSR, False); + SendSignalToLink(leRLSD, False); + DoCTSChange(False); + DoDSRChange(False); + DoRLSDChange(False); + end; +end; + +// called in response to EV_X events, except CallXClose, CallXOpen + +procedure TCustomComPort.CallAfterClose; +begin + SendSignalToLink(leConn, False); + DoAfterClose; +end; + +procedure TCustomComPort.CallAfterOpen; +begin + SendSignalToLink(leConn, True); + DoAfterOpen; + CheckSignals(True); +end; + +procedure TCustomComPort.CallBeforeClose; +begin + // shutdown com signals manually + CheckSignals(False); + DoBeforeClose; +end; + +procedure TCustomComPort.CallBeforeOpen; +begin + DoBeforeOpen; +end; + +procedure TCustomComPort.CallBreak; +begin + DoBreak; +end; + +procedure TCustomComPort.CallCTSChange; +var + OnOff: Boolean; +begin + OnOff := csCTS in Signals; + // check for linked components + SendSignalToLink(leCTS, OnOff); + DoCTSChange(OnOff); +end; + +procedure TCustomComPort.CallDSRChange; +var + OnOff: Boolean; +begin + OnOff := csDSR in Signals; + // check for linked components + SendSignalToLink(leDSR, OnOff); + DoDSRChange(OnOff); +end; + +procedure TCustomComPort.CallRLSDChange; +var + OnOff: Boolean; +begin + OnOff := csRLSD in Signals; + // check for linked components + SendSignalToLink(leRLSD, OnOff); + DoRLSDChange(OnOff); +end; + +procedure TCustomComPort.CallError; +var + Errors: TComErrors; +begin + Errors := LastErrors; + if Errors <> [] then + DoError(Errors); +end; + +procedure TCustomComPort.CallRing; +begin + NotifyLink(leRing); + DoRing; +end; + +procedure TCustomComPort.CallRx80Full; +begin + DoRx80Full; +end; + +procedure TCustomComPort.CallRxChar; +var + Count: Integer; + + // read from input buffer + procedure PerformRead(var P: Pointer); + begin + GetMem(P, Count); + Read(P^, Count); + // call OnRxBuf event + DoRxBuf(P^, Count); + end; + + // check if any component is linked, to OnRxChar event + procedure CheckLinks; + {$WARNINGS OFF} + var + I: Integer; + P: Pointer; + ComLink: TComLink; + ReadFromBuffer: Boolean; + begin + // examine links + if (Count > 0) and (not TriggersOnRxChar) then + begin + ReadFromBuffer := False; + try + // cycle through links + for I := 0 to FLinks.Count - 1 do + begin + ComLink := TComLink(FLinks[I]); + if Assigned(ComLink.OnRxBuf) then + begin + // link to OnRxChar event found + if not ReadFromBuffer then + begin + // TCustomComPort must read from comport, so OnRxChar event is + // not triggered + ReadFromBuffer := True; + PerformRead(P); + end; + // send data to linked component + ComLink.OnRxBuf(Self, P^, Count); + end + end; + if (not ReadFromBuffer) and (not FTriggersOnRxChar) then + begin + ReadFromBuffer := True; + PerformRead(P); + end; + finally + if ReadFromBuffer then + begin + FreeMem(P); + // data is already out of buffer, prevent from OnRxChar event to occur + Count := 0; + end; + end; + end; + end; + +begin + Count := InputCount; + if Count > 0 then + SendSignalToLink(leRx, True); + CheckLinks; + if Count > 0 then + DoRxChar(Count); +end; + +procedure TCustomComPort.CallRxFlag; +begin + NotifyLink(leRxFlag); + DoRxFlag; +end; + +procedure TCustomComPort.CallTxEmpty; +begin + SendSignalToLink(leTx, False); + NotifyLink(leTxEmpty); + DoTxEmpty; +end; + +// returns true if it has least one component linked to OnRxBuf event +function TCustomComPort.HasLink: Boolean; +var + I: Integer; + ComLink: TComLink; +begin + Result := False; + // examine links + if FLinks.Count > 0 then + for I := 0 to FLinks.Count - 1 do + begin + ComLink := TComLink(FLinks[I]); + if Assigned(ComLink.OnRxBuf) then + Result := True; + end; +end; + +// send TxBuf notify to link +procedure TCustomComPort.TxNotifyLink(const Buffer; Count: Integer); +var + I: Integer; + ComLink: TComLink; +begin + if (FLinks.Count > 0) then + for I := 0 to FLinks.Count - 1 do + begin + ComLink := TComLink(FLinks[I]); + if Assigned(ComLink.OnTxBuf) then + ComLink.OnTxBuf(Self, Buffer, Count); + end; +end; + +// send event notification to link +procedure TCustomComPort.NotifyLink(FLinkEvent: TComLinkEvent); +var + I: Integer; + ComLink: TComLink; + Event: TNotifyEvent; +begin + if (FLinks.Count > 0) then + for I := 0 to FLinks.Count - 1 do + begin + ComLink := TComLink(FLinks[I]); + Event := nil; + case FLinkEvent of + leRing: Event := ComLink.OnRing; + leTxEmpty: Event := ComLink.OnTxEmpty; + leRxFlag: Event := ComLink.OnRxFlag; + end; + if Assigned(Event) then + Event(Self); + end; +end; + +// send signal to linked components +procedure TCustomComPort.SendSignalToLink(Signal: TComLinkEvent; OnOff: Boolean); +var + I: Integer; + ComLink: TComLink; + SignalEvent: TComSignalEvent; +begin + if (FLinks.Count > 0) then + // cycle through links + for I := 0 to FLinks.Count - 1 do + begin + ComLink := TComLink(FLinks[I]); + SignalEvent := nil; + case Signal of + leCTS: SignalEvent := ComLink.OnCTSChange; + leDSR: SignalEvent := ComLink.OnDSRChange; + leRLSD: SignalEvent := ComLink.OnRLSDChange; + leTx: SignalEvent := ComLink.OnTx; + leRx: SignalEvent := ComLink.OnRx; + leConn: SignalEvent := ComLink.OnConn; + end; + // if linked, trigger event + if Assigned(SignalEvent) then + SignalEvent(Self, OnOff); + end; +end; + +// set connected property, same as Open/Close methods +procedure TCustomComPort.SetConnected(const Value: Boolean); +begin + if not ((csDesigning in ComponentState) or (csLoading in ComponentState)) then + begin + if Value <> FConnected then + if Value then + Open + else + Close; + end + else + FConnected := Value; +end; + +// set baud rate +procedure TCustomComPort.SetBaudRate(const Value: TBaudRate); +begin + if Value <> FBaudRate then + begin + FBaudRate := Value; + // if possible, apply settings + ApplyDCB; + end; +end; + +// set custom baud rate +procedure TCustomComPort.SetCustomBaudRate(const Value: Integer); +begin + if Value <> FCustomBaudRate then + begin + FCustomBaudRate := Value; + ApplyDCB; + end; +end; + +// set data bits +procedure TCustomComPort.SetDataBits(const Value: TDataBits); +begin + if Value <> FDataBits then + begin + FDataBits := Value; + ApplyDCB; + end; +end; + +// set discard null characters +procedure TCustomComPort.SetDiscardNull(const Value: Boolean); +begin + if Value <> FDiscardNull then + begin + FDiscardNull := Value; + ApplyDCB; + end; +end; + +// set event characters +procedure TCustomComPort.SetEventChar(const Value: Char); +begin + if Value <> FEventChar then + begin + FEventChar := Value; + ApplyDCB; + end; +end; + +// set port +procedure TCustomComPort.SetPort(const Value: TPort); +begin + // 11.1.2001 Ch. Kaufmann; removed function ComString, because there can be com ports + // with names other than COMn. + if Value <> FPort then + begin + FPort := Value; + if FConnected and not ((csDesigning in ComponentState) or + (csLoading in ComponentState)) then + begin + Close; + Open; + end; + end; +end; + +// set stop bits +procedure TCustomComPort.SetStopBits(const Value: TStopBits); +begin + if Value <> FStopBits then + begin + FStopBits := Value; + ApplyDCB; + end; +end; + +// set event synchronization method +procedure TCustomComPort.SetSyncMethod(const Value: TSyncMethod); +begin + if Value <> FSyncMethod then + begin + if FConnected and not ((csDesigning in ComponentState) or + (csLoading in ComponentState)) + then + //raise EComPort.CreateNoWinCode + CallException(CError_ConnChangeProp) + else + FSyncMethod := Value; + end; +end; + +// sets RxChar triggering +procedure TCustomComPort.SetTriggersOnRxChar(const Value: Boolean); +begin + if FHasLink then + //raise EComPort.CreateNoWinCode + CallException(CError_HasLink); + FTriggersOnRxChar := Value; +end; + +// sets event thread priority +procedure TCustomComPort.SetEventThreadPriority(const Value: TThreadPriority); +begin + if Value <> FEventThreadPriority then + begin + if FConnected and not ((csDesigning in ComponentState) or + (csLoading in ComponentState)) + then + //raise EComPort.CreateNoWinCode + CallException(CError_ConnChangeProp) + else + FEventThreadPriority := Value; + end; +end; + +// returns true if RxChar is triggered when data arrives input buffer +function TCustomComPort.GetTriggersOnRxChar: Boolean; +begin + Result := FTriggersOnRxChar and (not FHasLink); +end; + +// set flow control +procedure TCustomComPort.SetFlowControl(const Value: TComFlowControl); +begin + FFlowControl.Assign(Value); + ApplyDCB; +end; + +// set parity +procedure TCustomComPort.SetParity(const Value: TComParity); +begin + FParity.Assign(Value); + ApplyDCB; +end; + +// set timeouts +procedure TCustomComPort.SetTimeouts(const Value: TComTimeouts); +begin + FTimeouts.Assign(Value); + ApplyTimeouts; +end; + +// set buffer +procedure TCustomComPort.SetBuffer(const Value: TComBuffer); +begin + FBuffer.Assign(Value); + ApplyBuffer; +end; + +(***************************************** + * TComDataPacket component * + *****************************************) + +// create component +constructor TComDataPacket.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FComLink := TComLink.Create; + FComLink.OnRxBuf := RxBuf; + FMaxBufferSize := 1024; +end; + +// destroy component +destructor TComDataPacket.Destroy; +begin + ComPort := nil; + FComLink.Free; + inherited Destroy; +end; + +// add custom data to packet buffer +procedure TComDataPacket.AddData(const Str: string); +begin + if ValidStop then + begin + Buffer := Buffer + Str; + HandleBuffer; + end + else + DoPacket(Str); +end; + +// remove ComPort property if being destroyed +procedure TComDataPacket.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if (AComponent = FComPort) and (Operation = opRemove) then + ComPort := nil; +end; + +// call OnDiscard +procedure TComDataPacket.DoDiscard(const Str: string); +begin + if Assigned(FOnDiscard) then + FOnDiscard(Self, Str); +end; + +// call OnPacket +procedure TComDataPacket.DoPacket(const Str: string); +begin + if Assigned(FOnPacket) then + FOnPacket(Self, Str); +end; + +// call OnCustomStart +procedure TComDataPacket.DoCustomStart(const Str: string; + var Pos: Integer); +begin + if Assigned(FOnCustomStart) then + FOnCustomStart(Self, Str, Pos); +end; + +// call OnCustomStop +procedure TComDataPacket.DoCustomStop(const Str: string; var Pos: Integer); +begin + if Assigned(FOnCustomStop) then + FOnCustomStop(Self, Str, Pos); +end; + +// discard start and stop strings +procedure TComDataPacket.CheckIncludeStrings(var Str: string); +var + LenStart, LenStop: Integer; +begin + if FIncludeStrings then + Exit; + LenStart := Length(FStartString); + LenStop := Length(FStopString); + // remove start string + if Pos(Upper(FStartString), Upper(Str)) = 1 then + Str := Copy(Str, LenStart + 1, Length(Str) - LenStart); + // remove stop string + if Pos(Upper(FStopString), Upper(Str)) = (Length(Str) - LenStop + 1) then + Str := Copy(Str, 1, Length(Str) - LenStop); +end; + +// upper case +function TComDataPacket.Upper(const Str: string): string; +begin + if FCaseInsensitive then + Result := UpperCase(Str) + else + Result := Str; +end; + +// split buffer in packets +procedure TComDataPacket.HandleBuffer; + + procedure DiscardPacketToPos(Pos: Integer); + var + Str: string; + begin + FInPacket := True; + if Pos > 1 then + begin + Str := Copy(Buffer, 1, Pos - 1); // some discarded data + Buffer := Copy(Buffer, Pos, Length(Buffer) - Pos + 1); + DoDiscard(Str); + end; + end; + + procedure FormPacket(CutSize: Integer); + var + Str: string; + begin + Str := Copy(Buffer, 1, CutSize); + Buffer := Copy(Buffer, CutSize + 1, Length(Buffer) - CutSize); + CheckIncludeStrings(Str); + DoPacket(Str); + end; + + procedure StartPacket; + var + Found: Integer; + begin + // check for custom start condition + Found := -1; + DoCustomStart(Buffer, Found); + if Found > 0 then + DiscardPacketToPos(Found); + if Found = -1 then + begin + if Length(FStartString) > 0 then // start string valid + begin + Found := Pos(Upper(FStartString), Upper(Buffer)); + if Found > 0 then + DiscardPacketToPos(Found); + end + else + FInPacket := True; + end; + end; + + procedure EndPacket; + var + Found, CutSize, Len: Integer; + begin + // check for custom stop condition + Found := -1; + DoCustomStop(Buffer, Found); + if Found > 0 then + begin + // custom stop condition detected + CutSize := Found; + FInPacket := False; + end + else + if Found = -1 then + begin + Len := Length(Buffer); + if (FSize > 0) and (Len >= FSize) then + begin + // size stop condition detected + FInPacket := False; + CutSize := FSize; + end + else + begin + Len := Length(FStartString); + Found := Pos(Upper(FStopString), + Upper(Copy(Buffer, Len + 1, Length(Buffer) - Len))); + if Found > 0 then + begin + // stop string stop condition detected + CutSize := Found + Length(FStopString) + Len - 1; + FInPacket := False; + end; + end; + end; + if not FInPacket then + FormPacket(CutSize); // create packet + end; + + function IsBufferTooLarge: Boolean; + begin + Result := (Length(Buffer) >= FMaxBufferSize) and (FMaxBufferSize > 0); + end; + +begin + try + if not FInPacket then + StartPacket; + if FInPacket then + begin + EndPacket; + if not FInPacket then + HandleBuffer; + end; + finally + if IsBufferTooLarge then + EmptyBuffer; + end; +end; + +// is stop condition valid? +function TComDataPacket.ValidStop: Boolean; +begin + Result := (FSize > 0) or (Length(FStopString) > 0) + or (Assigned(FOnCustomStop)); +end; + +// receive data +procedure TComDataPacket.ResetBuffer; +begin + EmptyBuffer; +end; + +procedure TComDataPacket.RxBuf(Sender: TObject; const Buffer; Count: Integer); +var sa:AnsiString; Str: string; + i:integer; +begin + SetLength(Str, Count); + SetLength(Sa, Count); + Move(Buffer, Sa[1], Count); + {$IFDEF Unicode} + if length(sa)>0 then + for i := 1 to length(sa) do str[i] := char(byte(sa[i])); + {$ELSE} str := sa; {$ENDIF} + AddData(Str); +end; + +// empty buffer +procedure TComDataPacket.EmptyBuffer; +begin + if Buffer <> '' then + begin + try + DoDiscard(Buffer); + finally + Buffer := ''; + FInPacket := False; + end; + end; +end; + +// set com port +procedure TComDataPacket.SetComPort(const Value: TCustomComPort); +begin + if Value <> FComPort then + begin + if FComPort <> nil then + FComPort.UnRegisterLink(FComLink); + FComPort := Value; + if FComPort <> nil then + begin + FComPort.FreeNotification(Self); + FComPort.RegisterLink(FComLink); + end; + end; +end; + +// set case sensitivity +procedure TComDataPacket.SetCaseInsensitive(const Value: Boolean); +begin + if FCaseInsensitive <> Value then + begin + FCaseInsensitive := Value; + if not (csLoading in ComponentState) then + EmptyBuffer; + end; +end; + +// set packet size +procedure TComDataPacket.SetSize(const Value: Integer); +begin + if FSize <> Value then + begin + FSize := Value; + if not (csLoading in ComponentState) then + EmptyBuffer; + end; +end; + +// set start string +procedure TComDataPacket.SetStartString(const Value: string); +begin + if FStartString <> Value then + begin + FStartString := Value; + if not (csLoading in ComponentState) then + EmptyBuffer; + end; +end; + +// set stop string +procedure TComDataPacket.SetStopString(const Value: string); +begin + if FStopString <> Value then + begin + FStopString := Value; + if not (csLoading in ComponentState) then + EmptyBuffer; + end; +end; + +(***************************************** + * EComPort exception * + *****************************************) + +// create stream +constructor TComStream.Create(AComPort: TCustomComPort); +begin + inherited Create; + FComPort := AComPort; +end; + +// read from stream +function TComStream.Read(var Buffer; Count: Integer): Longint; +begin + FComPort.Read(Buffer, Count); +end; + +// write to stream +function TComStream.Write(const Buffer; Count: Integer): Longint; +begin + FComPort.Write(Buffer, Count); +end; + +// seek always to 0 +function TComStream.Seek(Offset: Integer; Origin: Word): Longint; +begin + Result := 0; +end; + +(***************************************** + * EComPort exception * + *****************************************) + +// create exception with windows error code +constructor EComPort.Create(ACode: Integer; AWinCode: Integer); +begin + FWinCode := AWinCode; + FCode := ACode; + inherited CreateFmt(ComErrorMessages[ACode] + ' (Error: %d)', [AWinCode]); +end; + +// create exception +constructor EComPort.CreateNoWinCode(ACode: Integer); +begin + FWinCode := -1; + FCode := ACode; + inherited Create(ComErrorMessages[ACode]); +end; + +(***************************************** + * other procedures/functions * + *****************************************) + +// initialization of PAsync variables used in asynchronous calls +procedure InitAsync(var AsyncPtr: PAsync); +begin + New(AsyncPtr); + with AsyncPtr^ do + begin + FillChar(Overlapped, SizeOf(TOverlapped), 0); + Overlapped.hEvent := CreateEvent(nil, True, True, nil); + Data := nil; + Size := 0; + end; +end; + +// clean-up of PAsync variable +procedure DoneAsync(var AsyncPtr: PAsync); +begin + with AsyncPtr^ do + begin + CloseHandle(Overlapped.hEvent); + if Data <> nil then + FreeMem(Data); + end; + Dispose(AsyncPtr); + AsyncPtr := nil; +end; + +procedure EnumComPorts(Ports: TStrings); +var + KeyHandle: HKEY; + ErrCode, Index: Integer; + ValueName, Data: string; + ValueLen, DataLen, ValueType: DWORD; + TmpPorts: TStringList; +begin + ErrCode := RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + 'HARDWARE\DEVICEMAP\SERIALCOMM', + 0, + KEY_READ, + KeyHandle); + + if ErrCode <> ERROR_SUCCESS then + begin + //raise EComPort.Create(CError_RegError, ErrCode); + exit; + end; + + TmpPorts := TStringList.Create; + try + Index := 0; + repeat + ValueLen := 256; + DataLen := 256; + SetLength(ValueName, ValueLen); + SetLength(Data, DataLen); + ErrCode := RegEnumValue( + KeyHandle, + Index, + PChar(ValueName), + {$IFDEF DELPHI_4_OR_HIGHER} + Cardinal(ValueLen), + {$ELSE} + ValueLen, + {$ENDIF} + nil, + @ValueType, + PByte(PChar(Data)), + @DataLen); + + if ErrCode = ERROR_SUCCESS then + begin + SetLength(Data, DataLen - 1); + TmpPorts.Add(Data); + Inc(Index); + end + else + if ErrCode <> ERROR_NO_MORE_ITEMS then break; + //raise EComPort.Create(CError_RegError, ErrCode); + + until (ErrCode <> ERROR_SUCCESS) ; + + TmpPorts.Sort; + Ports.Assign(TmpPorts); + finally + RegCloseKey(KeyHandle); + TmpPorts.Free; + end; + +end; + +// string to baud rate +function StrToBaudRate(Str: string): TBaudRate; +var + I: TBaudRate; +begin + I := Low(TBaudRate); + while (I <= High(TBaudRate)) do + begin + if UpperCase(Str) = UpperCase(BaudRateToStr(TBaudRate(I))) then + Break; + I := Succ(I); + end; + if I > High(TBaudRate) then + Result := br9600 + else + Result := I; +end; + +// string to stop bits +function StrToStopBits(Str: string): TStopBits; +var + I: TStopBits; +begin + I := Low(TStopBits); + while (I <= High(TStopBits)) do + begin + if UpperCase(Str) = UpperCase(StopBitsToStr(TStopBits(I))) then + Break; + I := Succ(I); + end; + if I > High(TStopBits) then + Result := sbOneStopBit + else + Result := I; +end; + +// string to data bits +function StrToDataBits(Str: string): TDataBits; +var + I: TDataBits; +begin + I := Low(TDataBits); + while (I <= High(TDataBits)) do + begin + if UpperCase(Str) = UpperCase(DataBitsToStr(I)) then + Break; + I := Succ(I); + end; + if I > High(TDataBits) then + Result := dbEight + else + Result := I; +end; + +// string to parity +function StrToParity(Str: string): TParityBits; +var + I: TParityBits; +begin + I := Low(TParityBits); + while (I <= High(TParityBits)) do + begin + if UpperCase(Str) = UpperCase(ParityToStr(I)) then + Break; + I := Succ(I); + end; + if I > High(TParityBits) then + Result := prNone + else + Result := I; +end; + +// string to flow control +function StrToFlowControl(Str: string): TFlowControl; +var + I: TFlowControl; +begin + I := Low(TFlowControl); + while (I <= High(TFlowControl)) do + begin + if UpperCase(Str) = UpperCase(FlowControlToStr(I)) then + Break; + I := Succ(I); + end; + if I > High(TFlowControl) then + Result := fcCustom + else + Result := I; +end; + +// baud rate to string +function BaudRateToStr(BaudRate: TBaudRate): string; +const + BaudRateStrings: array[TBaudRate] of string = ('Custom', '110', '300', '600', + '1200', '2400', '4800', '9600', '14400', '19200', '38400', '56000', '57600', + '115200', '128000', '256000'); +begin + Result := BaudRateStrings[BaudRate]; +end; + +// stop bits to string +function StopBitsToStr(StopBits: TStopBits): string; +const + StopBitsStrings: array[TStopBits] of string = ('1', '1.5', '2'); +begin + Result := StopBitsStrings[StopBits]; +end; + +// data bits to string +function DataBitsToStr(DataBits: TDataBits): string; +const + DataBitsStrings: array[TDataBits] of string = ('5', '6', '7', '8'); +begin + Result := DataBitsStrings[DataBits]; +end; + +// parity to string +function ParityToStr(Parity: TParityBits): string; +const + ParityBitsStrings: array[TParityBits] of string = ('None', 'Odd', 'Even', + 'Mark', 'Space'); +begin + Result := ParityBitsStrings[Parity]; +end; + +// flow control to string +function FlowControlToStr(FlowControl: TFlowControl): string; +const + FlowControlStrings: array[TFlowControl] of string = ('Hardware', + 'Software', 'None', 'Custom'); +begin + Result := FlowControlStrings[FlowControl]; +end; + +initialization + ComErrorMessages[1]:='Unable to open com port'; + ComErrorMessages[2]:='WriteFile function failed'; + ComErrorMessages[3]:='ReadFile function failed'; + ComErrorMessages[4]:='Invalid Async parameter'; + ComErrorMessages[5]:='PurgeComm function failed'; + ComErrorMessages[6]:='Unable to get async status'; + ComErrorMessages[7]:='SetCommState function failed'; + ComErrorMessages[8]:='SetCommTimeouts failed'; + ComErrorMessages[9]:='SetupComm function failed'; + ComErrorMessages[10]:='ClearCommError function failed'; + ComErrorMessages[11]:='GetCommModemStatus function failed'; + ComErrorMessages[12]:='EscapeCommFunction function failed'; + ComErrorMessages[13]:='TransmitCommChar function failed'; + ComErrorMessages[14]:='Cannot set property while connected'; + ComErrorMessages[15]:='EnumPorts function failed'; + ComErrorMessages[16]:='Failed to store settings'; + ComErrorMessages[17]:='Failed to load settings'; + ComErrorMessages[18]:='Link (un)registration failed'; + ComErrorMessages[19]:='Cannot change led state if ComPort is selected'; + ComErrorMessages[20]:='Cannot wait for event if event thread is created'; + ComErrorMessages[21]:='WaitForEvent method failed'; + ComErrorMessages[22]:='A component is linked to OnRxBuf event'; + ComErrorMessages[23]:='Registry error'; + ComErrorMessages[24]:='Port Not Open';// CError_PortNotOpen + + +end. diff --git a/Host/Source/MicroBoot/interfaces/uart/XcpSettings.dfm b/Host/Source/MicroBoot/interfaces/uart/XcpSettings.dfm index 5afe5dc3..67620e7d 100644 Binary files a/Host/Source/MicroBoot/interfaces/uart/XcpSettings.dfm and b/Host/Source/MicroBoot/interfaces/uart/XcpSettings.dfm differ diff --git a/Host/Source/MicroBoot/interfaces/uart/XcpSettings.pas b/Host/Source/MicroBoot/interfaces/uart/XcpSettings.pas index 9867bf5b..f2d34ab6 100644 --- a/Host/Source/MicroBoot/interfaces/uart/XcpSettings.pas +++ b/Host/Source/MicroBoot/interfaces/uart/XcpSettings.pas @@ -36,7 +36,7 @@ interface //*************************************************************************************** uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, - StdCtrls, ComCtrls, ExtCtrls, IniFiles; + StdCtrls, ComCtrls, ExtCtrls, IniFiles, Vcl.Imaging.pngimage; //*************************************************************************************** diff --git a/Host/Source/MicroBoot/interfaces/uart/XcpTransport.pas b/Host/Source/MicroBoot/interfaces/uart/XcpTransport.pas index ec5e3b33..2f7222d2 100644 --- a/Host/Source/MicroBoot/interfaces/uart/XcpTransport.pas +++ b/Host/Source/MicroBoot/interfaces/uart/XcpTransport.pas @@ -36,7 +36,7 @@ interface // Includes //*************************************************************************************** uses - Windows, Messages, SysUtils, Classes, Forms, CPDrv, IniFiles; + Windows, Messages, SysUtils, Classes, Forms, CPort, IniFiles; //*************************************************************************************** @@ -54,7 +54,7 @@ type public packetData : array[0..kMaxPacketSize-1] of Byte; packetLen : Word; - sciDriver : TCommPortDriver; + sciDriver : TComPort; constructor Create; procedure Configure(iniFile : string); function Connect : Boolean; @@ -80,14 +80,12 @@ begin inherited Create; // create a sci driver instance - sciDriver := TCommPortDriver.Create(nil); + sciDriver := TComPort.Create(nil); // init sci settings - sciDriver.DataBits := db8BITS; - sciDriver.StopBits := sb1BITS; - sciDriver.Parity := ptNONE; - sciDriver.SwFlow := sfNONE; - sciDriver.PollingDelay := 5; + sciDriver.DataBits := dbEight; + sciDriver.StopBits := sbOneStopBit; + sciDriver.Parity.Bits := prNone; // reset packet length packetLen := 0; @@ -149,8 +147,7 @@ begin // configure port configIndex := settingsIni.ReadInteger('sci', 'port', 0); - sciDriver.Port := pnCustom; - sciDriver.PortName := Format( '\\.\COM%d', [ord(configIndex + 1)] ); + sciDriver.Port := Format( 'COM%d', [ord(configIndex + 1)] ); // release ini file object settingsIni.Free; @@ -167,9 +164,8 @@ end; //*** end of Configure *** //*************************************************************************************** function TXcpTransport.Connect : Boolean; begin - result := true; - if not sciDriver.Connect then - result := false; + sciDriver.Open; + result := sciDriver.Connected; end; //*** end of Connect *** @@ -199,7 +195,6 @@ var msgData : array of Byte; resLen : byte; cnt : byte; - dwEnd :DWord; begin // init the return value result := false; @@ -222,35 +217,26 @@ begin msgData[cnt+1] := packetData[cnt]; end; + // configure transmit timeout. timeout = (MULTIPLIER) * number_of_bytes + CONSTANT + sciDriver.Timeouts.WriteTotalConstant := 0; + sciDriver.Timeouts.WriteTotalMultiplier := timeOutms div (packetLen+1); + // submit the packet transmission request - if sciDriver.SendData(@msgData[0], packetLen+1) <> (packetLen+1) then + if sciDriver.Write(msgData[0], packetLen+1) <> (packetLen+1) then begin // unable to submit tx request Exit; end; - // compute timeout time - dwEnd := GetTickCount + timeOutms; + // configure reception timeout. timeout = (MULTIPLIER) * number_of_bytes + CONSTANT + sciDriver.Timeouts.ReadTotalConstant := timeOutms; + sciDriver.Timeouts.ReadTotalMultiplier := 0; - // configure timeout for first byte - sciDriver.InputTimeout := timeOutms; - - // receive the first byte which holds the packet length - if sciDriver.ReadByte(resLen) = true then + // receive the first byte which should hold the packet length + if sciDriver.Read(resLen, 1) = 1 then begin - timeOutms := GetTickCount; - if timeOutms < dwEnd then - begin - // configure timeout for remaining bytes - sciDriver.InputTimeout := dwEnd - timeOutms; - end - else - begin - Exit; // timed out - end; - // receive the actual packet data - if sciDriver.ReadData(@packetData[0], resLen) = resLen then + if sciDriver.Read(packetData[0], resLen) = resLen then begin packetLen := resLen; result := true; @@ -268,7 +254,7 @@ end; //*** end of SendPacket *** //*************************************************************************************** procedure TXcpTransport.Disconnect; begin - sciDriver.Disconnect; + sciDriver.Close; end; //*** end of Disconnect *** diff --git a/Host/Source/MicroBoot/interfaces/uart/openblt_uart.cfg b/Host/Source/MicroBoot/interfaces/uart/openblt_uart.cfg deleted file mode 100644 index 7e67a882..00000000 --- a/Host/Source/MicroBoot/interfaces/uart/openblt_uart.cfg +++ /dev/null @@ -1,35 +0,0 @@ --$A+ --$B- --$C+ --$D+ --$E- --$F- --$G+ --$H+ --$I+ --$J+ --$K- --$L+ --$M- --$N+ --$O+ --$P+ --$Q- --$R- --$S- --$T- --$U- --$V+ --$W- --$X+ --$YD --$Z1 --cg --AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; --H+ --W+ --M --$M16384,1048576 --K$00400000 --E../../../../ --LNc:\borland\delphi4\Lib diff --git a/Host/Source/MicroBoot/interfaces/uart/openblt_uart.dof b/Host/Source/MicroBoot/interfaces/uart/openblt_uart.dof deleted file mode 100644 index 0e2c2a16..00000000 --- a/Host/Source/MicroBoot/interfaces/uart/openblt_uart.dof +++ /dev/null @@ -1,87 +0,0 @@ -[Compiler] -A=1 -B=0 -C=1 -D=1 -E=0 -F=0 -G=1 -H=1 -I=1 -J=1 -K=0 -L=1 -M=0 -N=1 -O=1 -P=1 -Q=0 -R=0 -S=0 -T=0 -U=0 -V=1 -W=0 -X=1 -Y=1 -Z=1 -ShowHints=1 -ShowWarnings=1 -UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -[Linker] -MapFile=0 -OutputObjs=0 -ConsoleApp=1 -DebugInfo=0 -RemoteSymbols=0 -MinStackSize=16384 -MaxStackSize=1048576 -ImageBase=4194304 -ExeDescription= -[Directories] -OutputDir=../../../../ -UnitOutputDir= -PackageDLLOutputDir= -PackageDCPOutputDir= -SearchPath= -Packages=Vcl40;Vclx40;Vcldb40;vcldbx40;VclSmp40;Qrpt40 -Conditionals= -DebugSourceDirs= -UsePackages=0 -[Parameters] -RunParams= -HostApplication= -[Version Info] -IncludeVerInfo=0 -AutoIncBuild=0 -MajorVer=1 -MinorVer=0 -Release=0 -Build=0 -Debug=0 -PreRelease=0 -Special=0 -Private=0 -DLL=0 -Locale=1031 -CodePage=1252 -[Version Info Keys] -CompanyName= -FileDescription= -FileVersion=1.0.0.0 -InternalName= -LegalCopyright= -LegalTrademarks= -OriginalFilename= -ProductName= -ProductVersion=1.0.0.0 -Comments= -[Excluded Packages] -$(DELPHI)\Lib\dclusr40.bpl=Borland User -[HistoryLists\hlUnitAliases] -Count=1 -Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -[HistoryLists\hlOutputDirectorry] -Count=2 -Item0=../../../../ -Item1=../../../ diff --git a/Host/Source/MicroBoot/interfaces/uart/openblt_uart.dpr b/Host/Source/MicroBoot/interfaces/uart/openblt_uart.dpr index ca070952..5f17d32b 100644 --- a/Host/Source/MicroBoot/interfaces/uart/openblt_uart.dpr +++ b/Host/Source/MicroBoot/interfaces/uart/openblt_uart.dpr @@ -51,8 +51,7 @@ uses XcpLoader in '..\XcpLoader.pas', XcpTransport in 'XcpTransport.pas', XcpSettings in 'XcpSettings.pas' {XcpSettingsForm}, - CPDrv in 'CPDrv.pas'; - + CPort in 'CPort.pas'; //*************************************************************************************** // Global Constants @@ -224,7 +223,7 @@ begin end; // update the log - MbiCallbackOnLog(logStr); + MbiCallbackOnLog(ShortString(logStr)); // update loop variables len := len - currentWriteCnt; @@ -258,25 +257,25 @@ begin // connect the transport layer MbiCallbackOnInfo('Connecting to the COM port.'); - MbiCallbackOnLog('Connecting to the COM port. t='+TimeToStr(Time)); + MbiCallbackOnLog('Connecting to the COM port. t='+ShortString(TimeToStr(Time))); Application.ProcessMessages; if not loader.Connect then begin // update the user info MbiCallbackOnError('Could not connect to COM port. Check your configuration.'); - MbiCallbackOnLog('Could not connect to COM port. Check your configuration and try again. t='+TimeToStr(Time)); + MbiCallbackOnLog('Could not connect to COM port. Check your configuration and try again. t='+ShortString(TimeToStr(Time))); Exit; end; //---------------- start the programming session -------------------------------------- - MbiCallbackOnLog('Starting the programming session. t='+TimeToStr(Time)); + MbiCallbackOnLog('Starting the programming session. t='+ShortString(TimeToStr(Time))); // try initial connect via XCP if loader.StartProgrammingSession <> kProgSessionStarted then begin // update the user info MbiCallbackOnInfo('Could not connect. Retrying. Reset your target if this takes a long time.'); - MbiCallbackOnLog('Connect failed. Switching to backdoor entry mode. t='+TimeToStr(Time)); + MbiCallbackOnLog('Connect failed. Switching to backdoor entry mode. t='+ShortString(TimeToStr(Time))); Application.ProcessMessages; // continuously try to connect via XCP true the backdoor sessionStartResult := kProgSessionGenericError; @@ -296,7 +295,7 @@ begin // don't retry if the error was caused by not being able to unprotect the programming resource if sessionStartResult = kProgSessionUnlockError then begin - MbiCallbackOnLog('Security issue. Could not unprotect the programming resource. Check your configured XCP protection DLL. t='+TimeToStr(Time)); + MbiCallbackOnLog('Security issue. Could not unprotect the programming resource. Check your configured XCP protection DLL. t='+ShortString(TimeToStr(Time))); MbiCallbackOnError('Security issue. Could not unprotect the programming resource.'); Exit; end; @@ -311,7 +310,7 @@ begin end; // still here so programming session was started - MbiCallbackOnLog('Programming session started. t='+TimeToStr(Time)); + MbiCallbackOnLog('Programming session started. t='+ShortString(TimeToStr(Time))); // create the datafile object datafile := TXcpDataFile.Create(progfile); @@ -336,16 +335,16 @@ begin datafile.GetRegionInfo(regionCnt, addr, len); // erase the memory - MbiCallbackOnLog('Clearing Memory '+Format('addr:0x%x,len:0x%x',[addr,len])+'. t='+TimeToStr(Time)); + MbiCallbackOnLog('Clearing Memory '+ShortString(Format('addr:0x%x,len:0x%x',[addr,len]))+'. t='+ShortString(TimeToStr(Time))); if not loader.ClearMemory(addr, len) then begin loader.GetLastError(errorInfo); - MbiCallbackOnLog('Could not clear memory ('+errorInfo+'). t='+TimeToStr(Time)); - MbiCallbackOnError('Could not clear memory ('+errorInfo+').'); + MbiCallbackOnLog('Could not clear memory ('+ShortString(errorInfo)+'). t='+ShortString(TimeToStr(Time))); + MbiCallbackOnError('Could not clear memory ('+ShortString(errorInfo)+').'); datafile.Free; Exit; end; - MbiCallbackOnLog('Memory cleared. t='+TimeToStr(Time)); + MbiCallbackOnLog('Memory cleared. t='+ShortString(TimeToStr(Time))); end; //---------------- next program the memory regions ------------------------------------ @@ -369,18 +368,18 @@ begin if currentWriteCnt = 0 then currentWriteCnt := kMaxProgLen; // program the data - MbiCallbackOnLog('Programming Data '+Format('addr:0x%x,len:0x%x',[addr,currentWriteCnt])+'. t='+TimeToStr(Time)); + MbiCallbackOnLog('Programming Data '+ShortString(Format('addr:0x%x,len:0x%x',[addr,currentWriteCnt]))+'. t='+ShortString(TimeToStr(Time))); LogData(@progdata[bufferOffset], currentWriteCnt); if not loader.WriteData(addr, currentWriteCnt, @progdata[bufferOffset]) then begin loader.GetLastError(errorInfo); - MbiCallbackOnLog('Could not program data ('+errorInfo+'). t='+TimeToStr(Time)); - MbiCallbackOnError('Could not program data ('+errorInfo+').'); + MbiCallbackOnLog('Could not program data ('+ShortString(errorInfo)+'). t='+ShortString(TimeToStr(Time))); + MbiCallbackOnError('Could not program data ('+ShortString(errorInfo)+').'); datafile.Free; Exit; end; - MbiCallbackOnLog('Data Programmed. t='+TimeToStr(Time)); + MbiCallbackOnLog('Data Programmed. t='+ShortString(TimeToStr(Time))); // update progress progress := progress + currentWriteCnt; @@ -392,30 +391,29 @@ begin bufferOffset := bufferOffset + currentWriteCnt; // update the user info - MbiCallbackOnInfo('Programming data... ' + Format('(%.1n of %.1n Kbytes)',[(progress/1024), dataSizeKB])); + MbiCallbackOnInfo('Programming data... ' + ShortString(Format('(%.1n of %.1n Kbytes)',[(progress/1024), dataSizeKB]))); end; end; //---------------- stop the programming session --------------------------------------- - MbiCallbackOnLog('Stopping the programming session. t='+TimeToStr(Time)); + MbiCallbackOnLog('Stopping the programming session. t='+ShortString(TimeToStr(Time))); if not loader.StopProgrammingSession then begin loader.GetLastError(errorInfo); - MbiCallbackOnLog('Could not stop the programming session ('+errorInfo+'). t='+TimeToStr(Time)); - MbiCallbackOnError('Could not stop the programming session ('+errorInfo+').'); + MbiCallbackOnLog('Could not stop the programming session ('+ShortString(errorInfo)+'). t='+ShortString(TimeToStr(Time))); + MbiCallbackOnError('Could not stop the programming session ('+ShortString(errorInfo)+').'); datafile.Free; Exit; end; - MbiCallbackOnLog('Programming session stopped. t='+TimeToStr(Time)); + MbiCallbackOnLog('Programming session stopped. t='+ShortString(TimeToStr(Time))); // all done so set progress to 100% and finish up progress := datafile.GetDataCnt; datafile.Free; MbiCallbackOnProgress(progress); - MbiCallbackOnLog('File successfully downloaded t='+TimeToStr(Time)); + MbiCallbackOnLog('File successfully downloaded t='+ShortString(TimeToStr(Time))); MbiCallbackOnDone; - end; //*** end of OnTimeout *** @@ -477,7 +475,7 @@ begin timer.Enabled := True; // store the program's filename - progfile := fileName; + progfile := String(fileName); end; //*** end of MbiStart *** @@ -495,7 +493,7 @@ begin stopRequest := true; // disconnect the transport layer - MbiCallbackOnLog('Disconnecting the transport layer. t='+TimeToStr(Time)); + MbiCallbackOnLog('Disconnecting the transport layer. t='+ShortString(TimeToStr(Time))); loader.Disconnect; end; //*** end of MbiStop *** @@ -614,15 +612,15 @@ end; //*** end of MbiConfigure *** //*************************************************************************************** exports //--- begin of don't change --- - MbiInit index 1, - MbiStart index 2, - MbiStop index 3, - MbiDeInit index 4, - MbiName index 5, - MbiDescription index 6, - MbiVersion index 7, - MbiConfigure index 8, - MbiVInterface index 9; + MbiInit, + MbiStart, + MbiStop, + MbiDeInit, + MbiName, + MbiDescription, + MbiVersion, + MbiConfigure, + MbiVInterface; //--- end of don't change --- end. diff --git a/Host/Source/MicroBoot/interfaces/uart/openblt_uart.dproj b/Host/Source/MicroBoot/interfaces/uart/openblt_uart.dproj new file mode 100644 index 00000000..62c0ad2e --- /dev/null +++ b/Host/Source/MicroBoot/interfaces/uart/openblt_uart.dproj @@ -0,0 +1,120 @@ + + + {38BAA5EC-0626-4775-9516-B3DED4560560} + openblt_uart.dpr + True + Debug + 1 + Library + VCL + 18.1 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace) + Vcl40;Vclx40;Vcldb40;vcldbx40;VclSmp40;Qrpt40;$(DCC_UsePackage) + false + false + 1031 + 00400000 + 1 + 1 + true + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= + openblt_uart + true + false + true + ../../../../ + 1 + + + 1033 + System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + true + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + true + false + + + 1033 + C:\Work\software\OpenBLT\Host\MicroBoot.exe + (None) + true + + + + MainSource + + + + + + + +
XcpSettingsForm
+
+ + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + +
+ + Delphi.Personality.12 + + + + + openblt_uart.dpr + + + + True + + + 12 + + + +
diff --git a/Host/Source/MicroBoot/interfaces/usb/UsbBulkLib.pas b/Host/Source/MicroBoot/interfaces/usb/UsbBulkLib.pas index 12130645..c7df7292 100644 --- a/Host/Source/MicroBoot/interfaces/usb/UsbBulkLib.pas +++ b/Host/Source/MicroBoot/interfaces/usb/UsbBulkLib.pas @@ -89,7 +89,7 @@ external DLL_Name; //*************************************************************************************** -// NAME: UblDllTransmit +// NAME: UblTransmit // PARAMETER: data pointer to byte array with transmit data. // len number of bytes to transmit. // RETURN VALUE: UBL_OKAY if successful, UBL_ERROR otherwise. @@ -104,7 +104,7 @@ external DLL_Name; //*************************************************************************************** -// NAME: UblDllReceive +// NAME: UblReceive // PARAMETER: data pointer to byte array where the data will be stored. // len number of bytes to receive. // timeout max time in milliseconds for the read to complete. diff --git a/Host/Source/MicroBoot/interfaces/usb/XcpSettings.dfm b/Host/Source/MicroBoot/interfaces/usb/XcpSettings.dfm index 64f4f177..585cc2ee 100644 Binary files a/Host/Source/MicroBoot/interfaces/usb/XcpSettings.dfm and b/Host/Source/MicroBoot/interfaces/usb/XcpSettings.dfm differ diff --git a/Host/Source/MicroBoot/interfaces/usb/XcpSettings.pas b/Host/Source/MicroBoot/interfaces/usb/XcpSettings.pas index e78cdd96..f18a6271 100644 --- a/Host/Source/MicroBoot/interfaces/usb/XcpSettings.pas +++ b/Host/Source/MicroBoot/interfaces/usb/XcpSettings.pas @@ -36,7 +36,7 @@ interface //*************************************************************************************** uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, - StdCtrls, ComCtrls, ExtCtrls, IniFiles; + StdCtrls, ComCtrls, ExtCtrls, IniFiles, Vcl.Imaging.pngimage; //*************************************************************************************** @@ -102,7 +102,8 @@ implementation procedure TXcpSettingsForm.btnOKClick(Sender: TObject); begin ModalResult := mrOK; -end; //*** end of btnOKClick *** +end; +//*** end of btnOKClick *** //*************************************************************************************** diff --git a/Host/Source/MicroBoot/interfaces/usb/openblt_usb.cfg b/Host/Source/MicroBoot/interfaces/usb/openblt_usb.cfg deleted file mode 100644 index 929df35b..00000000 --- a/Host/Source/MicroBoot/interfaces/usb/openblt_usb.cfg +++ /dev/null @@ -1,35 +0,0 @@ --$A+ --$B- --$C+ --$D+ --$E- --$F- --$G+ --$H+ --$I+ --$J+ --$K- --$L+ --$M- --$N+ --$O+ --$P+ --$Q- --$R- --$S- --$T- --$U- --$V+ --$W- --$X+ --$YD --$Z1 --cg --AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; --H+ --W+ --M --$M16384,1048576 --K$00400000 --E.\..\..\..\..\ --LNc:\borland\delphi4\Lib diff --git a/Host/Source/MicroBoot/interfaces/usb/openblt_usb.dof b/Host/Source/MicroBoot/interfaces/usb/openblt_usb.dof deleted file mode 100644 index 66305adc..00000000 --- a/Host/Source/MicroBoot/interfaces/usb/openblt_usb.dof +++ /dev/null @@ -1,87 +0,0 @@ -[Compiler] -A=1 -B=0 -C=1 -D=1 -E=0 -F=0 -G=1 -H=1 -I=1 -J=1 -K=0 -L=1 -M=0 -N=1 -O=1 -P=1 -Q=0 -R=0 -S=0 -T=0 -U=0 -V=1 -W=0 -X=1 -Y=1 -Z=1 -ShowHints=1 -ShowWarnings=1 -UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -[Linker] -MapFile=0 -OutputObjs=0 -ConsoleApp=1 -DebugInfo=0 -RemoteSymbols=0 -MinStackSize=16384 -MaxStackSize=1048576 -ImageBase=4194304 -ExeDescription= -[Directories] -OutputDir=.\..\..\..\..\ -UnitOutputDir= -PackageDLLOutputDir= -PackageDCPOutputDir= -SearchPath= -Packages=Vcl40;Vclx40;Vcldb40;vcldbx40;VclSmp40;Qrpt40 -Conditionals= -DebugSourceDirs= -UsePackages=0 -[Parameters] -RunParams= -HostApplication= -[Version Info] -IncludeVerInfo=0 -AutoIncBuild=0 -MajorVer=1 -MinorVer=0 -Release=0 -Build=0 -Debug=0 -PreRelease=0 -Special=0 -Private=0 -DLL=0 -Locale=1031 -CodePage=1252 -[Version Info Keys] -CompanyName= -FileDescription= -FileVersion=1.0.0.0 -InternalName= -LegalCopyright= -LegalTrademarks= -OriginalFilename= -ProductName= -ProductVersion=1.0.0.0 -Comments= -[Excluded Packages] -$(DELPHI)\Lib\dclusr40.bpl=Borland User -[HistoryLists\hlUnitAliases] -Count=1 -Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; -[HistoryLists\hlOutputDirectorry] -Count=2 -Item0=.\..\..\..\..\ -Item1=.\..\..\..\ diff --git a/Host/Source/MicroBoot/interfaces/usb/openblt_usb.dpr b/Host/Source/MicroBoot/interfaces/usb/openblt_usb.dpr index 1339f8b8..deb150eb 100644 --- a/Host/Source/MicroBoot/interfaces/usb/openblt_usb.dpr +++ b/Host/Source/MicroBoot/interfaces/usb/openblt_usb.dpr @@ -224,7 +224,7 @@ begin end; // update the log - MbiCallbackOnLog(logStr); + MbiCallbackOnLog(ShortString(logStr)); // update loop variables len := len - currentWriteCnt; @@ -258,14 +258,14 @@ begin // connect the transport layer MbiCallbackOnInfo('Connecting to target via USB.'); - MbiCallbackOnLog('Connecting to target via USB. t='+TimeToStr(Time)); + MbiCallbackOnLog('Connecting to target via USB. t='+ShortString(TimeToStr(Time))); Application.ProcessMessages; if not loader.Connect then begin // update the user info MbiCallbackOnInfo('Could not connect via USB. Retrying. Reset your target if this takes a long time.'); - MbiCallbackOnLog('Transport layer connection failed. t='+TimeToStr(Time)); - MbiCallbackOnLog('Retrying transport layer connection. Reset your target if this takes a long time. t='+TimeToStr(Time)); + MbiCallbackOnLog('Transport layer connection failed. t='+ShortString(TimeToStr(Time))); + MbiCallbackOnLog('Retrying transport layer connection. Reset your target if this takes a long time. t='+ShortString(TimeToStr(Time))); Application.ProcessMessages; // continuously try to coonect the transport layer while not loader.Connect do @@ -281,14 +281,14 @@ begin end; //---------------- start the programming session -------------------------------------- - MbiCallbackOnLog('Starting the programming session. t='+TimeToStr(Time)); + MbiCallbackOnLog('Starting the programming session. t='+ShortString(TimeToStr(Time))); // try initial connect via XCP if loader.StartProgrammingSession <> kProgSessionStarted then begin // update the user info MbiCallbackOnInfo('Could not connect. Retrying. Reset your target if this takes a long time.'); - MbiCallbackOnLog('Connect failed. Switching to backdoor entry mode. t='+TimeToStr(Time)); + MbiCallbackOnLog('Connect failed. Switching to backdoor entry mode. t='+ShortString(TimeToStr(Time))); Application.ProcessMessages; // continuously try to connect via XCP true the backdoor sessionStartResult := kProgSessionGenericError; @@ -300,7 +300,7 @@ begin // don't retry if the error was caused by not being able to unprotect the programming resource if sessionStartResult = kProgSessionUnlockError then begin - MbiCallbackOnLog('Security issue. Could not unprotect the programming resource. Check your configured XCP protection DLL. t='+TimeToStr(Time)); + MbiCallbackOnLog('Security issue. Could not unprotect the programming resource. Check your configured XCP protection DLL. t='+ShortString(TimeToStr(Time))); MbiCallbackOnError('Security issue. Could not unprotect the programming resource.'); Exit; end; @@ -315,7 +315,7 @@ begin end; // still here so programming session was started - MbiCallbackOnLog('Programming session started. t='+TimeToStr(Time)); + MbiCallbackOnLog('Programming session started. t='+ShortString(TimeToStr(Time))); // create the datafile object datafile := TXcpDataFile.Create(progfile); @@ -340,16 +340,16 @@ begin datafile.GetRegionInfo(regionCnt, addr, len); // erase the memory - MbiCallbackOnLog('Clearing Memory '+Format('addr:0x%x,len:0x%x',[addr,len])+'. t='+TimeToStr(Time)); + MbiCallbackOnLog('Clearing Memory '+ShortString(Format('addr:0x%x,len:0x%x',[addr,len]))+'. t='+ShortString(TimeToStr(Time))); if not loader.ClearMemory(addr, len) then begin loader.GetLastError(errorInfo); - MbiCallbackOnLog('Could not clear memory ('+errorInfo+'). t='+TimeToStr(Time)); - MbiCallbackOnError('Could not clear memory ('+errorInfo+').'); + MbiCallbackOnLog('Could not clear memory ('+ShortString(errorInfo)+'). t='+ShortString(TimeToStr(Time))); + MbiCallbackOnError('Could not clear memory ('+ShortString(errorInfo)+').'); datafile.Free; Exit; end; - MbiCallbackOnLog('Memory cleared. t='+TimeToStr(Time)); + MbiCallbackOnLog('Memory cleared. t='+ShortString(TimeToStr(Time))); end; //---------------- next program the memory regions ------------------------------------ @@ -373,18 +373,18 @@ begin if currentWriteCnt = 0 then currentWriteCnt := kMaxProgLen; // program the data - MbiCallbackOnLog('Programming Data '+Format('addr:0x%x,len:0x%x',[addr,currentWriteCnt])+'. t='+TimeToStr(Time)); + MbiCallbackOnLog('Programming Data '+ShortString(Format('addr:0x%x,len:0x%x',[addr,currentWriteCnt]))+'. t='+ShortString(TimeToStr(Time))); LogData(@progdata[bufferOffset], currentWriteCnt); if not loader.WriteData(addr, currentWriteCnt, @progdata[bufferOffset]) then begin loader.GetLastError(errorInfo); - MbiCallbackOnLog('Could not program data ('+errorInfo+'). t='+TimeToStr(Time)); - MbiCallbackOnError('Could not program data ('+errorInfo+').'); + MbiCallbackOnLog('Could not program data ('+ShortString(errorInfo)+'). t='+ShortString(TimeToStr(Time))); + MbiCallbackOnError('Could not program data ('+ShortString(errorInfo)+').'); datafile.Free; Exit; end; - MbiCallbackOnLog('Data Programmed. t='+TimeToStr(Time)); + MbiCallbackOnLog('Data Programmed. t='+ShortString(TimeToStr(Time))); // update progress progress := progress + currentWriteCnt; @@ -396,28 +396,28 @@ begin bufferOffset := bufferOffset + currentWriteCnt; // update the user info - MbiCallbackOnInfo('Programming data... ' + Format('(%.1n of %.1n Kbytes)',[(progress/1024), dataSizeKB])); + MbiCallbackOnInfo('Programming data... ' + ShortString(Format('(%.1n of %.1n Kbytes)',[(progress/1024), dataSizeKB]))); end; end; //---------------- stop the programming session --------------------------------------- - MbiCallbackOnLog('Stopping the programming session. t='+TimeToStr(Time)); + MbiCallbackOnLog('Stopping the programming session. t='+ShortString(TimeToStr(Time))); if not loader.StopProgrammingSession then begin loader.GetLastError(errorInfo); - MbiCallbackOnLog('Could not stop the programming session ('+errorInfo+'). t='+TimeToStr(Time)); - MbiCallbackOnError('Could not stop the programming session ('+errorInfo+').'); + MbiCallbackOnLog('Could not stop the programming session ('+ShortString(errorInfo)+'). t='+ShortString(TimeToStr(Time))); + MbiCallbackOnError('Could not stop the programming session ('+ShortString(errorInfo)+').'); datafile.Free; Exit; end; - MbiCallbackOnLog('Programming session stopped. t='+TimeToStr(Time)); + MbiCallbackOnLog('Programming session stopped. t='+ShortString(TimeToStr(Time))); // all done so set progress to 100% and finish up progress := datafile.GetDataCnt; datafile.Free; MbiCallbackOnProgress(progress); - MbiCallbackOnLog('File successfully downloaded t='+TimeToStr(Time)); + MbiCallbackOnLog('File successfully downloaded t='+ShortString(TimeToStr(Time))); MbiCallbackOnDone; end; //*** end of OnTimeout *** @@ -481,7 +481,7 @@ begin timer.Enabled := True; // store the program's filename - progfile := fileName; + progfile := String(fileName); end; //*** end of MbiStart *** @@ -499,7 +499,7 @@ begin stopRequest := true; // disconnect the transport layer - MbiCallbackOnLog('Disconnecting the transport layer. t='+TimeToStr(Time)); + MbiCallbackOnLog('Disconnecting the transport layer. t='+ShortString(TimeToStr(Time))); loader.Disconnect; end; //*** end of MbiStop *** @@ -618,16 +618,15 @@ end; //*** end of MbiConfigure *** //*************************************************************************************** exports //--- begin of don't change --- - MbiInit index 1, - MbiStart index 2, - MbiStop index 3, - MbiDeInit index 4, - MbiName index 5, - MbiDescription index 6, - MbiVersion index 7, - MbiConfigure index 8, - MbiVInterface index 9; + MbiInit, + MbiStart, + MbiStop, + MbiDeInit, + MbiName, + MbiDescription, + MbiVersion, + MbiConfigure, + MbiVInterface; //--- end of don't change --- - end. //********************************** end of openblt_usb.dpr ***************************** diff --git a/Host/Source/MicroBoot/interfaces/usb/openblt_usb.dproj b/Host/Source/MicroBoot/interfaces/usb/openblt_usb.dproj new file mode 100644 index 00000000..eaf36b20 --- /dev/null +++ b/Host/Source/MicroBoot/interfaces/usb/openblt_usb.dproj @@ -0,0 +1,120 @@ + + + {5F773EB4-5A4B-4591-999A-E208B1A44407} + openblt_usb.dpr + True + Debug + 1 + Library + VCL + 18.1 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + 1 + true + .\..\..\..\..\ + 1 + true + false + false + 00400000 + true + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace) + openblt_usb + 1031 + 1 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= + Vcl40;Vclx40;Vcldb40;vcldbx40;VclSmp40;Qrpt40;$(DCC_UsePackage) + + + 1033 + System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + true + + + RELEASE;$(DCC_Define) + false + 0 + 0 + + + true + DEBUG;$(DCC_Define) + false + + + C:\Work\software\OpenBLT\Host\MicroBoot.exe + 1033 + (None) + true + + + + MainSource + + + + + + + +
XcpSettingsForm
+
+ + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + +
+ + Delphi.Personality.12 + + + + + openblt_usb.dpr + + + + True + + + 12 + + + +
diff --git a/Host/Source/MicroBoot/uBootInterface.pas b/Host/Source/MicroBoot/uBootInterface.pas index 810eba14..92856138 100644 --- a/Host/Source/MicroBoot/uBootInterface.pas +++ b/Host/Source/MicroBoot/uBootInterface.pas @@ -148,7 +148,7 @@ end; //*** end of Create *** //*************************************************************************************** destructor TMicroBootInterface.Destroy; begin - if FLibraryHandle = 0 then //##Vg shouldn't this be <> 0? + if FLibraryHandle <> 0 then begin FreeLibrary(FLibraryHandle); // release the handle end; diff --git a/Host/openblt_can_peak.dll b/Host/openblt_can_peak.dll index fc39d61e..d73863ad 100644 Binary files a/Host/openblt_can_peak.dll and b/Host/openblt_can_peak.dll differ diff --git a/Host/openblt_can_peak.ini b/Host/openblt_can_peak.ini index 98acacfa..a0c9bdec 100644 --- a/Host/openblt_can_peak.ini +++ b/Host/openblt_can_peak.ini @@ -1,7 +1,7 @@ [can] hardware=0 channel=0 -baudrate=500 +baudrate=2 extended=0 txid=1639 rxid=2017 diff --git a/Host/openblt_can_vector.dll b/Host/openblt_can_vector.dll deleted file mode 100644 index 10688c4d..00000000 Binary files a/Host/openblt_can_vector.dll and /dev/null differ diff --git a/Host/openblt_can_vector.ini b/Host/openblt_can_vector.ini deleted file mode 100644 index 571a73bb..00000000 --- a/Host/openblt_can_vector.ini +++ /dev/null @@ -1,15 +0,0 @@ -[can] -hardware=2 -channel=0 -baudrate=500 -extended=0 -txid=1639 -rxid=2017 -[xcp] -seedkey=FeaserKey.dll -t1=1000 -t3=2000 -t4=10000 -t5=1000 -t7=2000 -tconnect=20 diff --git a/Host/openblt_net.dll b/Host/openblt_net.dll index 8936b1bc..918ad048 100644 Binary files a/Host/openblt_net.dll and b/Host/openblt_net.dll differ diff --git a/Host/openblt_net.ini b/Host/openblt_net.ini index d659c657..9e2d8189 100644 --- a/Host/openblt_net.ini +++ b/Host/openblt_net.ini @@ -1,7 +1,6 @@ [net] -hostname=169.254.19.63 +hostname=192.168.178.38 port=1000 -retry=1 [xcp] seedkey=FeaserKey.dll t1=1000 diff --git a/Host/openblt_uart.dll b/Host/openblt_uart.dll index 2f990392..77ac705c 100644 Binary files a/Host/openblt_uart.dll and b/Host/openblt_uart.dll differ diff --git a/Host/openblt_uart.ini b/Host/openblt_uart.ini index 34d42005..922a4fe5 100644 --- a/Host/openblt_uart.ini +++ b/Host/openblt_uart.ini @@ -1,5 +1,5 @@ [sci] -port=2 +port=7 baudrate=8 [xcp] seedkey=FeaserKey.dll diff --git a/Host/openblt_usb.dll b/Host/openblt_usb.dll index a1116cfe..d8cf1002 100644 Binary files a/Host/openblt_usb.dll and b/Host/openblt_usb.dll differ diff --git a/Host/vcand32.dll b/Host/vcand32.dll deleted file mode 100644 index 56dcfe98..00000000 Binary files a/Host/vcand32.dll and /dev/null differ