Všechny obvody v ATI-TV, které je možné softwarově ovládat, používají sběrnici I2C. Její hardwarový popis tady uvádět nebudu, protože je to z programátorského hlediska zbytečné, a hlavně ho neznám :-). Stačí, že je to sériová sběrnice se signály clock a data.ATI ve svých programech používá pro přístup k I2C knihovnu ATI_I2C.DLL. Dříve jsem ji taky používal, ale pak jsem si všiml, že TV-Online se na ATI_I2C.DLL vůbec neobrací a místo toho používá knihovnu I2CAPI.DLL. Ta je, na rozdíl od ATI_I2C.DLL, umístěná v systémovém adresáři Windows (%WINDIR%\System). Přitom všechny odstatní DLL jsou v \ATI\ATIDESK[\DRIVERS]. Předpokládám tedy, že I2CAPI.DLL je jakási "veřejná" knihovna, která má sloužit vývojářům ke komunikaci s I2C. Navíc jsem se do ní díval, a je to vlastně jen interface, který najde ATI_I2C.DLL, naimportuje z ní patřičné funkce a ty pak volá. To by potvrzovalo předpoklad o public verzi.
Ještě vás chci upozornit, že programuji převážně v Delphi. Proto i všechny deklarace funkcí apod. budu uvádět tak, jak by se použily v Delphi. Myslím ale, že převod do "C" podoby pro vás nebude vůbec žádný problém.
- deklarace procedure xxx je to samé jako void xxx()
- deklarace function xxx(a:TYP1, b:TYP2):TYPF je to samé jako TYPF xxx(TYP1 a, TYP2 b)
- typ word je 16bitový unsigned int
- typ pointer je obecný_typ *
- všem funkcím exportovaným z knihoven ATI se parametry předávají v původním pořadí, návratová hodnota se vrací v registru AX, a úklid zásobníku provádí volaná funkce. To myslím odpovídá konvenci stdcall, ale ruku do ohně bych za to nedal. Nemám teď po ruce manuál.
Knihovna I2CAPI.DLL exportuje tyto funkce pro práci s I2C:
NE-Dump of "I2CAPI.DLL" ... Entry 7: I2CREADAFTERRESTART Entry 4: I2CCLOSE Entry 3: I2COPEN Entry 6: I2CWRITE ...Když se podíváme, s jakými parametry se tyto funkce volají, vyjde nám něco takového:
function I2COPEN(dummy:Word):Word; far; external 'I2CAPI.DLL' name 'I2COPEN'; procedure I2CCLOSE; far; external 'I2CAPI.DLL' name 'I2CCLOSE'; function I2CWRITE( xunit:Word; port:Word; wbuffer:Pointer; wcount:Word):Word; far; external 'I2CAPI.DLL' name 'I2CWRITE'; function I2CREADAFTERRESTART( xunit:Word; port:Word; rbuffer:Pointer; rcount:Word; wbuffer:Pointer; wcount:Word):Word; far; external 'I2CAPI.DLL' name 'I2CREADAFTERRESTART';Důležité jsou jen funkce I2CWRITE a I2CREADAFTERRESTART. I2COPEN a I2CCLOSE totiž v aktuální verzi (5.0) nedělají vůbec nic. Resp. I2CCLOSE skutečně nedělá nic, a I2COPEN pouze vrátí parametr dummy, který jí byl předán :-).
Takže teď k těm dvěma důležitým funkcím:
unit I2C_API; interface uses SysUtils, WinTypes, WinProcs; type TI2CBuffer = record a:Word; {+0 (0)} port:Word; {+2 (port)} retval:Word; {+4 (return value -- 0 = OK)} writeCount:Word; {+6 (delka)} readCount:Word; {+8 (0)} writeBuf:Pointer; {ofs=+0a, seg=+0c} readBuf:Pointer; end; procedure I2C_Open; procedure I2C_Close; function I2C_write(port:Byte; co:String):Word; function I2C_read(port:Byte; wbuf:String; co:Pointer; delka:Integer):Word; implementation function I2COPEN(dummy:Word):Word; far; external 'I2CAPI.DLL' name 'I2COPEN'; procedure I2CCLOSE; far; external 'I2CAPI.DLL' name 'I2CCLOSE'; function I2CWRITE(xunit:Word; port:Word; wbuffer:Pointer; wcount:Word):Word; far; external 'I2CAPI.DLL' name 'I2CWRITE'; function I2CREADAFTERRESTART(xunit:Word; port:Word; rbuffer:Pointer; rcount:Word; wbuffer:Pointer; wcount:Word):Word; far; external 'I2CAPI.DLL' name 'I2CREADAFTERRESTART'; procedure I2C_Open; var W:Word; begin W:=I2COPEN(0); end; procedure I2C_Close; begin I2CCLOSE; end; function I2C_write(port:Byte; co:String):Word; begin I2C_write := I2CWRITE(0, port, @co[1], Length(co)); end; function I2C_read(port:Byte; wbuf:String; co:Pointer; delka:Integer):Word; begin I2C_read := I2CREADAFTERRESTART(0, port, co, delka, @wbuf[1], Length(wbuf)); end; end.To by bylo pro začátek všechno. Odkazy na popisy jednotlivých I2C obvodů jsou na úvodní straně.