PASCAL-Unit fuer Ansteuerung der Porterweiterung I2C PCA9954



{==============================================================================}
unit TWI_PCA9554;
{                                                                              }
{ Unit fuer Ansteuerung der Porterweiterung I2C PCA9954                        }
{                                                                              }
{ Bearbeitungsbeginn: 05.10.2010                                               }
{ Bearbeitungsstand : 08.10.2010                                               }
{ Bearbeiter        : S. Taborek                                               }
{==============================================================================}
{                                                                              }
{ Uses Hardware-TWI from Library-Manager                                       }
{ The first Call in Main-Program have to be:   Init_PCA9554(Modul-Adresse);    }
{ Change the Adresse, if the Chip-address-input 0, 1, 2  ist unlike Low.       }
{------------------------------------------------------------------------------}
(*
Command Protocol Function PCA9554
0 read byte Input Port register
1 read/write byte Output Port register
2 read/write byte Polarity Inversion register
3 read/write byte Configuration register
Register 0 - Input Port register bit description
Bit Symbol Access     Value      Description
7   I7     read only  X          determined by externally applied logic level
6   I6     read only  X
5   I5     read only  X
4   I4     read only  X
3   I3     read only  X
2   I2     read only  X
1   I1     read only  X
0   I0     read only  X
Register 1 - Output Port register
This register reflects the outgoing logic levels of the pins defined as outputs
by Register 3.  Bit values in this register have no effect on pins defined as
inputs. Reads from this register return the value that is in the flip-flop
controlling the output selection, not the actual pin value.
Legend: * default value.
Bit Symbol Access Value Description
7   O7     R      1*    reflects outgoing logic levels of pins defined as
6   O6     R      1*    outputs by Register 3
5   O5     R      1*
4   O4     R      1*
3   O3     R      1*
2   O2     R      1*
1   O1     R      1*
0   O0     R      1*
Register 2 - Polarity Inversion register bit description
0 = Input Port register data retained (default value)
1 = Input Port register data inverted
Bit Symbol Access Value Description
7   N7     R/W    0*    inverts polarity of Input Port register data
6   N6     R/W    0*
5   N5     R/W    0*
4   N4     R/W    0*
3   N3     R/W    0*
2   N2     R/W    0*
1   N1     R/W    0*
0   N0     R/W    0*
Register 3 - Configuration register
This register configures the directions of the I/O pins.
0 = corresponding port pin enabled as an output
1 = corresponding port pin configured as input
Legend: * default value.
Bit Symbol Access Value Description
7   C7     R/W    1*    configures the directions of the I/O pins
6   C6     R/W    1*
5   C5     R/W    1*
4   C4     R/W    1*
3   C3     R/W    1*
2   C2     R/W    1*
1   C1     R/W    1*
0   C0     R/W    1*
          *)
//-----------------------------Interface-------------------------------
function Init_PCA9554(UnitAdr:Byte):byte;
function Config_PCA9554(directions, invert :byte):byte;
function Write_PCA9554(daten:byte):byte;
function Read_PCA9554(var daten:byte):byte;
//---------------------------------------------------------------------
implementation
const 
  Twi_clock     : longint = 400000;   // max 400 KHz
  Read_Adr      : byte    = 0x01;
  Write_Adr     : byte    = 0x00;
  C_PCA9554_Adr : byte    = 0x38;     // Datenblatt und A2A1A0 = low
var
  PCA9554_Conf  : byte;
  PCA9554_Adr   : byte;
{------------------------------------------------------------------------------}
function Init_PCA9554(UnitAdr:Byte):byte;
{------------------------------------------------------------------------------}
{Returns 0 if OK                                                               }
{Function muss nur einmal aufgerufen werden}
begin
  TWI_Init(Twi_clock);
  PCA9554_Adr := (UnitAdr shl 1);
  Result := 0;
  if (PCA9554_Adr < C_PCA9554_Adr) then Result := 1;
end;
{------------------------------------------------------------------------------}
function Config_PCA9554(directions, invert:byte):byte;
{------------------------------------------------------------------------------}
{Returns 0 if OK                                                               }
{Function muss nur einmal aufgerufen werden}
begin
  Result := 1;
  if (PCA9554_Adr < C_PCA9554_Adr) then exit;
  //
  if TWI_Start() = 0 then begin           // issue TWI start signal
    TWI_Write(PCA9554_Adr or Write_Adr);  // send byte via TWI (device address)
    TWI_Write(0x02);                      // send byte (Invert-cmd)
    TWI_Write(invert);                    // send data (Register2) (for input-inv)
    TWI_Write(PCA9554_Adr or Write_Adr);
    TWI_Write(0x03);                      // send byte (Direct ion-cmd)
    PCA9554_Conf := directions;           // merkt die aktuelle Config
    TWI_Write(directions);                // send data (Register3)
    TWI_Stop();                           // issue TWI stop signal
    delay_ms(1);
    Result := 0;
  end;
end;
{------------------------------------------------------------------------------}
function Write_PCA9554(daten:byte):byte;
{------------------------------------------------------------------------------}
{Returns 0 if OK                                                               }
begin
  Result := 1;
  if TWI_Start() = 0 then begin          // issue TWI start signal
    TWI_Write(PCA9554_Adr or Write_Adr); // send byte via TWI (device address + W)
    TWI_Write(0x1);             // send byte (Out-cmd=1)
    TWI_Write(daten);           // send data (Register1)
    TWI_Stop();                 // issue TWI stop signal
    Result := 0;
  end;
end;
{------------------------------------------------------------------------------}
function Read_PCA9554(var daten:byte):byte;
{------------------------------------------------------------------------------}
{Returns 0 if OK                                                               }
begin
  Result := 1;
  if TWI_Start() = 0 then begin           // issue TWI start signal
    TWI_Write(PCA9554_Adr or Write_Adr);  // send byte via TWI (device address)
    TWI_Write(0x0);                       // send byte (Inp-cmd=0)
    TWI_Start();                          // issue TWI start signal
    TWI_Write(PCA9554_Adr or Read_Adr);   // send byte via TWI (device address + R)
    daten := TWI_Read(0);                 // read data (Register0)
    TWI_Stop();                           // issue TWI stop signal
    Result := 0;
  end;
end;
//
//------------------------------------------------------------------------------
end.