<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>