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