Post Reply 
The holy grail of the BEEP(1400, 0.08) command: USB-HID
05-01-2023, 08:59 PM
Post: #28
RE: The holy grail of the BEEP(1400, 0.08) command: USB-HID
Quote: It would be great to see any progress that Anyone has made on it, even if it was not progress, something might be learned by those that haven't dared to try yet.

I have been playing with the FT260 and BME680 but have not had much time to devote to reproducing the OP's solution. So far:

I have found a bug in the originally posted code for getregs(). It doesn't handle retrieving more than 52 registers (bytes) at a time. Add line 262 reg:=reg+bsize; so that the block of code looks like this:

Code:
    // set register #D0 'i2ca' #06 #01 #'reg'
    ft260_i2cSend(i2ca,{reg}); 
    reg:=reg+bsize; // update the register to be read if reading more than max block size registers
    // read request p bytes  #C2 'i2ca' #06 #low #high
    sts:=CONCAT(sts,ft260_i2cReadReq(i2ca, p));

I started implementing the BME680 code from the Bosch pseudo code and C code. Unfortunately, firstly the results for temp and pressure seem inaccurate, so I think I have missed something but I'm not sure what exactly. Secondly, I tried implementing the Bosch integer algorithms to check that my implementation of the floating point routines was correct. The two versions of the temperature code give the same result. When it came to implementing the integer version of the pressure code, the program currently crashes as my conversion from C to PPL was too simplistic - I need to alter the integer code to use 2's complement ints so that negative numbers are handled correctly. These are my additions to the OP's supplied code if anyone else wants to play:

Code:
// MP's additions to connect Bosch BME680 temperature, pressure,
// humidity and air quality (gas resistance) sensor to FT260

// Make a list follow C convention of first element being zero

List0(lst)
BEGIN
  RETURN(CONCAT(tail(lst), head(lst)));
END;

// Reorder a list modified by List0() so that index 1 is the first element
// as per normal Prime convention

List1(lst)
BEGIN
  RETURN(CONCAT(lst(0), SUB(lst,1,SIZE(lst)-1)));
END;

// Check if ft260 and bme680 are connected and try to take sensor readings

EXPORT check_ft260_bme680() 
BEGIN
  LOCAL sts, temp_comp;
  LOCAL bme260_raw:={};
  LOCAL bme260_mm:={};
  LOCAL temp_res:={};
  LOCAL t_fine:=0;

  PRINT;
  IF EQ(UClose(),{{1027,24624}}) THEN
    IF EQ(ft260_open(),{64,64}) THEN
      IF EQ(getregs(#76h, #D0h, 1),{1,{97}}) THEN
        PRINT("Connected");
        // Perform one forced measurement of temp and pressure
        // osrs_t = 010b, osrs_p = 010b, mode = 01b = 49h
        sts:=setreg(#76h,{#74h,#49h});
        PRINT(sts); 
        // Read the entire contents of the 256 registers in the BME680
        bme260_raw:=getregs(#76h,#0,256);
        // Build list of all results with index zero being first register
        bme260_mm:=List0(bme260_raw(2));

        // Calculate temperature according to Bosch document
        temp_res:=calc_temp_float(bme260_mm);
        t_fine:=temp_res(2);
        calc_press_float(bme260_mm, t_fine);

        // Check temp calculation by also using the int code
        temp_res:=calc_temp_integer(bme260_mm);
        t_fine:=temp_res(2);
        L3:=calc_press_integer(bme260_mm, t_fine);

        UClose();
        RETURN(L3);
      ELSE
        RETURN("BME680 not connected");
      END;
    ELSE
      RETURN("FTE260 report error");
    END;
  ELSE
    RETURN("FT260 not connected");
  END;
END;

EXPORT calc_temp_float(data)
BEGIN
  LOCAL temp_adc, t_fine, temp_comp, par_t1, par_t2, par_t3, var1, var2;

  temp_adc:=data(#22h)*256*16+data(#23h)*16+IP(data(#24h)/16);
  par_t1:=data(#EAh)*256+data(#E9h);
  par_t2:=data(#8Bh)*256+data(#8Ah);
  par_t3:=data(#8Ch);

  var1:=((temp_adc/16384)-(par_t1/1024))*par_t2;
  var2:=(((temp_adc/131072)-(par_t1/8192))*
          ((temp_adc/131072)-(par_t1/8192)))*
          (par_t3*16);
  t_fine:=var1+var2;
  temp_comp:=t_fine/5120;

  PRINT("temp_comp "+STRING(temp_comp));
  PRINT("t_fine "+STRING(t_fine));
  RETURN({temp_comp, t_fine});
END;

EXPORT calc_press_float(data, t_fine)
BEGIN
  LOCAL press_adc, press_comp;
  LOCAL par_p1, par_p2, par_p3, par_p4, par_p5;
  LOCAL par_p6, par_p7, par_p8, par_p9, par_p10;
  LOCAL var1, var2, var3;

  press_adc:=data(#1Fh)*256*16+data(#20h)*16+IP(data(#21h)/16);
  par_p1:=data(#8Fh)*256+data(#8Eh);
  par_p2:=data(#91h)*256+data(#90h);
  par_p3:=data(#92h);
  par_p4:=data(#95h)*256+data(#94h);
  par_p5:=data(#97h)*256+data(#96h);
  par_p6:=data(#99h);
  par_p7:=data(#98h);
  par_p8:=data(#9Dh)*256+data(#9Ch);
  par_p9:=data(#9Fh)*256+data(#9Eh);
  par_p10:=data(#A0h);

  var1:=(t_fine/2)-64000;
  var2:=var1*var1*(par_p6/131072);
  var2:=var2+(var1*par_p5*2);
  var2:=(var2/4)+(par_p4*65536);
  var1:=(((par_p3*var1*var1)/16384)+(par_p2*var1))/524288;
  var1:=(1+(var1/32768))*par_p1;
  press_comp:=1048576-press_adc;

  // Avoid exception caused by division by zero
  IF IP(var1) THEN
    press_comp:=((press_comp-(var2/4096))*6250)/var1;
    var1:=(par_p9*press_comp*press_comp)/2147483648;
    var2:=press_comp*(par_p8/32768);
    var3:=(press_comp/256)*(press_comp/256)*(press_comp/256)*(par_p10/131072);
    press_comp:=press_comp+(var1+var2+var3+(par_p7*128))/16;
  ELSE
    press_comp:=0;
  END;

  PRINT("press_comp "+STRING(press_comp));
  RETURN(press_comp);
END;

EXPORT calc_temp_integer(data)
BEGIN
  LOCAL temp_adc, t_fine, temp_comp;
  LOCAL par_t1, par_t2, par_t3;
  LOCAL var1, var2, var3;

  temp_adc:=BITSL(data(#22h),12)+BITSL(data(#23h),4)+BITSR(data(#24h),4);
  par_t1:=BITSL(data(#EAh),8)+data(#E9h);
  par_t2:=BITSL(data(#8Bh),8)+data(#8Ah);
  par_t3:=data(#8Ch);

  var1:=BITSR(temp_adc,3)-BITSL(par_t1,1);
  var2:=BITSR(var1*par_t2,11);
  var3:=BITSR(BITSR(var1,1)*BITSR(var1,1),12);
  var3:=BITSR(var3*BITSL(par_t3,4),14);
  t_fine:=var2+var3;
  temp_comp:=BITSR((t_fine*5)+128,8);

  PRINT("temp_comp "+STRING(temp_comp/100));
  PRINT("t_fine "+STRING(t_fine));
  RETURN({temp_comp/100, t_fine});
END;

EXPORT calc_press_integer(data, t_fine)
BEGIN
  LOCAL press_adc, press_comp;
  LOCAL par_p1, par_p2, par_p3, par_p4, par_p5;
  LOCAL par_p6, par_p7, par_p8, par_p9, par_p10;
  LOCAL var1, var2, var3;

  press_adc:=BITSL(data(#1Fh),12)+BITSL(data(#20h),4)+BITSR(data(#21h),4);
  par_p1:=BITSL(data(#8Fh),8)+data(#8Eh);
  par_p2:=BITSL(data(#91h),8)+data(#90h);
  par_p3:=data(#92h);
  par_p4:=BITSL(data(#95h),8)+data(#94h);
  par_p5:=BITSL(data(#97h),8)+data(#96h);
  par_p6:=data(#99h);
  par_p7:=data(#98h);
  par_p8:=BITSL(data(#9Dh),8)+data(#9Ch);
  par_p9:=BITSL(data(#9Fh),8)+data(#9Eh);
  par_p10:=data(#A0h);

  // This returns a negative value and the later code bombs
  // Need to change all int code over to correctly using signed 2's complement ints
  var1:=BITSR(IP(t_fine),1)-#64000d;
DEBUG;
  var2:=BITSR(BITSR(BITSR(var1,2)*BITSR(var1,2),11)*par_p6,2);
  var2:=var2+BITSL(var1*par_p5,1);
  var2:=BITSR(var2,2)+BITSL(par_p4,16);
  var1:=BITSR(BITSR(BITSR(var1,2)*BITSR(var1,2),13)*BITSL(par_p3,5),3)+BITSR(​par_p2*var1,1);
  var1:=BITSR(var1,18);
  var1:=BITSR((32768+var1)*par_p1,15);
  press_comp:=1048576-press_adc;
  press_comp:=(press_comp-BITSR(var2,12))*3125;
  IF press_compā‰„BITSL(1,30) THEN
    press_comp:=BITSL(press_comp/var1,1);
  ELSE
    press_comp:=BITSL(press_comp,1)/var1;
  END;
  var1:=BITSR(par_p9*BITSR(BITSR(press_comp,3)*BITSR(press_comp,3),13),12);
  var2:=BITSR(BITSR(press_comp,2)*par_p8,13);
  var3:=BITSR(BITSR(press_comp,8)*BITSR(press_comp,8)*BITSR(press_comp,8)*par​_p10,17);
  press_comp:=press_comp+BITSR(var1+var2+var3+BITSL(par_p7,7),4);

  PRINT("press_comp "+STRING(press_comp));
  RETURN(press_comp);
END;
Find all posts by this user
Quote this message in a reply
Post Reply 


Messages In This Thread
RE: The holy grail of the BEEP(1400, 0.08) command: USB-HID - Mark Power - 05-01-2023 08:59 PM



User(s) browsing this thread: 1 Guest(s)