<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Apr 5, 2023 at 12:43 PM Bo Berglund via fpc-pascal <<a href="mailto:fpc-pascal@lists.freepascal.org">fpc-pascal@lists.freepascal.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Wed, 5 Apr 2023 11:40:09 +0200, Christo Crause via fpc-pascal<br>
<<a href="mailto:fpc-pascal@lists.freepascal.org" target="_blank">fpc-pascal@lists.freepascal.org</a>> wrote:<br>
>Looking at the datasheet for CAT24C128, Fig. 6 Byte Write Sequence, shows<br>
>no repeated start condition between register address and data bytes. I<br>
>suspect that the second i2c message should contain the I2C_M_NOSTART flag,<br>
>else the address and data parts of the transaction will be separated by a<br>
>repeated start signal. I have modified the WriteBytesToReg methods in<br>
>i2c.pas, please feel free to pull from Github and test this again.<br></blockquote><div><br></div><div>I tested the i2c code with a PCA9685 IC.  It also supports multi-byte writes, although it only has 8 bit register addresses.  I realised that my original code used two i2c transactions and that each transaction starts with sending the device address.  The multibyte write obviously doesn't work like this, so I changed the WriteBytesToReg methods (in i2c.pas) to combine the register address and data into one buffer, which is then transmitted using the WriteBytes method.</div><div><br></div><div>This was tested and confirmed when writing 4 bytes to sequential registers to a PCA9685 IC with the new WriteBytesToReg method (<a href="https://github.com/ccrause/rpiplc_pas/blob/dc568bbfba2cda50f7ba394469480109e652247d/native/pwm_pca9685.pas#L227">https://github.com/ccrause/rpiplc_pas/blob/dc568bbfba2cda50f7ba394469480109e652247d/native/pwm_pca9685.pas#L227</a>).</div><div><br></div><div>Only the WriteBytesToReg for 16 bit register addresses are now untested, although it follows a similar pattern so I have a reasonable expectation that it should work.<br></div><div><br></div><div>If this update still doesn't work, I will need a logic analyser trace of an i2c write transaction that is successful (say using i2ctrace) and one which is unsuccessful using TI2cMaster.WriteBytesToReg.  Or I need to find a similar EEPROM to test...<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Thanks, I did so and used it in my code but it still does not write the<br>
EEPROM...<br>
<br>
Here is the code I use to test (in a command line program), maybe you can see a<br>
usage problem?<br>
<br>
var<br>
  i2cbus,<br>
  dev_addr,<br>
  reg_addr,<br>
  data_cnt: integer;<br>
  indata: TBytes;<br>
<br>
procedure main_12c_write(); //This is the main application procedure<br>
var<br>
  i: integer;<br>
  num: uint16;<br>
  i2cEeprom: TI2c_eeprom;<br>
begin<br>
  processInputs; //Read command line and write to variables<br>
  //Now process the data towards the EEPROM<br>
  i2cEeprom := TI2c_eeprom.Create; //Defaults are set for my EEPROM<br>
  try<br>
    num := i2cEeprom.WriteData(reg_addr, data_cnt, indata);<br>
    Writeln('Wrote ' + IntToStr(num) + ' bytes to address $' +<br>
IntToHex(reg_addr,4) );<br>
  finally<br>
    i2cEeprom.Free;<br>
  end;<br>
<br>
function TI2c_eeprom.WriteData(StartAddress, NumBytes: uint16; Source: TBytes):<br>
uint16;<br>
var<br>
  endpos, capacity, addr: uint16;<br>
  i2cMaster: TI2cMaster;<br>
  i2cbus: TI2CBus;<br>
  sourcelen, i, j: integer;<br>
  pSource: PByte;<br>
begin<br>
  Result := 0;<br>
  //Check valid indata:<br>
  //snip....<br>
  //Prepare the handler for action...<br>
  i2cbus := TI2CBus(FI2cBusNo);<br>
  i2cMaster := TI2cMaster.Create;<br>
  try<br>
    if not i2cMaster.Initialize(i2cbus) then<br>
    begin<br>
      writeln('Error opening i2c device: ', FI2cBusNo);<br>
      exit;<br>
    end;<br>
<br>
    //Check if data will fit into a single page start at given address:<br>
    if ((StartAddress and $ffc0) = (endpos and  $ffc0)) then //Fits in page<br>
    begin<br>
      //Perform a single write cycle into the buffer<br>
      pSource := @source[0];<br>
      if not i2cMaster.WriteBytesToReg(FEEPROMAddr, startaddress, pSource,<br>
NumBytes) then<br>
      begin<br>
        Writeln('Error: Could not write to I2C device!');<br>
        exit;<br>
      end<br>
      else<br>
        Result := NumBytes;<br>
    end<br>
    else  //We need to split data over several commands<br>
    begin<br>
      Writeln('Not yet implmented data split into several writes');<br>
    end;<br>
  finally<br>
    i2cMaster.Free;<br>
  end;<br></blockquote><div><br></div><div>The use of WriteBytesToReg in the TI2c_eeprom.WriteData method seems fine, perhaps retest with the updated WriteBytesToReg method.<br></div></div></div>