Recent

Author Topic: I2C: From AVR master to RPI slave, code help!  (Read 1983 times)

pascalbythree

  • Sr. Member
  • ****
  • Posts: 266
I2C: From AVR master to RPI slave, code help!
« on: November 10, 2023, 11:29:45 am »
Hey can anybody / MarkMLl help me out with these two peaces of source code?

I meed to use the Raspberry as Slave and the AVR as master to send strings/bytes throug the I2C stack!

FPC Raspberry code:

Code: Pascal  [Select][+][-]
  1. program ei_eio_i2c_55;
  2.  
  3. (* This is a companion to ei_eio_serial.ino, which is assumed to be compiled    *)
  4. (* with I2C support enabled and to respond to "EI\r" with "EIO\r". MarkMLl.     *)
  5.  
  6. {$mode objfpc}{$H+}
  7. {$assertions on }
  8.  
  9. uses
  10.   Sysutils, BaseUnix, crt;
  11.  
  12. const
  13.   I2C_SLAVE = 1795;
  14.  
  15. type
  16.   responseType= (none, bad, ok);
  17.  
  18. var
  19.   slave: dword= $55;
  20.   fd: cint;
  21.   scratch: integer;
  22.   ei: string[15]= 'EI' + #$0d;
  23.   response: string;
  24.  
  25.  
  26.   (* Convert the Data parameter from a word to a pointer. This should have
  27.     lots of sanity checks, i.e. that the IOCTL number is known to be one
  28.     that doesn't take a pointer, that the value being cast is actually small
  29.     and so on.
  30.   *)
  31.   function fpIoctl(Handle: cint; Ndx: TIOCtlRequest; Data: dword): cint;
  32.  
  33.   begin
  34.     Assert(Ndx = I2C_SLAVE, 'Bad IOCTL number');
  35.     Assert(Data < 256, 'Bad IOCTL parameter');
  36.     result := BaseUnix.FpIOCtl(Handle, Ndx, pointer(ptruint(Data)))
  37.   end { fpIoctl } ;
  38.  
  39.  
  40.   (* Assume that messages are fixed-format and that we're looking for EIO
  41.     followed by stuff.
  42.   *)
  43.   function getResponse(Handle: cint): responseType;
  44.  
  45. // Apparently an Arduino I2C message is restricted by buffer length to 32 bytes,
  46. // and a serial message to 64 bytes. This suggests that, assuming text-format
  47. // rather than binary data, individual lines are probably best kept below 32
  48. // characters and possibly when generated zero-padded to precisely 32 bytes even
  49. // if trimmed before being sent as text.
  50.  
  51.   begin
  52.     response := '........................';     (* 24 characters                *)
  53.     Sleep(100);                         (* Milliseconds                         *)
  54.     if fpRead(Handle, response[1], 24) <> 24 then
  55.       if response[1] = '.' then         (* No response at all                   *)
  56.         exit(none)
  57.       else                              (* Didn't get to \r                     *)
  58.         exit(bad);
  59.     if (Pos('EIO', response) <> 1) or (Pos(#$0d, response) = 0) then
  60.       exit(bad)                         (* Not quite right                      *)
  61.     else begin                          (* Got it                               *)
  62.       SetLength(response, Pos(#$0d, response) - 1);
  63.       exit(ok)
  64.     end
  65.   end { getResponse } ;
  66.  
  67.  
  68. begin
  69.   fd := fpOpen('/dev/i2c-1', O_RDWR);
  70.   Assert(fd >= 0, 'Open failed');
  71.   scratch := fpIoctl(fd, I2C_SLAVE, slave);
  72.   Assert(scratch = 0, 'Slave assignment failed');
  73.  
  74.   repeat
  75.  
  76.   case getResponse(fd) of
  77.     none: WriteLn('Read timed out');
  78.     bad:  WriteLn('Read incomplete')  
  79.   end;
  80.  
  81.   until keypressed;
  82.  
  83.   scratch := fpClose(fd);
  84.   Assert(scratch = 0, 'Close failed');
  85.   WriteLn('EXIT OK')
  86. end.

Freepascal AVR code:

Code: Pascal  [Select][+][-]
  1.     program WVW_LEFT;
  2.      
  3.     uses
  4.      i2c, delay;
  5.      
  6.       procedure ModePortB(Pin: byte; Value: Boolean);
  7.       begin
  8.         if Value then
  9.           begin
  10.             DDRB := DDRB or (1 shl pin);
  11.           end
  12.         else
  13.           begin
  14.             DDRB := DDRB and not (1 shl pin);
  15.           end;
  16.       end;
  17.      
  18.     procedure WritePortB(Pin: byte; Value: Boolean);
  19.       begin
  20.         if Value then
  21.           begin
  22.             PORTB := PORTB or (1 shl pin);
  23.           end
  24.         else
  25.           begin
  26.             PORTB := PORTB and not (1 shl pin);
  27.         end;
  28.       end;
  29.      
  30.     const  AddressI2C = $55;
  31.      
  32.     var
  33.       i2c_master: TI2CMaster;
  34.       i, wb ,data: byte;
  35.       S:String;
  36.       C:Char;  
  37.      
  38.     begin
  39.       i:=0;
  40.       wb:=0;
  41.       data:=0;
  42.       S:=' ';
  43.       C:=' ';  
  44.      
  45.       ModePortB(1, TRUE); // Status LED to output
  46.      
  47.       i2c_master.init(I2C_50kHz);
  48.      
  49.       S := 'Hello World!';
  50.      
  51.       repeat
  52.          inc(i);
  53.              if i = 12 then i:=1;
  54.      
  55.              i2c_master.start(AddressI2C,I2C_Wri]"]>Blockedde);    
  56.              wb := Ord(S[i]);
  57.              i2c_master.writeByte(wb);
  58.              i2c_master.stop;    
  59.              
  60.              WritePortB(1,True);  // Status LED OFF
  61.              delay_ms(20);
  62.              WritePortB(1,False); // Status LED ON
  63.              delay_ms(20);  
  64.       until 1=2;    
  65.     end.

Hope to hear from you all soon!, Greets Wouter van Wegen, PascalByThree.

PS: This is the topic where i got my source code from.
https://forum.lazarus.freepascal.org/index.php/topic,47384.msg339430.html#msg339430

« Last Edit: November 10, 2023, 11:37:57 am by pascalbythree »

 

TinyPortal © 2005-2018