many updates..
new sensors.. display.. led.. drawing.. stuff..
This commit is contained in:
277
ext/sens/BME280.h
Normal file
277
ext/sens/BME280.h
Normal file
@@ -0,0 +1,277 @@
|
||||
#ifndef SENS_BME280
|
||||
#define SENS_BME280
|
||||
|
||||
#include "../../io/SoftI2C.h"
|
||||
|
||||
class BME280 {
|
||||
|
||||
static constexpr const char* NAME = "BME280";
|
||||
|
||||
static constexpr uint8_t ADDR7 = 0b1110110;
|
||||
|
||||
static constexpr uint8_t REG_CTRL1 = 0xF2; // humidity
|
||||
static constexpr uint8_t REG_CTRL2 = 0xF4; // temp, pressure, mode
|
||||
|
||||
static constexpr uint8_t REG_STATUS = 0xF3;
|
||||
static constexpr uint8_t REG_PRESSURE = 0xF7;
|
||||
static constexpr uint8_t REG_TEMPERATURE= 0xFA;
|
||||
static constexpr uint8_t REG_HUMIDITY = 0xFD;
|
||||
|
||||
static constexpr uint8_t REG_DIG_T1 = 0x88;
|
||||
static constexpr uint8_t REG_DIG_T2 = 0x8A;
|
||||
static constexpr uint8_t REG_DIG_T3 = 0x8C;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
bool started = false;
|
||||
|
||||
/** internal sensor calibration values */
|
||||
struct Calibration {
|
||||
|
||||
uint16_t dig_T1 = 0;
|
||||
int16_t dig_T2 = 0;
|
||||
int16_t dig_T3 = 0;
|
||||
|
||||
uint16_t dig_P1 = 0;
|
||||
int16_t dig_P2 = 0;
|
||||
int16_t dig_P3 = 0;
|
||||
int16_t dig_P4 = 0;
|
||||
int16_t dig_P5 = 0;
|
||||
int16_t dig_P6 = 0;
|
||||
int16_t dig_P7 = 0;
|
||||
int16_t dig_P8 = 0;
|
||||
int16_t dig_P9 = 0;
|
||||
|
||||
uint8_t dig_H1 = 0;
|
||||
int16_t dig_H2 = 0;
|
||||
uint8_t dig_H3 = 0;
|
||||
int16_t dig_H4 = 0;
|
||||
int16_t dig_H5 = 0;
|
||||
int8_t dig_H6 = 0;
|
||||
|
||||
} cal;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool isPresent() {
|
||||
return i2c::query(ADDR7);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void readCalib() {
|
||||
|
||||
debugMod(NAME, "readCalib()");
|
||||
|
||||
// read all 24 calibration bytes for temperature and pressure
|
||||
uint8_t b1[24];
|
||||
readRegister(REG_DIG_T1, b1, 24);
|
||||
|
||||
cal.dig_T1 = (b1[1] << 8) | b1[0];
|
||||
cal.dig_T2 = (b1[3] << 8) | b1[2];
|
||||
cal.dig_T3 = (b1[5] << 8) | b1[4];
|
||||
|
||||
cal.dig_P1 = (b1[7] << 8) | b1[6];
|
||||
cal.dig_P2 = (b1[9] << 8) | b1[8];
|
||||
cal.dig_P3 = (b1[11] << 8) | b1[10];
|
||||
cal.dig_P4 = (b1[13] << 8) | b1[12];
|
||||
cal.dig_P5 = (b1[15] << 8) | b1[14];
|
||||
cal.dig_P6 = (b1[17] << 8) | b1[16];
|
||||
cal.dig_P7 = (b1[19] << 8) | b1[18];
|
||||
cal.dig_P8 = (b1[21] << 8) | b1[20];
|
||||
cal.dig_P9 = (b1[23] << 8) | b1[22];
|
||||
|
||||
// humidity
|
||||
readRegister(0xA1, &cal.dig_H1, 1);
|
||||
readRegister(0xE1, b1, 7);
|
||||
cal.dig_H2 = (b1[1] << 8) | b1[0];
|
||||
cal.dig_H3 = b1[3];
|
||||
cal.dig_H4 = (b1[3] << 4) | (b1[4] & 0b000001111);
|
||||
cal.dig_H5 = (b1[5] << 4) | ((b1[4] & 0b111100000) >> 4);
|
||||
cal.dig_H6 = (b1[6]);
|
||||
|
||||
//os_printf("calib temp: %d %d %d\n", cal.dig_T1, cal.dig_T2, cal.dig_T3);
|
||||
//os_printf("calib pres: %d %d %d %d %d %d %d %d %d\n", cal.dig_P1, cal.dig_P2, cal.dig_P3, cal.dig_P4, cal.dig_P5, cal.dig_P6, cal.dig_P7, cal.dig_P8, cal.dig_P9);
|
||||
//os_printf("calib humi: %d %d %d %d %d %d\n", cal.dig_H1, cal.dig_H2, cal.dig_H3, cal.dig_H4, cal.dig_H5, cal.dig_H6);
|
||||
debugMod3(NAME, "calTemp: %d %d %d", cal.dig_T1, cal.dig_T2, cal.dig_T3);
|
||||
debugMod9(NAME, "calPres: %d %d %d %d %d %d %d %d %d", cal.dig_P1, cal.dig_P2, cal.dig_P3, cal.dig_P4, cal.dig_P5, cal.dig_P6, cal.dig_P7, cal.dig_P8, cal.dig_P9);
|
||||
debugMod6(NAME, "calHumi: %d %d %d %d %d %d", cal.dig_H1, cal.dig_H2, cal.dig_H3, cal.dig_H4, cal.dig_H5, cal.dig_H6);
|
||||
|
||||
}
|
||||
|
||||
void start() {
|
||||
debugMod(NAME, "start()");
|
||||
const uint8_t cfgHumi = 0b101; // 16x oversampling
|
||||
const uint8_t cfgPres = 0b101; // 16x oversampling
|
||||
const uint8_t cfgTemp = 0b101; // 16x oversampling
|
||||
const uint8_t cfgMode = 0b11;
|
||||
const uint8_t cfg1 = (cfgHumi << 1);
|
||||
const uint8_t cfg2 = (cfgTemp << 5) | (cfgPres << 2) | (cfgMode << 0);
|
||||
writeRegister(REG_CTRL1, &cfg1, 1);
|
||||
writeRegister(REG_CTRL2, &cfg2, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
void startOnce() {
|
||||
if (started) {return;}
|
||||
debugMod(NAME, "startOnce()");
|
||||
readCalib();
|
||||
start();
|
||||
started = true;
|
||||
}
|
||||
|
||||
uint8_t getStatus() {
|
||||
uint8_t res[1];
|
||||
readRegister(REG_STATUS, res, 1);
|
||||
//os_printf("Status: %d \n", res[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** get current pressure in hPa */
|
||||
float getPressure() {
|
||||
uint8_t res[3];
|
||||
readRegister(REG_PRESSURE, res, 3);
|
||||
//os_printf("res: %d - %d - %d \n", res[0], res[1], res[2]);
|
||||
const uint32_t tmp = ((res[0] << 16) | (res[1] << 8) | (res[2] << 0)) >> 4;
|
||||
const uint32_t pres = BME280_compensate_P_int64(tmp);
|
||||
const float presF = pres / 256.0f / 100.0f; // convert from Q24.8 to float and from Pa to hPa
|
||||
const uint32_t p0 = pres / 256;
|
||||
const uint32_t p1 = (uint32_t) presF;
|
||||
const uint32_t p2 = (presF - p1) * 100000;
|
||||
debugMod4(NAME, "[pres] ADC: %d -> %d Pa | %d.%d hPa", tmp, p0, p1,p2);
|
||||
return presF;
|
||||
}
|
||||
|
||||
float getTemperature() {
|
||||
uint8_t res[3];
|
||||
readRegister(REG_TEMPERATURE, res, 3);
|
||||
//os_printf("res: %d - %d - %d \n", res[0], res[1], res[2]);
|
||||
const uint32_t tmp = ((res[0] << 16) | (res[1] << 8) | (res[2] << 0)) >> 4;
|
||||
const int32_t temp = BME280_compensate_T_int32(tmp);
|
||||
const float tempF = temp / 100.0f;
|
||||
debugMod2(NAME, "[temp] ADC: %d -> %d", tmp, temp);
|
||||
return tempF;
|
||||
}
|
||||
|
||||
float getHumidity() {
|
||||
uint8_t res[2];
|
||||
readRegister(REG_HUMIDITY, res, 2);
|
||||
//os_printf("res: %d - %d \n", res[0], res[1]);
|
||||
const uint32_t tmp = (res[0] << 8) | (res[1] << 0);
|
||||
const int32_t humi = bme280_compensate_H_int32(tmp);
|
||||
const float humiF = humi / 1024.0f;
|
||||
const uint16_t h0 = humi / 1024;
|
||||
const uint16_t h1 = (uint16_t) humiF;
|
||||
const uint16_t h2 = (humiF - humi) * 10000;
|
||||
debugMod4(NAME, "[humi] ADC: %d -> %d -> %d.%d %%", tmp, h0, h1,h2);
|
||||
return humiF;
|
||||
}
|
||||
|
||||
bool readRegister(const uint8_t addr, uint8_t* dst, const uint8_t len) {
|
||||
|
||||
bool ok;
|
||||
|
||||
// address the slave in write mode and select the first register to read
|
||||
ok = i2c::startWrite(ADDR7);
|
||||
if (!ok) {os_printf("failed start write\n"); return false;}
|
||||
ok = i2c::writeByteAndCheck(addr);
|
||||
if (!ok) {os_printf("failed to select register %d\n", addr); return false;}
|
||||
|
||||
//i2c::stop();
|
||||
|
||||
// address the slave in read mode and read [len] registers
|
||||
ok = i2c::startRead(ADDR7);
|
||||
if (!ok) {os_printf("failed start read\n"); return 0;}
|
||||
i2c::readBytes(dst, len);
|
||||
|
||||
// done
|
||||
i2c::stop();
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool writeRegister(const uint8_t addr, const uint8_t* src, const uint8_t len) {
|
||||
|
||||
bool ok;
|
||||
|
||||
// address the slave in write mode and select the first register to read
|
||||
ok = i2c::startWrite(ADDR7);
|
||||
if (!ok) {os_printf("failed start write\n"); return false;}
|
||||
ok = i2c::writeByteAndCheck(addr);
|
||||
if (!ok) {os_printf("failed to select register %d\n", addr); return false;}
|
||||
ok = i2c::writeBytesAndCheck(src, len);
|
||||
if (!ok) {os_printf("failed to write register contents \n"); return false;}
|
||||
|
||||
// done
|
||||
i2c::stop();
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/** conversions from ADC values to real-world values. from Bosch BMP280 manual! */
|
||||
|
||||
using BME280_S32_t = int32_t;
|
||||
using BME280_U32_t = uint32_t;
|
||||
using BME280_S64_t = int64_t;
|
||||
BME280_S32_t t_fine = 0;
|
||||
|
||||
// Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC.
|
||||
// t_fine carries fine temperature as global value
|
||||
BME280_S32_t BME280_compensate_T_int32(BME280_S32_t adc_T) {
|
||||
BME280_S32_t var1, var2, T;
|
||||
var1 = ((((adc_T>>3) - ((BME280_S32_t)cal.dig_T1<<1))) * ((BME280_S32_t)cal.dig_T2)) >> 11;
|
||||
var2 = (((((adc_T>>4) - ((BME280_S32_t)cal.dig_T1)) * ((adc_T>>4) - ((BME280_S32_t)cal.dig_T1))) >> 12) * ((BME280_S32_t)cal.dig_T3)) >> 14;
|
||||
t_fine = var1 + var2;
|
||||
T = (t_fine * 5 + 128) >> 8;
|
||||
return T;
|
||||
}
|
||||
|
||||
// Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
|
||||
// Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa
|
||||
BME280_U32_t BME280_compensate_P_int64(BME280_S32_t adc_P) {
|
||||
BME280_S64_t var1, var2, p;
|
||||
var1 = ((BME280_S64_t)t_fine) - 128000;
|
||||
var2 = var1 * var1 * (BME280_S64_t)cal.dig_P6;
|
||||
var2 = var2 + ((var1*(BME280_S64_t)cal.dig_P5)<<17);
|
||||
var2 = var2 + (((BME280_S64_t)cal.dig_P4)<<35);
|
||||
var1 = ((var1 * var1 * (BME280_S64_t)cal.dig_P3)>>8) + ((var1 * (BME280_S64_t)cal.dig_P2)<<12);
|
||||
var1 = (((((BME280_S64_t)1)<<47)+var1))*((BME280_S64_t)cal.dig_P1)>>33;
|
||||
if (var1 == 0) {return 0;} // avoid exception caused by division by zero
|
||||
p = 1048576-adc_P;
|
||||
p = (((p<<31)-var2)*3125)/var1;
|
||||
var1 = (((BME280_S64_t)cal.dig_P9) * (p>>13) * (p>>13)) >> 25;
|
||||
var2 = (((BME280_S64_t)cal.dig_P8) * p) >> 19;
|
||||
p = ((p + var1 + var2) >> 8) + (((BME280_S64_t)cal.dig_P7)<<4);
|
||||
return (BME280_U32_t)p;
|
||||
}
|
||||
|
||||
// Returns humidity in %RH as unsigned 32 bit integer in Q22.10 format (22 integer and 10 fractional bits).
|
||||
// Output value of “47445” represents 47445/1024 = 46.333 %RH
|
||||
BME280_U32_t bme280_compensate_H_int32(BME280_S32_t adc_H) {
|
||||
BME280_S32_t v_x1_u32r;
|
||||
v_x1_u32r = (t_fine - ((BME280_S32_t)76800));
|
||||
v_x1_u32r = (((((adc_H << 14) - (((BME280_S32_t)cal.dig_H4) << 20) - (((BME280_S32_t)cal.dig_H5) * v_x1_u32r)) +
|
||||
((BME280_S32_t)16384)) >> 15) * (((((((v_x1_u32r * ((BME280_S32_t)cal.dig_H6)) >> 10) * (((v_x1_u32r *
|
||||
((BME280_S32_t)cal.dig_H3)) >> 11) + ((BME280_S32_t)32768))) >> 10) + ((BME280_S32_t)2097152)) *
|
||||
((BME280_S32_t)cal.dig_H2) + 8192) >> 14));
|
||||
v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((BME280_S32_t)cal.dig_H1)) >>
|
||||
4));
|
||||
v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r);
|
||||
v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r);
|
||||
return (BME280_U32_t)(v_x1_u32r>>12);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
154
ext/sens/MPU6050.h
Normal file
154
ext/sens/MPU6050.h
Normal file
@@ -0,0 +1,154 @@
|
||||
#ifndef SENS_MPU6050
|
||||
#define SENS_MPU6050
|
||||
|
||||
#include "../../io/SoftI2C.h"
|
||||
#include "../../Debug.h"
|
||||
|
||||
/**
|
||||
* accelereomter/gyroscope
|
||||
* https://www.invensense.com/wp-content/uploads/2015/02/MPU-6000-Datasheet1.pdf
|
||||
* https://www.invensense.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf
|
||||
* https://github.com/kriswiner/MPU6050/blob/master/MPU6050BasicExample.ino
|
||||
*/
|
||||
class MPU6050 {
|
||||
|
||||
private:
|
||||
|
||||
static constexpr const char* NAME = "MPU6050";
|
||||
|
||||
static constexpr uint8_t ADDR = 0b1101000 ;
|
||||
|
||||
static constexpr uint8_t REG_CFG_GYRO = 0x1B;
|
||||
static constexpr uint8_t REG_CFG_ACC = 0x1C;
|
||||
static constexpr uint8_t REG_ACCEL_XOUT_H = 0x3B;
|
||||
|
||||
static constexpr uint8_t REG_SMPLRT_DIV = 0x19;
|
||||
static constexpr uint8_t REG_CONFIG = 0x1A;
|
||||
|
||||
static constexpr uint8_t REG_PWR_MGMT_1 = 0x6B;
|
||||
|
||||
bool inited = false;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void init() {
|
||||
|
||||
debugMod(NAME, "init()");
|
||||
|
||||
// set clock source to be PLL with x-axis gyroscope reference, bits 2:0 = 001
|
||||
writeRegister(REG_PWR_MGMT_1, 0b001); // table on page 40
|
||||
|
||||
// Configure Gyro and Accelerometer
|
||||
// Disable FSYNC and set accelerometer and gyro bandwidth to 44 and 42 Hz, respectively;
|
||||
// DLPF_CFG = bits 2:0 = 010; this sets the sample rate at 1 kHz for both
|
||||
//writeRegister(REG_CONFIG, 0x03); // table on page 13
|
||||
writeRegister(REG_CONFIG, 0x00); // table on page 13
|
||||
|
||||
// Set sample rate = gyroscope output rate/(1 + SMPLRT_DIV)
|
||||
writeRegister(REG_SMPLRT_DIV, 0x04); // Use a 200 Hz sample rate
|
||||
|
||||
// configure gyro as +/- 4G -> +32767 = +4G, -32768 = -4G
|
||||
writeRegister(REG_CFG_ACC, 0b01 << 3); // table on page 15
|
||||
#define oneGto1000(x) ((int)x)*1000/(32768/4)
|
||||
}
|
||||
|
||||
bool writeRegister(const uint8_t addr, const uint8_t val) {
|
||||
|
||||
bool ok;
|
||||
|
||||
// address the slave in write mode and select the first register to read
|
||||
ok = i2c::startWrite(ADDR);
|
||||
if (!ok) {os_printf("failed start write\n"); return false;}
|
||||
ok = i2c::writeByteAndCheck(addr);
|
||||
if (!ok) {os_printf("failed to select register %d\n", addr); return false;}
|
||||
ok = i2c::writeBytesAndCheck(&val, 1);
|
||||
if (!ok) {os_printf("failed to write register contents \n"); return false;}
|
||||
|
||||
// done
|
||||
i2c::stop();
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
struct Acc {
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int16_t z;
|
||||
};
|
||||
|
||||
struct Gyro {
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int16_t z;
|
||||
};
|
||||
|
||||
struct Res {
|
||||
Acc acc;
|
||||
int16_t temp;
|
||||
Gyro gyro;
|
||||
};
|
||||
|
||||
void initOnce() {
|
||||
if (inited) {return;}
|
||||
init();
|
||||
inited = true;
|
||||
}
|
||||
|
||||
|
||||
bool isPresent() {
|
||||
return i2c::query(ADDR);
|
||||
}
|
||||
|
||||
bool query(Res& res) {
|
||||
|
||||
bool ok;
|
||||
|
||||
// select register(s) to read
|
||||
//i2c::start();
|
||||
ok = i2c::startWrite(ADDR);
|
||||
if (!ok) {os_printf("failed start write1\n"); return false;}
|
||||
ok = i2c::writeByteAndCheck(REG_ACCEL_XOUT_H);
|
||||
if (!ok) {os_printf("failed select register\n"); return false;}
|
||||
i2c::stop();
|
||||
|
||||
// read registers
|
||||
uint8_t buf[14];
|
||||
//i2c::start();
|
||||
ok = i2c::startRead(ADDR);
|
||||
if (!ok) {os_printf("failed start write2\n"); return false;}
|
||||
i2c::readBytes(buf, 14);
|
||||
i2c::stop();
|
||||
|
||||
res.acc.x = (buf[0] << 8) | buf[1];
|
||||
res.acc.y = (buf[2] << 8) | buf[3];
|
||||
res.acc.z = (buf[4] << 8) | buf[5];
|
||||
|
||||
res.temp = (buf[6] << 8) | buf[7];
|
||||
|
||||
res.gyro.x = (buf[8] << 8) | buf[9];
|
||||
res.gyro.y = (buf[10] << 8) | buf[11];
|
||||
res.gyro.z = (buf[12] << 8) | buf[13];
|
||||
|
||||
res.acc.x = oneGto1000(res.acc.x);
|
||||
res.acc.y = oneGto1000(res.acc.y);
|
||||
res.acc.z = oneGto1000(res.acc.z);
|
||||
|
||||
|
||||
//os_printf("Acc (%d, %d, %d)\n", res.acc.x, res.acc.y, res.acc.z);
|
||||
//os_printf("Gyro (%d, %d, %d)\n", res.gyro.x, res.gyro.y, res.gyro.z);
|
||||
//os_printf("Temp (%d)\n", res.temp);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
1127
ext/sens/VL53L0X.h
Normal file
1127
ext/sens/VL53L0X.h
Normal file
File diff suppressed because it is too large
Load Diff
132
ext/sens/XPT2046.h
Normal file
132
ext/sens/XPT2046.h
Normal file
@@ -0,0 +1,132 @@
|
||||
#ifndef XPT2046_H
|
||||
#define XPT2046_H
|
||||
|
||||
#include "../../Platforms.h"
|
||||
#include "../../io/HardSPI.h"
|
||||
#include "../../io/SoftSPI.h"
|
||||
|
||||
// https://www.buydisplay.com/download/ic/XPT2046.pdf
|
||||
|
||||
/** SPI-like touch controller */
|
||||
//template <int PIN_CS, int PIN_MISO, int PIN_MOSI, int PIN_CLK> class XPT2046 {
|
||||
template <int PIN_CS, typename SPI> class XPT2046 {
|
||||
|
||||
//SoftSPI<PIN_MISO, PIN_MOSI, PIN_CLK, true> spi;
|
||||
//HardSPI<PIN_MISO, PIN_MOSI, PIN_CLK> spi;
|
||||
|
||||
|
||||
static constexpr int PD0 = 0;
|
||||
static constexpr int PD1 = 1;
|
||||
static constexpr int SER_DFR = 2;
|
||||
static constexpr int MODE = 3;
|
||||
static constexpr int ADDR = 4;
|
||||
static constexpr int START = 7;
|
||||
|
||||
SPI& spi;
|
||||
|
||||
public:
|
||||
|
||||
XPT2046(SPI& spi) : spi(spi) {
|
||||
//spi.init();
|
||||
GPIO::setOutput(PIN_CS);
|
||||
}
|
||||
|
||||
struct Result {
|
||||
bool valid;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
};
|
||||
|
||||
Result read() {
|
||||
|
||||
GPIO::clear(PIN_CS);
|
||||
//vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
|
||||
Result res;
|
||||
|
||||
if (!isTouched()) {
|
||||
res.valid = false;
|
||||
} else {
|
||||
const uint16_t y = readAvg(1);
|
||||
const uint16_t x = readAvg(5);
|
||||
res.y = y;
|
||||
res.x = x;
|
||||
res.valid = (x != 0xFFFF) && (y != 0xFFFF);
|
||||
}
|
||||
|
||||
GPIO::set(PIN_CS);
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/** read 12-bit result from the given input-address using either differential mode or not */
|
||||
uint16_t read(const int inp, const bool differential) {
|
||||
|
||||
//uint8_t buf[2];
|
||||
const uint8_t diff = differential ? 0 : 1;
|
||||
const uint8_t cmd = (1 << START) | (inp << ADDR) | (0 << MODE) | (diff << SER_DFR) | (1 << PD1) | (1 << PD0);
|
||||
|
||||
//printf("touch cmd: %d\n", cmd);
|
||||
// spi.writeByte(cmd);
|
||||
// uint8_t v1 = spi.readByte();
|
||||
// uint8_t v2 = spi.readByte();
|
||||
// spi.read(buf, 2);
|
||||
|
||||
// mainly needed for hardware SPI, where send8+read8+read8 does not work as expected
|
||||
// output: cccccccc 00000000 00000000 00000000
|
||||
// input: -------- -rrrrrrr rrrrr--- --------
|
||||
const uint32_t tmp = spi.readWriteQuad(cmd << 24);
|
||||
const uint8_t v1 = (tmp >> 16) & 0xFF;
|
||||
const uint8_t v2 = (tmp >> 8) & 0xFF;
|
||||
const uint16_t res = (v1 << 8 | v2) >> 3;
|
||||
|
||||
//printf("res: %d\n", res);
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
bool isTouched() {
|
||||
|
||||
// read Y-axis in non-differential mode. if result is close to 4095, screen is not touched
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (read(1,false) > 3900) {return false;}
|
||||
}
|
||||
|
||||
// read X-axis in non-differential mode. if result is close to 4095, screen is not touched
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (read(5,false) > 3900) {return false;}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
uint16_t readAvg(const int inp) {
|
||||
|
||||
// dummy-reads to stabilize the result
|
||||
for (int i = 0; i < 4; ++i) {read(inp, true);}
|
||||
|
||||
// perform several reads and estimate std-dev
|
||||
static constexpr uint8_t cnt = 12;
|
||||
uint32_t sum = 0;
|
||||
uint32_t sum2 = 0;
|
||||
for (int i = 0; i < cnt; ++i) {
|
||||
const uint16_t cur = read(inp, true);
|
||||
sum += cur;
|
||||
sum2 += cur*cur;
|
||||
}
|
||||
const uint32_t stdDev = (sum2/cnt) - (sum/cnt)*(sum/cnt);
|
||||
//printf("%d\n", stdDev);
|
||||
|
||||
return (stdDev < 4096) ? ((sum/cnt)&0xFFFF) : (0xFFFF);
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // XPT2046_H
|
||||
Reference in New Issue
Block a user