Zápis a čítanie pamäte sa realizuje cez paralelný port s použitím I2C protokolu, ktorý je podrobnejšie popísaný nižšie na obrázku. Z paralelného portu sa využívajú nasledovné piny:
SDA (serial data line) – LPT pin 5 (DATA 3)
SCL (serial clock) – LPT pin 3 (DATA 1)
Pri zápise je potrebné nastaviť aj /WC (write control, write protect), ktorý slúži na ochranu pred nežiadúcim prepísaním údajov pamäte.
/WC – LPT pin 14 (CONTROL 1 – Auto Line Feed, hardvérovo invertovaný).
Na riadenie paralelného portu sa v zdrojovom kode využíva (volá) knižnica "inpout32.dll". LPT obsahuje tri registre DATA, STATUS, CONTROL. Port sa inicializuje s adresou 0x378h (base address), co je adresa dátového registra, ostatné registre sa potom inicializujú ako base adrress + 1 (status) a base address + 2 (control). Register DATA je štandardne nastavený ako výstupný (čize je možný iba zápis). Pre čitanie z registra je nutné nastaviť pin Enable Bi-Directional Port (CONTROL 5). Konkretnejší popis LPT pinov je uvedený na obrázku nižšie.
I2C protokol
Zápis bytov do M24C02
Čítanie bytov z M24C02
Paralelný port
Zdrojový kód:
using System; using System.Threading; namespace I2C { class I2CInterface { private int delay; private int PB; private int PC; private int lptPort = 0x00; public int DELAY_1ms { get { return delay; } set { delay = value; } } public I2CInterface(int lptPort) { this.PB = ParallelPort.Input(lptPort); this.PC = ParallelPort.Input(lptPort + 2); this.PB |= 0x0A; this.PC &= 0xDD; this.lptPort = lptPort; ParallelPort.Output(lptPort, this.PB); ParallelPort.Output(lptPort + 2, this.PC); } public void SDAOut(bool value) { if (value == true) { this.PB |= 0x08; } else { this.PB &= 0xF7; } ParallelPort.Output(this.lptPort, this.PB); } public void WriteProtect(bool value) { if (value == true) { this.PC &= 0xFD; } else { this.PC |= 0x02; } ParallelPort.Output(this.lptPort + 2, this.PC); } public bool SDAIn() { this.PC |= 0x20; ParallelPort.Output(this.lptPort + 2, this.PC); int data = ParallelPort.Input(this.lptPort); this.PC &= 0xDF; ParallelPort.Output(this.lptPort + 2, this.PC); return !((data & 0x08) == 0x08); } public void SCLOut(bool value) { if (value == true) { this.PB |= 0x02; } else { this.PB &= 0xFD; } ParallelPort.Output(this.lptPort, this.PB); } public void StartBit() { SDAOut(true); SCLOut(true); Thread.Sleep(delay); SDAOut(false); Thread.Sleep(delay); SCLOut(false); Thread.Sleep(delay); } public void StopBit() { SDAOut(false); SCLOut(true); Thread.Sleep(delay); SDAOut(true); Thread.Sleep(delay); } public void SendBit(bool value) { SDAOut(value); Thread.Sleep(delay); SCLOut(true); Thread.Sleep(delay); SCLOut(false); Thread.Sleep(delay); } public bool ReadBit() { SDAOut(true); Thread.Sleep(delay); SCLOut(true); Thread.Sleep(delay); bool value = SDAIn(); SCLOut(false); Thread.Sleep(delay); return value; } public bool Ack() { SDAOut(true); Thread.Sleep(delay); SCLOut(true); Thread.Sleep(delay); bool value = SDAIn(); SCLOut(false); Thread.Sleep(delay); return value; } public void NonAck() { SDAOut(true); Thread.Sleep(delay); SCLOut(true); Thread.Sleep(delay); SCLOut(false); Thread.Sleep(delay); } public void SendByte(int value, int bits, bool getAck, out bool ackValue) { for (int i = (int)Math.Pow(2, bits - 1); i > 0; i /= 2) { SendBit(((i & value) == i) ? true : false); } if (getAck == true) { ackValue = Ack(); } else { ackValue = false; NonAck(); } } public int ReadByte(int bits, bool ack) { int value = 0; for (int i = 0; i < bits; i++) { value *= 2; value += (ReadBit() == true) ? 0 : 1; } SendBit(!ack); return value; } } } //Pridanie "inpout32.dll" using System.Runtime.InteropServices; namespace I2C { class ParallelPort { [DllImport("inpout32.dll", EntryPoint = "Out32")] public static extern void Output(int address, int value); [DllImport("inpout32.dll", EntryPoint = "Inp32")] public static extern int Input(int address); } }