?? avr309.dpr
字號:
library AVR309;
{
Author: Ing. Igor Cesko
http://www.cesko.host.sk
cesko@internet.sk
Project: AVR309 application note : USB to UART converter
www.atmel.com
}
//{$DEFINE DemoVersion}
{$WARN UNSAFE_CODE OFF}
{$WARN UNSAFE_TYPE OFF}
{$WARN UNSAFE_CAST OFF}
uses
Windows,Mmsystem,Messages;
{$R *.RES} //resource: AVRUSBicon
const
GlobalRS232BufferHiIndexLength=100016; //length of RS232 buffer
type
TGlobalRS232Buffer=array[0..GlobalRS232BufferHiIndexLength]of byte;
const
DrvName:PChar='\\.\AVR309USB_0'; //name of driver IgorPlug.sys
RS232BufferFileMappedName='IgorPlugUSBRS232FileMappedHandleName'; //name of unique memory mapped file - RS232 buffer
RS232BufferMutexName='IgorPlugUSBRS232MutexHandleName'; //name of unique mutex receiving RS232 thread
SerializationEventName='IgorPlugDLLEvent'; //name of unique event for serialization access to hardware
UARTx2Mode:boolean=false;
const
PGlobalRS232Buffer:^TGlobalRS232Buffer=nil; //pointer to RS232 buffer (unique in system - memory maped file)
GlobalRS232BufferLength=SizeOf(TGlobalRS232Buffer); //size of RS232 buffer
RS232BufferFileMappedHND:THandle=0;//file mapped handle of RS232 buffer
RS232BufferWrite:integer=0;//write position in RS232 buffer
RS232BufferRead:integer=0;//read position in RS232 buffer
GlobalRS232BufferEnd=High(TGlobalRS232Buffer)-16;//end of write position in RS232 buffer (can be overrun up to 8 bytes)
GlobalRS232BufferWritePos:integer=GlobalRS232BufferHiIndexLength-SizeOf(GlobalRS232BufferWritePos); //position in RS232 buffer where is located write position in RS232 buffer (for other applications to know where buffer ends)
IsRS232PrevInst: Boolean=true; //if there is previous application with DLL using
RS232MutexHandle: THandle=0; //handle of unique mutex - for detection if exist another application using this DLL
DrvHnd:DWORD=INVALID_HANDLE_VALUE; //handle of driver IgorPlug.sys
OutputDataLength=256;
var
OutputData:array[0..OutputDataLength-1] of byte; //data to USB
const
OutLength:integer=0; //length of data to USB
DoGetRS232BufferTimer:integer=0; //handle of timer generating event: reading to RS232 from device FIFO in intervals
RS232BufferTimerInterval:integer=10; //interval for reading from device FIFO into RS232 buffer
RS232BufferThreadId:integer=0; //reading RS232 buffer thread ID
RS232BufferThreadHND:integer=0; //reading RS232 buffer thread handle
RS232BufferGetEvent:integer=0; //event - signal for read from device FIFO
RS232BufferEndEvent:integer=0; //event to stop cyclic reading RS232 buffer thread
LocalThreadRunningEvent:integer=0; //event to signal to end of local RS232 buffer thread
SerializationEvent:THandle=0; //handle of serialization event - for serialization access to hardware
SerializationEventTimeout:integer=20000;//20 seconds to wait to end previous device access
HookHandle:integer=0; //hook handle: DLL is hooking message WM_QUIT to safe resouce unallocation
{$IFDEF DemoVersion}
DemoOK:integer=IDNO; //if there was clicked OK in DEMO version (in registered version is this IDOK)
OKDemoValue:integer=IDOK+1; //for hackers debugging - comparing value with DemoOK
{$ENDIF}
//Function numbers in hardware device
FNCNumberDoSetInfraBufferEmpty =1 ;//;restart of infra reading (if was stopped by RAM reading)
FNCNumberDoGetInfraCode =2 ;//;transmit of receved infra code (if some code in infra buffer)
FNCNumberDoSetDataPortDirection =3 ;//;set direction of data bits
FNCNumberDoGetDataPortDirection =4 ;//;get direction of data bits
FNCNumberDoSetOutDataPort =5 ;//;set data bits (if are bits as input, then set theirs pull-ups)
FNCNumberDoGetOutDataPort =6 ;//;get data bits (if are bits as input, then get theirs pull-ups)
FNCNumberDoGetInDataPort =7 ;//;get data bits - pin reading
FNCNumberDoEEPROMRead =8 ;//;read EEPROM from given address
FNCNumberDoEEPROMWrite =9 ;//;write data byte to EEPROM to given address
FNCNumberDoRS232Send =10 ;//;send one data byte to RS232 line
FNCNumberDoRS232Read =11 ;//;read one data byte from serial line (only when FIFO not implemented in device)
FNCNumberDoSetRS232Baud =12 ;//;set baud speed of serial line
FNCNumberDoGetRS232Baud =13 ;//;get baud speed of serial line (exact value)
FNCNumberDoGetRS232Buffer =14 ;//;get received bytes from FIFO RS232 buffer
FNCNumberDoSetRS232DataBits =15 ;//;set number of data bits of serial line
FNCNumberDoGetRS232DataBits =16 ;//;get number of data bits of serial line
FNCNumberDoSetRS232Parity =17 ;//;set parity of serial line
FNCNumberDoGetRS232Parity =18 ;//;get parity of serial line
FNCNumberDoSetRS232StopBits =19 ;//;set stopbits of serial line
FNCNumberDoGetRS232StopBits =20 ;//;get stopbits of serial line
//results - answers from device
NO_ERROR=0;
DEVICE_NOT_PRESENT=1;
NO_DATA_AVAILABLE=2;
INVALID_BAUDRATE=3;
OVERRUN_ERROR=4;
INVALID_DATABITS=5;
INVALID_PARITY=6;
INVALID_STOPBITS=7;
//-------------------------------------------------------------------------------------------------------
function DoGetRS232Baud(var BaudRate:integer):integer; stdcall export; forward;
//-------------------------------------------------------------------------------------------------------
function FNHookProc(code:Integer; wparam:Integer; lparam:Integer): Longint stdcall;
// Hook function: only when application ends then safely frees FIFO reading thread
var
lpMsg:^TMsg;
begin
lpMsg:=pointer(lparam);
Result:=CallNextHookEx(HookHandle,code,wParam,lParam);
if (lpMsg^.message=WM_QUIT) then
begin
if DoGetRS232BufferTimer<>0 then
begin
timeKillEvent(DoGetRS232BufferTimer);
DoGetRS232BufferTimer:=0;
end;
SetEvent(RS232BufferEndEvent);
WaitForSingleObject(RS232BufferThreadHND,5000);
CloseHandle(RS232BufferThreadHND);
RS232BufferThreadHND:=0;
end;
end;
//-------------------------------------------------------------------------------------------------------
procedure ShowThreadErrorMessage;
//if some thread locks serialization access - display message
const
InProgress:boolean=false;
begin
SetEvent(SerializationEvent);
if InProgress then Exit;
InProgress:=true;
MessageBox(0,'Another thread is using long time AVR309.dll','Error',MB_OK or MB_ICONERROR or MB_TASKMODAL or MB_TOPMOST);
InProgress:=false;
end;
//-------------------------------------------------------------------------------------------------------
function OpenDriver:boolean;
//open device driver
begin
Result:=false;
DrvHnd:=CreateFile(PChar(DrvName),GENERIC_WRITE or GENERIC_READ, FILE_SHARE_WRITE or FILE_SHARE_READ,
nil,OPEN_EXISTING,0,0);
if DrvHnd=INVALID_HANDLE_VALUE then Exit;
Result:=true;
end;
//-------------------------------------------------------------------------------------------------------
function CloseDriver:boolean;
//close device driver
begin
Result:=true;
if DrvHnd<>INVALID_HANDLE_VALUE then CloseHandle(DrvHnd);
end;
//-------------------------------------------------------------------------------------------------------
function SendToDriver(FunctionNumber:byte; Param1,Param2:word;
var OutputData:array of byte; var OutLength:integer):boolean;
//send and receive data to device through device driver
var
LocalInBuffer:array [0..4] of byte;
RepeatCount:integer;
OutLengthMax:integer;
begin
{$IFDEF DemoVersion}
if abs(DemoOK)<>(Round(OKDemoValue)-1) then
WaitForSingleObject(SerializationEvent,SerializationEventTimeout);//delay for bad cracking
{$ENDIF}
RepeatCount:=3;
Result:=false;
if not OpenDriver then
begin
OutLength:=0;
Exit;
end;
LocalInBuffer[0]:=FunctionNumber;
LocalInBuffer[1]:=Lo(Param1);
LocalInBuffer[2]:=Hi(Param1);
LocalInBuffer[3]:=Lo(Param2);
LocalInBuffer[4]:=Hi(Param2);
if OutLength<0 then
OutLengthMax:=OutputDataLength
else
OutLengthMax:=OutLength;
if OutLengthMax>255 then
OutLengthMax:=255;
try
repeat
Result:=DeviceIoControl(DrvHnd,$800+8,@LocalInBuffer,5,@OutputData,OutLengthMax,cardinal(OutLength),nil);
Result:=Result and (OutLength>0);
dec(RepeatCount);
until (OutLength>0)or(RepeatCount<=0);
except
DrvHnd:=CreateFile(PChar(DrvName),GENERIC_WRITE or GENERIC_READ, FILE_SHARE_WRITE or FILE_SHARE_READ,nil,OPEN_EXISTING,0,0);
end;
CloseDriver;
end;
//-------------------------------------------------------------------------------------------------------
function DoSetInfraBufferEmpty:integer; stdcall export;
//;restart of infra reading (if was stopped by RAM reading)
begin
Result:=DEVICE_NOT_PRESENT;
OutLength:=1;
if SendToDriver(FNCNumberDoSetInfraBufferEmpty,0,0,OutputData,OutLength) then
Result:=NO_ERROR;
end;
//-------------------------------------------------------------------------------------------------------
function DoGetInfraCode(var TimeCodeDiagram:array of byte; var DiagramLength:integer):integer; stdcall export;
//;transmit of receved infra code (if some code in infra buffer)
const
LastReadedCode:integer=-1;
HeaderLength=3;
var
BytesToRead:integer;
OutputData:array[0..200]of byte;
LastWrittenIndex:integer;
i,j,k:integer;
begin
if WaitForSingleObject(SerializationEvent,SerializationEventTimeout)=WAIT_TIMEOUT then
begin
ShowThreadErrorMessage;
Result:=DEVICE_NOT_PRESENT;
Exit;
end;
Result:=DEVICE_NOT_PRESENT;
DiagramLength:=0;
OutLength:=3; //3 bytes is IR header length
if not SendToDriver(FNCNumberDoGetInfraCode,0,0,OutputData,OutLength) then
begin
SetEvent(SerializationEvent);
Exit;
end;
BytesToRead:=OutputData[0];
if (LastReadedCode=OutputData[1])or(OutLength<=1)or(BytesToRead=0) then
begin
Result:=NO_ERROR;
SetEvent(SerializationEvent);
Exit;
end;
LastReadedCode:=OutputData[1];
LastWrittenIndex:=OutputData[2];
i:=0;
while i<BytesToRead do
begin
OutLength:=BytesToRead-i;
if not SendToDriver(FNCNumberDoGetInfraCode,i+HeaderLength,0,OutputData[i],OutLength) then
begin
DoSetInfraBufferEmpty;
LastReadedCode:=-1;
SetEvent(SerializationEvent);
Exit;
end;
inc(i,OutLength);
end;
j:=LastWrittenIndex mod BytesToRead;
k:=0;
for i:=j to BytesToRead-1 do
begin
TimeCodeDiagram[k]:=OutputData[i];
inc(k);
end;
for i:=0 to (j-1) do
begin
TimeCodeDiagram[k]:=OutputData[i];
inc(k);
end;
DiagramLength:=BytesToRead;
DoSetInfraBufferEmpty;
Result:=NO_ERROR;
SetEvent(SerializationEvent);
end;
//-------------------------------------------------------------------------------------------------------
function DoSetDataPortDirections(DirectionByteB, DirectionByteC, DirectionByteD:byte; UsedPorts:byte):integer; stdcall export;
//;set direction of data bits
var
Param1,Param2:word;
begin
if WaitForSingleObject(SerializationEvent,SerializationEventTimeout)=WAIT_TIMEOUT then
begin
ShowThreadErrorMessage;
Result:=DEVICE_NOT_PRESENT;
Exit;
end;
Result:=DEVICE_NOT_PRESENT;
Param1:=DirectionByteC;
Param1:=(Param1 shl 8) or DirectionByteB;
Param2:=UsedPorts;
Param2:=(Param2 shl 8) or DirectionByteD;
OutLength:=1;
if SendToDriver(FNCNumberDoSetDataPortDirection,Param1,Param2,OutputData,OutLength) then
Result:=NO_ERROR;
SetEvent(SerializationEvent);
end;
//-------------------------------------------------------------------------------------------------------
function DoSetDataPortDirection(DirectionByte:byte):integer; stdcall export;
//;set direction of data bits (all ports the same)
begin
Result:=DoSetDataPortDirections(DirectionByte,DirectionByte,DirectionByte,$FF);
end;
//-------------------------------------------------------------------------------------------------------
function DoGetDataPortDirections(var DataDirectionByteB, DataDirectionByteC, DataDirectionByteD:byte; var UsedPorts:byte):integer; stdcall export;
//;get direction of data bits
begin
if WaitForSingleObject(SerializationEvent,SerializationEventTimeout)=WAIT_TIMEOUT then
begin
ShowThreadErrorMessage;
Result:=DEVICE_NOT_PRESENT;
Exit;
end;
Result:=DEVICE_NOT_PRESENT;
OutLength:=3;
if not SendToDriver(FNCNumberDoGetDataPortDirection,0,0,OutputData,OutLength) then
begin
SetEvent(SerializationEvent);
Exit;
end;
UsedPorts:=0;
if (OutLength>0)and(@DataDirectionByteB<>nil) then
begin
DataDirectionByteB:=OutputData[0];
UsedPorts:=UsedPorts or 1;
end;
if (OutLength>1)and(@DataDirectionByteC<>nil) then
begin
DataDirectionByteC:=OutputData[1];
UsedPorts:=UsedPorts or 2;
end;
if (OutLength>2)and(@DataDirectionByteD<>nil) then
begin
DataDirectionByteD:=OutputData[2];
UsedPorts:=UsedPorts or 4;
end;
Result:=NO_ERROR;
SetEvent(SerializationEvent);
end;
//-------------------------------------------------------------------------------------------------------
function DoGetDataPortDirection(var DataDirectionByte:byte):integer; stdcall export;
//;get direction of data bits
var
Dummy:byte;
begin
Result:=DoGetDataPortDirections(DataDirectionByte,Dummy,Dummy,Dummy);
end;
//-------------------------------------------------------------------------------------------------------
function DoSetOutDataPorts(DataOutByteB, DataOutByteC, DataOutByteD:byte; UsedPorts:byte):integer; stdcall export;
//;set data bits (if are bits as input, then set theirs pull-ups)
var
Param1,Param2:word;
begin
if WaitForSingleObject(SerializationEvent,SerializationEventTimeout)=WAIT_TIMEOUT then
begin
ShowThreadErrorMessage;
Result:=DEVICE_NOT_PRESENT;
Exit;
end;
Result:=DEVICE_NOT_PRESENT;
Param1:=DataOutByteC;
Param1:=(Param1 shl 8) or DataOutByteB;
Param2:=UsedPorts;
Param2:=(Param2 shl 8) or DataOutByteD;
OutLength:=1;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -