mirror of https://github.com/arendst/Tasmota.git
Merge pull request #10171 from gemu2015/core2_support
m5stack core2 support
This commit is contained in:
commit
e6d815c762
|
@ -60,6 +60,15 @@
|
|||
#define ILI9341_2_HWSPI
|
||||
#endif
|
||||
|
||||
#if defined (ILI9341_2_HWSPI)
|
||||
#define SPI_BEGIN_TRANSACTION() if (_hwspi) spi2->beginTransaction(sspi2)
|
||||
#define SPI_END_TRANSACTION() if (_hwspi) spi2->endTransaction()
|
||||
#else
|
||||
#define SPI_BEGIN_TRANSACTION() (void)
|
||||
#define SPI_END_TRANSACTION() (void)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
const uint16_t ili9341_2_colors[]={ILI9341_2_BLACK,ILI9341_2_WHITE,ILI9341_2_RED,ILI9341_2_GREEN,ILI9341_2_BLUE,ILI9341_2_CYAN,ILI9341_2_MAGENTA,\
|
||||
ILI9341_2_YELLOW,ILI9341_2_NAVY,ILI9341_2_DARKGREEN,ILI9341_2_DARKCYAN,ILI9341_2_MAROON,ILI9341_2_PURPLE,ILI9341_2_OLIVE,\
|
||||
|
@ -99,6 +108,32 @@ static const uint8_t PROGMEM ili9341_2_initcmd[] = {
|
|||
0x00 // End of list
|
||||
};
|
||||
|
||||
static const uint8_t PROGMEM ili9342_initcmd[] = {
|
||||
0xEF, 3, 0x03, 0x80, 0x02,
|
||||
0xCF, 3, 0x00, 0xC1, 0x30,
|
||||
0xED, 4, 0x64, 0x03, 0x12, 0x81,
|
||||
0xE8, 3, 0x85, 0x00, 0x78,
|
||||
0xCB, 5, 0x39, 0x2C, 0x00, 0x34, 0x02,
|
||||
0xF7, 1, 0x20,
|
||||
0xEA, 2, 0x00, 0x00,
|
||||
ILI9341_2_PWCTR1 , 1, 0x23, // Power control VRH[5:0]
|
||||
ILI9341_2_PWCTR2 , 1, 0x10, // Power control SAP[2:0];BT[3:0]
|
||||
ILI9341_2_VMCTR1 , 2, 0x2B, 0x2B, // 0x3e, 0x28, // VCM control
|
||||
ILI9341_2_VMCTR2 , 1, 0xC0, // VCM control2
|
||||
ILI9341_2_MADCTL , 1, 0x48, // Memory Access Control
|
||||
ILI9341_2_VSCRSADD, 1, 0x00, // Vertical scroll zero
|
||||
ILI9341_2_PIXFMT , 1, 0x55,
|
||||
ILI9341_2_FRMCTR1 , 2, 0x00, 0x1B,
|
||||
ILI9341_2_DFUNCTR , 3, 0x08, 0x82, 0x27, // Display Function Control
|
||||
0xF2, 1, 0x00, // 3Gamma Function Disable
|
||||
ILI9341_2_GAMMASET , 1, 0x01, // Gamma curve selected
|
||||
ILI9341_2_GMCTRP1 , 15, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00,
|
||||
ILI9341_2_GMCTRN1 , 15, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F,
|
||||
ILI9341_2_INVON , 0x80,
|
||||
ILI9341_2_SLPOUT , 0x80, // Exit Sleep
|
||||
ILI9341_2_DISPON , 0x80, // Display on
|
||||
0x00 // End of list
|
||||
};
|
||||
|
||||
ILI9341_2::ILI9341_2(int8_t cs, int8_t mosi, int8_t miso, int8_t sclk, int8_t res, int8_t dc, int8_t bp) : Renderer(ILI9341_2_TFTWIDTH, ILI9341_2_TFTHEIGHT) {
|
||||
_cs = cs;
|
||||
|
@ -108,7 +143,16 @@ ILI9341_2::ILI9341_2(int8_t cs, int8_t mosi, int8_t miso, int8_t sclk, int8_t re
|
|||
_res = res;
|
||||
_dc = dc;
|
||||
_bp = bp;
|
||||
_hwspi = 0;
|
||||
_hwspi = 1;
|
||||
}
|
||||
|
||||
// special init for ILI9342
|
||||
ILI9341_2::ILI9341_2(int8_t cs, int8_t res, int8_t dc, int8_t bp) : Renderer(ILI9341_2_TFTWIDTH, ILI9341_2_TFTHEIGHT) {
|
||||
_cs = cs;
|
||||
_res = res;
|
||||
_dc = dc;
|
||||
_bp = bp;
|
||||
_hwspi = 2;
|
||||
}
|
||||
|
||||
#define ILI9341_2_CS_LOW digitalWrite( _cs, LOW);
|
||||
|
@ -128,12 +172,25 @@ void ILI9341_2::writecmd(uint8_t d) {
|
|||
void ILI9341_2::init(uint16_t width, uint16_t height) {
|
||||
//sspi2 = SPISettings(2500000, MSBFIRST, SPI_MODE3);
|
||||
|
||||
if (_hwspi==2) {
|
||||
iwidth=ILI9341_2_TFTWIDTH;
|
||||
iheight=ILI9341_2_TFTHEIGHT;
|
||||
} else {
|
||||
iwidth=ILI9341_2_TFTHEIGHT;
|
||||
iheight=ILI9341_2_TFTWIDTH;
|
||||
}
|
||||
|
||||
#ifdef ILI9341_2_HWSPI
|
||||
spi2 = new SPIClass(HSPI);
|
||||
spi2->setDataMode(SPI_MODE3);
|
||||
spi2->setBitOrder(MSBFIRST);
|
||||
spi2->setFrequency(40000000);
|
||||
spi2->begin(_sclk, _miso, _mosi, -1);
|
||||
|
||||
sspi2 = SPISettings(40000000, MSBFIRST, SPI_MODE0);
|
||||
|
||||
if (_hwspi==2) {
|
||||
spi2=&SPI;
|
||||
} else {
|
||||
spi2 = new SPIClass(HSPI);
|
||||
spi2->begin(_sclk, _miso, _mosi, -1);
|
||||
}
|
||||
|
||||
#else
|
||||
pinMode(_mosi, OUTPUT);
|
||||
digitalWrite(_mosi,HIGH);
|
||||
|
@ -144,13 +201,31 @@ void ILI9341_2::init(uint16_t width, uint16_t height) {
|
|||
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs,HIGH);
|
||||
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc,HIGH);
|
||||
pinMode(_bp, OUTPUT);
|
||||
digitalWrite(_bp,HIGH);
|
||||
pinMode(_res, OUTPUT);
|
||||
digitalWrite(_res,HIGH);
|
||||
|
||||
if (_bp>=0) {
|
||||
pinMode(_bp, OUTPUT);
|
||||
digitalWrite(_bp,HIGH);
|
||||
}
|
||||
|
||||
if (_res>=0) {
|
||||
pinMode(_res, OUTPUT);
|
||||
digitalWrite(_res, HIGH);
|
||||
delay(100);
|
||||
digitalWrite(_res, LOW);
|
||||
delay(100);
|
||||
digitalWrite(_res, HIGH);
|
||||
delay(200);
|
||||
} else {
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
ILI9341_2_CS_LOW
|
||||
writecmd(ILI9341_2_SWRESET); // software reset
|
||||
ILI9341_2_CS_HIGH
|
||||
SPI_END_TRANSACTION();
|
||||
delay(150);
|
||||
}
|
||||
|
||||
if (_bp>=0) {
|
||||
#ifdef ILI9341_2_DIMMER
|
||||
|
@ -162,16 +237,16 @@ void ILI9341_2::init(uint16_t width, uint16_t height) {
|
|||
#endif
|
||||
}
|
||||
|
||||
pinMode(_res, OUTPUT);
|
||||
digitalWrite(_res, HIGH);
|
||||
delay(100);
|
||||
digitalWrite(_res, LOW);
|
||||
delay(100);
|
||||
digitalWrite(_res, HIGH);
|
||||
delay(200);
|
||||
|
||||
uint8_t cmd, x, numArgs;
|
||||
const uint8_t *addr = ili9341_2_initcmd;
|
||||
const uint8_t *addr;
|
||||
|
||||
if (_hwspi<2) {
|
||||
addr = ili9341_2_initcmd;
|
||||
} else {
|
||||
addr = ili9342_initcmd;
|
||||
}
|
||||
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
|
||||
while ((cmd = pgm_read_byte(addr++)) > 0) {
|
||||
ILI9341_2_CS_LOW
|
||||
|
@ -188,11 +263,15 @@ void ILI9341_2::init(uint16_t width, uint16_t height) {
|
|||
ILI9341_2_CS_HIGH
|
||||
if(x & 0x80) delay(120);
|
||||
}
|
||||
SPI_END_TRANSACTION();
|
||||
|
||||
// endWrite();
|
||||
}
|
||||
|
||||
void ILI9341_2::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) {
|
||||
// SPI_BEGIN_TRANSACTION();
|
||||
// writecmd(ILI9341_2_INVOFF);
|
||||
// SPI_END_TRANSACTION();
|
||||
setRotation(rot);
|
||||
setTextFont(font&3);
|
||||
setTextSize(size&7);
|
||||
|
@ -201,9 +280,37 @@ void ILI9341_2::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) {
|
|||
fillScreen(ILI9341_2_BLACK);
|
||||
}
|
||||
|
||||
void ILI9341_2::setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
|
||||
void ILI9341_2::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
|
||||
|
||||
if (!x0 && !y0 && !x1 && !y1) {
|
||||
ILI9341_2_CS_HIGH
|
||||
SPI_END_TRANSACTION();
|
||||
} else {
|
||||
ILI9341_2_CS_LOW
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
setAddrWindow_int(x0,y0,x1-x0,y1-y0);
|
||||
}
|
||||
}
|
||||
|
||||
void ILI9341_2::pushColors(uint16_t *data, uint8_t len, boolean first) {
|
||||
uint16_t color;
|
||||
|
||||
while (len--) {
|
||||
color = *data++;
|
||||
#ifdef ILI9341_2_HWSPI
|
||||
spi2->write16(color);
|
||||
#else
|
||||
spiwrite16(color);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ILI9341_2::setAddrWindow_int(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
|
||||
uint32_t xa = ((uint32_t)x << 16) | (x+w-1);
|
||||
uint32_t ya = ((uint32_t)y << 16) | (y+h-1);
|
||||
|
||||
|
||||
writecmd(ILI9341_2_CASET); // Column addr set
|
||||
#ifdef ILI9341_2_HWSPI
|
||||
spi2->write32(xa);
|
||||
|
@ -218,6 +325,8 @@ void ILI9341_2::setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
|
|||
spiwrite32(ya);
|
||||
#endif
|
||||
writecmd(ILI9341_2_RAMWR); // write to RAM
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ILI9341_2::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
|
@ -227,7 +336,10 @@ void ILI9341_2::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
|||
|
||||
ILI9341_2_CS_LOW
|
||||
|
||||
setAddrWindow(x,y,1,1);
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
|
||||
setAddrWindow_int(x,y,1,1);
|
||||
|
||||
|
||||
#ifdef ILI9341_2_HWSPI
|
||||
spi2->write16(color);
|
||||
|
@ -236,39 +348,80 @@ void ILI9341_2::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
|||
#endif
|
||||
ILI9341_2_CS_HIGH
|
||||
|
||||
SPI_END_TRANSACTION();
|
||||
}
|
||||
|
||||
|
||||
void ILI9341_2::setRotation(uint8_t m) {
|
||||
|
||||
if (_hwspi<2) {
|
||||
rotation = m % 4; // can't be higher than 3
|
||||
switch (rotation) {
|
||||
case 0:
|
||||
m = (MADCTL_2_MX | MADCTL_2_BGR);
|
||||
_width = ILI9341_2_TFTWIDTH;
|
||||
_height = ILI9341_2_TFTHEIGHT;
|
||||
_width = iwidth;
|
||||
_height = iheight;
|
||||
break;
|
||||
case 1:
|
||||
m = (MADCTL_2_MV | MADCTL_2_BGR);
|
||||
_width = ILI9341_2_TFTHEIGHT;
|
||||
_height = ILI9341_2_TFTWIDTH;
|
||||
_width = iheight;
|
||||
_height = iwidth;
|
||||
break;
|
||||
case 2:
|
||||
m = (MADCTL_2_MY | MADCTL_2_BGR);
|
||||
_width = ILI9341_2_TFTWIDTH;
|
||||
_height = ILI9341_2_TFTHEIGHT;
|
||||
_width = iwidth;
|
||||
_height = iheight;
|
||||
break;
|
||||
case 3:
|
||||
m = (MADCTL_2_MX | MADCTL_2_MY | MADCTL_2_MV | MADCTL_2_BGR);
|
||||
_width = ILI9341_2_TFTHEIGHT;
|
||||
_height = ILI9341_2_TFTWIDTH;
|
||||
_width = iheight;
|
||||
_height = iwidth;
|
||||
break;
|
||||
}
|
||||
|
||||
ILI9341_2_CS_LOW
|
||||
writecmd(ILI9341_2_MADCTL);
|
||||
spiwrite(m);
|
||||
ILI9341_2_CS_HIGH
|
||||
} else {
|
||||
|
||||
#define MADCTL_MY 0x80 ///< Bottom to top
|
||||
#define MADCTL_MX 0x40 ///< Right to left
|
||||
#define MADCTL_MV 0x20 ///< Reverse Mode
|
||||
#define MADCTL_ML 0x10 ///< LCD refresh Bottom to top
|
||||
#define MADCTL_RGB 0x00 ///< Red-Green-Blue pixel order
|
||||
#define MADCTL_BGR 0x08 ///< Blue-Green-Red pixel order
|
||||
#define MADCTL_MH 0x04 ///< LCD refresh right to left
|
||||
|
||||
rotation = m % 4; // can't be higher than 3
|
||||
switch (rotation) {
|
||||
case 0:
|
||||
m = (MADCTL_BGR);
|
||||
_width = iwidth;
|
||||
_height = iheight;
|
||||
break;
|
||||
case 1:
|
||||
m = (MADCTL_MV | MADCTL_BGR);
|
||||
_width = iheight;
|
||||
_height = iwidth;
|
||||
break;
|
||||
case 2:
|
||||
m = (MADCTL_MY | MADCTL_BGR);
|
||||
_width = iwidth;
|
||||
_height = iheight;
|
||||
break;
|
||||
case 3:
|
||||
m = (MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR);
|
||||
_width = iheight;
|
||||
_height = iwidth;
|
||||
break;
|
||||
}
|
||||
}
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
ILI9341_2_CS_LOW
|
||||
writecmd(ILI9341_2_MADCTL);
|
||||
spiwrite(m);
|
||||
ILI9341_2_CS_HIGH
|
||||
SPI_END_TRANSACTION();
|
||||
}
|
||||
|
||||
|
||||
void ILI9341_2::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
|
||||
|
||||
// Rudimentary clipping
|
||||
|
@ -277,7 +430,10 @@ void ILI9341_2::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
|
|||
|
||||
ILI9341_2_CS_LOW
|
||||
|
||||
setAddrWindow(x, y, 1, h);
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
|
||||
setAddrWindow_int(x, y, 1, h);
|
||||
|
||||
|
||||
while (h--) {
|
||||
#ifdef ILI9341_2_HWSPI
|
||||
|
@ -289,6 +445,7 @@ void ILI9341_2::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
|
|||
|
||||
ILI9341_2_CS_HIGH
|
||||
|
||||
SPI_END_TRANSACTION();
|
||||
}
|
||||
|
||||
void ILI9341_2::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
|
||||
|
@ -299,7 +456,10 @@ void ILI9341_2::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
|
|||
|
||||
ILI9341_2_CS_LOW
|
||||
|
||||
setAddrWindow(x, y, w, 1);
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
|
||||
setAddrWindow_int(x, y, w, 1);
|
||||
|
||||
|
||||
while (w--) {
|
||||
#ifdef ILI9341_2_HWSPI
|
||||
|
@ -310,6 +470,8 @@ void ILI9341_2::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
|
|||
}
|
||||
|
||||
ILI9341_2_CS_HIGH
|
||||
|
||||
SPI_END_TRANSACTION();
|
||||
}
|
||||
|
||||
void ILI9341_2::fillScreen(uint16_t color) {
|
||||
|
@ -326,7 +488,9 @@ void ILI9341_2::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t co
|
|||
|
||||
ILI9341_2_CS_LOW
|
||||
|
||||
setAddrWindow(x, y, w-1, h-1);
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
|
||||
setAddrWindow_int(x, y, w, h);
|
||||
|
||||
for (y=h; y>0; y--) {
|
||||
for (x=w; x>0; x--) {
|
||||
|
@ -338,11 +502,26 @@ void ILI9341_2::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t co
|
|||
}
|
||||
}
|
||||
ILI9341_2_CS_HIGH
|
||||
|
||||
SPI_END_TRANSACTION();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ili9342_bpwr(uint8_t on);
|
||||
|
||||
void ILI9341_2::DisplayOnff(int8_t on) {
|
||||
|
||||
if (_hwspi==2) {
|
||||
ili9342_bpwr(on);
|
||||
}
|
||||
|
||||
if (on) {
|
||||
writecmd(ILI9341_2_DISPON); //Display on
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
ILI9341_2_CS_LOW
|
||||
writecmd(ILI9341_2_DISPON);
|
||||
ILI9341_2_CS_HIGH
|
||||
SPI_END_TRANSACTION();
|
||||
if (_bp>=0) {
|
||||
#ifdef ILI9341_2_DIMMER
|
||||
ledcWrite(ESP32_PWM_CHANNEL,dimmer);
|
||||
|
@ -351,7 +530,11 @@ void ILI9341_2::DisplayOnff(int8_t on) {
|
|||
#endif
|
||||
}
|
||||
} else {
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
ILI9341_2_CS_LOW
|
||||
writecmd(ILI9341_2_DISPOFF);
|
||||
ILI9341_2_CS_HIGH
|
||||
SPI_END_TRANSACTION();
|
||||
if (_bp>=0) {
|
||||
#ifdef ILI9341_2_DIMMER
|
||||
ledcWrite(ESP32_PWM_CHANNEL,0);
|
||||
|
@ -362,13 +545,21 @@ void ILI9341_2::DisplayOnff(int8_t on) {
|
|||
}
|
||||
}
|
||||
|
||||
void ili9342_dimm(uint8_t dim);
|
||||
|
||||
// dimmer 0-100
|
||||
void ILI9341_2::dim(uint8_t dim) {
|
||||
dimmer = dim;
|
||||
if (dimmer>15) dimmer=15;
|
||||
dimmer=((float)dimmer/15.0)*255.0;
|
||||
#ifdef ESP32
|
||||
ledcWrite(ESP32_PWM_CHANNEL,dimmer);
|
||||
if (_bp>=0) {
|
||||
ledcWrite(ESP32_PWM_CHANNEL,dimmer);
|
||||
} else {
|
||||
if (_hwspi==2) {
|
||||
ili9342_dimm(dim);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <SPI.h>
|
||||
|
||||
#define ILI9341_2_TFTWIDTH 320
|
||||
#define ILI9341_2_TFTHEIGHT 480
|
||||
#define ILI9341_2_TFTHEIGHT 240
|
||||
|
||||
#define ILI9341_2_NOP 0x00 ///< No-op register
|
||||
#define ILI9341_2_SWRESET 0x01 ///< Software reset register
|
||||
|
@ -116,6 +116,7 @@ class ILI9341_2 : public Renderer {
|
|||
public:
|
||||
|
||||
ILI9341_2(int8_t cs, int8_t mosi, int8_t miso, int8_t sclk, int8_t res, int8_t dc, int8_t bp);
|
||||
ILI9341_2(int8_t cs, int8_t res, int8_t dc, int8_t bp);
|
||||
|
||||
void init(uint16_t width, uint16_t height);
|
||||
/*
|
||||
|
@ -148,7 +149,8 @@ class ILI9341_2 : public Renderer {
|
|||
SPIClass *spi2;
|
||||
SPISettings sspi2;
|
||||
void writecmd(uint8_t d);
|
||||
void setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
|
||||
void setAddrWindow(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
|
||||
void setAddrWindow_int(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
void DisplayOnff(int8_t on);
|
||||
void setRotation(uint8_t m);
|
||||
|
@ -158,7 +160,7 @@ class ILI9341_2 : public Renderer {
|
|||
void fillScreen(uint16_t color);
|
||||
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||
void dim(uint8_t dim);
|
||||
|
||||
void pushColors(uint16_t *data, uint8_t len, boolean first);
|
||||
|
||||
void spiwrite(uint8_t c);
|
||||
void spiwrite16(uint16_t c);
|
||||
|
@ -174,6 +176,8 @@ class ILI9341_2 : public Renderer {
|
|||
int8_t _dc;
|
||||
int8_t _bp;
|
||||
int8_t _hwspi;
|
||||
uint16_t iwidth;
|
||||
uint16_t iheight;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,614 @@
|
|||
#include "AXP192.h"
|
||||
|
||||
//#define AXP192_DEBUG
|
||||
|
||||
AXP192::AXP192()
|
||||
{
|
||||
}
|
||||
|
||||
void AXP192::begin(void)
|
||||
{
|
||||
|
||||
Wire1.begin(21, 22);
|
||||
Wire1.setClock(400000);
|
||||
|
||||
//AXP192 30H
|
||||
Write1Byte(0x30, (Read8bit(0x30) & 0x04) | 0X02);
|
||||
#ifdef AXP192_DEBUG
|
||||
Serial.printf("axp: vbus limit off\n");
|
||||
#endif
|
||||
|
||||
//AXP192 GPIO1:OD OUTPUT
|
||||
Write1Byte(0x92, Read8bit(0x92) & 0xf8);
|
||||
#ifdef AXP192_DEBUG
|
||||
Serial.printf("axp: gpio1 init\n");
|
||||
#endif
|
||||
//AXP192 GPIO2:OD OUTPUT
|
||||
Write1Byte(0x93, Read8bit(0x93) & 0xf8);
|
||||
#ifdef AXP192_DEBUG
|
||||
Serial.printf("axp: gpio2 init\n");
|
||||
#endif
|
||||
//AXP192 RTC CHG
|
||||
Write1Byte(0x35, (Read8bit(0x35) & 0x1c) | 0xa2);
|
||||
#ifdef AXP192_DEBUG
|
||||
Serial.printf("axp: rtc battery charging enabled\n");
|
||||
#endif
|
||||
SetESPVoltage(3350);
|
||||
#ifdef AXP192_DEBUG
|
||||
Serial.printf("axp: esp32 power voltage was set to 3.35v\n");
|
||||
#endif
|
||||
SetLcdVoltage(2800);
|
||||
#ifdef AXP192_DEBUG
|
||||
Serial.printf("axp: lcd backlight voltage was set to 2.80v\n");
|
||||
#endif
|
||||
SetLDOVoltage(2, 3300); //Periph power voltage preset (LCD_logic, SD card)
|
||||
#ifdef AXP192_DEBUG
|
||||
Serial.printf("axp: lcd logic and sdcard voltage preset to 3.3v\n");
|
||||
#endif
|
||||
SetLDOVoltage(3, 2000); //Vibrator power voltage preset
|
||||
#ifdef AXP192_DEBUG
|
||||
Serial.printf("axp: vibrator voltage preset to 2v\n");
|
||||
#endif
|
||||
|
||||
SetLDOEnable(2, true);
|
||||
SetDCDC3(true); // LCD backlight
|
||||
SetLed(true);
|
||||
|
||||
SetCHGCurrent(kCHG_100mA);
|
||||
//SetAxpPriphPower(1);
|
||||
//Serial.printf("axp: lcd_logic and sdcard power enabled\n\n");
|
||||
|
||||
//pinMode(39, INPUT_PULLUP);
|
||||
|
||||
//AXP192 GPIO4
|
||||
Write1Byte(0X95, (Read8bit(0x95) & 0x72) | 0X84);
|
||||
|
||||
Write1Byte(0X36, 0X4C);
|
||||
|
||||
Write1Byte(0x82,0xff);
|
||||
|
||||
SetLCDRSet(0);
|
||||
delay(100);
|
||||
SetLCDRSet(1);
|
||||
delay(100);
|
||||
// I2C_WriteByteDataAt(0X15,0XFE,0XFF);
|
||||
|
||||
// bus power mode_output
|
||||
SetBusPowerMode(0);
|
||||
}
|
||||
|
||||
void AXP192::Write1Byte(uint8_t Addr, uint8_t Data)
|
||||
{
|
||||
Wire1.beginTransmission(0x34);
|
||||
Wire1.write(Addr);
|
||||
Wire1.write(Data);
|
||||
Wire1.endTransmission();
|
||||
}
|
||||
|
||||
uint8_t AXP192::Read8bit(uint8_t Addr)
|
||||
{
|
||||
Wire1.beginTransmission(0x34);
|
||||
Wire1.write(Addr);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x34, 1);
|
||||
return Wire1.read();
|
||||
}
|
||||
|
||||
uint16_t AXP192::Read12Bit(uint8_t Addr)
|
||||
{
|
||||
uint16_t Data = 0;
|
||||
uint8_t buf[2];
|
||||
ReadBuff(Addr, 2, buf);
|
||||
Data = ((buf[0] << 4) + buf[1]); //
|
||||
return Data;
|
||||
}
|
||||
|
||||
uint16_t AXP192::Read13Bit(uint8_t Addr)
|
||||
{
|
||||
uint16_t Data = 0;
|
||||
uint8_t buf[2];
|
||||
ReadBuff(Addr, 2, buf);
|
||||
Data = ((buf[0] << 5) + buf[1]); //
|
||||
return Data;
|
||||
}
|
||||
|
||||
uint16_t AXP192::Read16bit(uint8_t Addr)
|
||||
{
|
||||
uint16_t ReData = 0;
|
||||
Wire1.beginTransmission(0x34);
|
||||
Wire1.write(Addr);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x34, 2);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
ReData <<= 8;
|
||||
ReData |= Wire1.read();
|
||||
}
|
||||
return ReData;
|
||||
}
|
||||
|
||||
uint32_t AXP192::Read24bit(uint8_t Addr)
|
||||
{
|
||||
uint32_t ReData = 0;
|
||||
Wire1.beginTransmission(0x34);
|
||||
Wire1.write(Addr);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x34, 3);
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
ReData <<= 8;
|
||||
ReData |= Wire1.read();
|
||||
}
|
||||
return ReData;
|
||||
}
|
||||
|
||||
uint32_t AXP192::Read32bit(uint8_t Addr)
|
||||
{
|
||||
uint32_t ReData = 0;
|
||||
Wire1.beginTransmission(0x34);
|
||||
Wire1.write(Addr);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x34, 2);
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
ReData <<= 8;
|
||||
ReData |= Wire1.read();
|
||||
}
|
||||
return ReData;
|
||||
}
|
||||
|
||||
void AXP192::ReadBuff(uint8_t Addr, uint8_t Size, uint8_t *Buff)
|
||||
{
|
||||
Wire1.beginTransmission(0x34);
|
||||
Wire1.write(Addr);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x34, (int)Size);
|
||||
for (int i = 0; i < Size; i++)
|
||||
{
|
||||
*(Buff + i) = Wire1.read();
|
||||
}
|
||||
}
|
||||
|
||||
void AXP192::ScreenBreath(uint8_t brightness)
|
||||
{
|
||||
if (brightness > 12)
|
||||
{
|
||||
brightness = 12;
|
||||
}
|
||||
uint8_t buf = Read8bit(0x28);
|
||||
Write1Byte(0x28, ((buf & 0x0f) | (brightness << 4)));
|
||||
}
|
||||
|
||||
bool AXP192::GetBatState()
|
||||
{
|
||||
if (Read8bit(0x01) | 0x20)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
//---------coulombcounter_from_here---------
|
||||
//enable: void EnableCoulombcounter(void);
|
||||
//disable: void DisableCOulombcounter(void);
|
||||
//stop: void StopCoulombcounter(void);
|
||||
//clear: void ClearCoulombcounter(void);
|
||||
//get charge data: uint32_t GetCoulombchargeData(void);
|
||||
//get discharge data: uint32_t GetCoulombdischargeData(void);
|
||||
//get coulomb val affter calculation: float GetCoulombData(void);
|
||||
//------------------------------------------
|
||||
void AXP192::EnableCoulombcounter(void)
|
||||
{
|
||||
Write1Byte(0xB8, 0x80);
|
||||
}
|
||||
|
||||
void AXP192::DisableCoulombcounter(void)
|
||||
{
|
||||
Write1Byte(0xB8, 0x00);
|
||||
}
|
||||
|
||||
void AXP192::StopCoulombcounter(void)
|
||||
{
|
||||
Write1Byte(0xB8, 0xC0);
|
||||
}
|
||||
|
||||
void AXP192::ClearCoulombcounter(void)
|
||||
{
|
||||
Write1Byte(0xB8, 0xA0);
|
||||
}
|
||||
|
||||
uint32_t AXP192::GetCoulombchargeData(void)
|
||||
{
|
||||
return Read32bit(0xB0);
|
||||
}
|
||||
|
||||
uint32_t AXP192::GetCoulombdischargeData(void)
|
||||
{
|
||||
return Read32bit(0xB4);
|
||||
}
|
||||
|
||||
float AXP192::GetCoulombData(void)
|
||||
{
|
||||
|
||||
uint32_t coin = 0;
|
||||
uint32_t coout = 0;
|
||||
|
||||
coin = GetCoulombchargeData();
|
||||
coout = GetCoulombdischargeData();
|
||||
|
||||
//c = 65536 * current_LSB * (coin - coout) / 3600 / ADC rate
|
||||
//Adc rate can be read from 84H ,change this variable if you change the ADC reate
|
||||
float ccc = 65536 * 0.5 * (coin - coout) / 3600.0 / 25.0;
|
||||
return ccc;
|
||||
}
|
||||
|
||||
// Cut all power, except for LDO1 (RTC)
|
||||
void AXP192::PowerOff(void)
|
||||
{
|
||||
Write1Byte(0x32, Read8bit(0x32) | 0b10000000);
|
||||
}
|
||||
|
||||
void AXP192::SetAdcState(bool state)
|
||||
{
|
||||
// Enable / Disable all ADCs
|
||||
Write1Byte(0x82, state ? 0xff : 0x00);
|
||||
}
|
||||
|
||||
void AXP192::PrepareToSleep(void)
|
||||
{
|
||||
// Disable ADCs
|
||||
SetAdcState(false);
|
||||
|
||||
// Turn LED off
|
||||
SetLed(false);
|
||||
|
||||
// Turn LCD backlight off
|
||||
SetDCDC3(false);
|
||||
}
|
||||
|
||||
void AXP192::RestoreFromLightSleep(void)
|
||||
{
|
||||
// Turn LCD backlight on
|
||||
SetDCDC3(true);
|
||||
|
||||
// Turn LED on
|
||||
SetLed(true);
|
||||
|
||||
// Enable ADCs
|
||||
SetAdcState(true);
|
||||
}
|
||||
|
||||
uint8_t AXP192::GetWarningLeve(void)
|
||||
{
|
||||
Wire1.beginTransmission(0x34);
|
||||
Wire1.write(0x47);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x34, 1);
|
||||
uint8_t buf = Wire1.read();
|
||||
return (buf & 0x01);
|
||||
}
|
||||
|
||||
// -- sleep
|
||||
void AXP192::DeepSleep(uint64_t time_in_us)
|
||||
{
|
||||
PrepareToSleep();
|
||||
|
||||
if (time_in_us > 0)
|
||||
{
|
||||
esp_sleep_enable_timer_wakeup(time_in_us);
|
||||
}
|
||||
else
|
||||
{
|
||||
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);
|
||||
}
|
||||
(time_in_us == 0) ? esp_deep_sleep_start() : esp_deep_sleep(time_in_us);
|
||||
|
||||
// Never reached - after deep sleep ESP32 restarts
|
||||
}
|
||||
|
||||
void AXP192::LightSleep(uint64_t time_in_us)
|
||||
{
|
||||
PrepareToSleep();
|
||||
|
||||
if (time_in_us > 0)
|
||||
{
|
||||
esp_sleep_enable_timer_wakeup(time_in_us);
|
||||
}
|
||||
else
|
||||
{
|
||||
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);
|
||||
}
|
||||
esp_light_sleep_start();
|
||||
|
||||
RestoreFromLightSleep();
|
||||
}
|
||||
|
||||
uint8_t AXP192::GetWarningLevel(void)
|
||||
{
|
||||
return Read8bit(0x47) & 0x01;
|
||||
}
|
||||
|
||||
float AXP192::GetBatVoltage()
|
||||
{
|
||||
float ADCLSB = 1.1 / 1000.0;
|
||||
uint16_t ReData = Read12Bit(0x78);
|
||||
return ReData * ADCLSB;
|
||||
}
|
||||
|
||||
float AXP192::GetBatCurrent()
|
||||
{
|
||||
float ADCLSB = 0.5;
|
||||
uint16_t CurrentIn = Read13Bit(0x7A);
|
||||
uint16_t CurrentOut = Read13Bit(0x7C);
|
||||
return (CurrentIn - CurrentOut) * ADCLSB;
|
||||
}
|
||||
|
||||
float AXP192::GetVinVoltage()
|
||||
{
|
||||
float ADCLSB = 1.7 / 1000.0;
|
||||
uint16_t ReData = Read12Bit(0x56);
|
||||
return ReData * ADCLSB;
|
||||
}
|
||||
|
||||
float AXP192::GetVinCurrent()
|
||||
{
|
||||
float ADCLSB = 0.625;
|
||||
uint16_t ReData = Read12Bit(0x58);
|
||||
return ReData * ADCLSB;
|
||||
}
|
||||
|
||||
float AXP192::GetVBusVoltage()
|
||||
{
|
||||
float ADCLSB = 1.7 / 1000.0;
|
||||
uint16_t ReData = Read12Bit(0x5A);
|
||||
return ReData * ADCLSB;
|
||||
}
|
||||
|
||||
float AXP192::GetVBusCurrent()
|
||||
{
|
||||
float ADCLSB = 0.375;
|
||||
uint16_t ReData = Read12Bit(0x5C);
|
||||
return ReData * ADCLSB;
|
||||
}
|
||||
|
||||
float AXP192::GetTempInAXP192()
|
||||
{
|
||||
float ADCLSB = 0.1;
|
||||
const float OFFSET_DEG_C = -144.7;
|
||||
uint16_t ReData = Read12Bit(0x5E);
|
||||
return OFFSET_DEG_C + ReData * ADCLSB;
|
||||
}
|
||||
|
||||
float AXP192::GetBatPower()
|
||||
{
|
||||
float VoltageLSB = 1.1;
|
||||
float CurrentLCS = 0.5;
|
||||
uint32_t ReData = Read24bit(0x70);
|
||||
return VoltageLSB * CurrentLCS * ReData / 1000.0;
|
||||
}
|
||||
|
||||
float AXP192::GetBatChargeCurrent()
|
||||
{
|
||||
float ADCLSB = 0.5;
|
||||
uint16_t ReData = Read12Bit(0x7A);
|
||||
return ReData * ADCLSB;
|
||||
}
|
||||
float AXP192::GetAPSVoltage()
|
||||
{
|
||||
float ADCLSB = 1.4 / 1000.0;
|
||||
uint16_t ReData = Read12Bit(0x7E);
|
||||
return ReData * ADCLSB;
|
||||
}
|
||||
|
||||
float AXP192::GetBatCoulombInput()
|
||||
{
|
||||
uint32_t ReData = Read32bit(0xB0);
|
||||
return ReData * 65536 * 0.5 / 3600 / 25.0;
|
||||
}
|
||||
|
||||
float AXP192::GetBatCoulombOut()
|
||||
{
|
||||
uint32_t ReData = Read32bit(0xB4);
|
||||
return ReData * 65536 * 0.5 / 3600 / 25.0;
|
||||
}
|
||||
|
||||
void AXP192::SetCoulombClear()
|
||||
{
|
||||
Write1Byte(0xB8, 0x20);
|
||||
}
|
||||
|
||||
void AXP192::SetLDO2(bool State)
|
||||
{
|
||||
uint8_t buf = Read8bit(0x12);
|
||||
if (State == true)
|
||||
buf = (1 << 2) | buf;
|
||||
else
|
||||
buf = ~(1 << 2) & buf;
|
||||
Write1Byte(0x12, buf);
|
||||
}
|
||||
|
||||
void AXP192::SetDCDC3(bool State)
|
||||
{
|
||||
uint8_t buf = Read8bit(0x12);
|
||||
if (State == true)
|
||||
buf = (1 << 1) | buf;
|
||||
else
|
||||
buf = ~(1 << 1) & buf;
|
||||
Write1Byte(0x12, buf);
|
||||
}
|
||||
|
||||
uint8_t AXP192::AXPInState()
|
||||
{
|
||||
return Read8bit(0x00);
|
||||
}
|
||||
bool AXP192::isACIN()
|
||||
{
|
||||
return ( Read8bit(0x00) & 0x80 ) ? true : false;
|
||||
}
|
||||
bool AXP192::isCharging()
|
||||
{
|
||||
return ( Read8bit(0x00) & 0x04 ) ? true : false;
|
||||
}
|
||||
bool AXP192::isVBUS()
|
||||
{
|
||||
return ( Read8bit(0x00) & 0x20 ) ? true : false;
|
||||
}
|
||||
|
||||
void AXP192::SetLDOVoltage(uint8_t number, uint16_t voltage)
|
||||
{
|
||||
voltage = (voltage > 3300) ? 15 : (voltage / 100) - 18;
|
||||
switch (number)
|
||||
{
|
||||
//uint8_t reg, data;
|
||||
case 2:
|
||||
Write1Byte(0x28, (Read8bit(0x28) & 0X0F) | (voltage << 4));
|
||||
break;
|
||||
case 3:
|
||||
Write1Byte(0x28, (Read8bit(0x28) & 0XF0) | voltage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AXP192::SetDCVoltage(uint8_t number, uint16_t voltage)
|
||||
{
|
||||
uint8_t addr;
|
||||
if (number > 2)
|
||||
return;
|
||||
voltage = (voltage < 700) ? 0 : (voltage - 700) / 25;
|
||||
switch (number)
|
||||
{
|
||||
case 0:
|
||||
addr = 0x26;
|
||||
break;
|
||||
case 1:
|
||||
addr = 0x25;
|
||||
break;
|
||||
case 2:
|
||||
addr = 0x27;
|
||||
break;
|
||||
}
|
||||
Write1Byte(addr, (Read8bit(addr) & 0X80) | (voltage & 0X7F));
|
||||
}
|
||||
|
||||
void AXP192::SetESPVoltage(uint16_t voltage)
|
||||
{
|
||||
if (voltage >= 3000 && voltage <= 3400)
|
||||
{
|
||||
SetDCVoltage(0, voltage);
|
||||
}
|
||||
}
|
||||
void AXP192::SetLcdVoltage(uint16_t voltage)
|
||||
{
|
||||
if (voltage >= 2500 && voltage <= 3300)
|
||||
{
|
||||
SetDCVoltage(2, voltage);
|
||||
}
|
||||
}
|
||||
|
||||
void AXP192::SetLDOEnable(uint8_t number, bool state)
|
||||
{
|
||||
uint8_t mark = 0x01;
|
||||
if ((number < 2) || (number > 3))
|
||||
return;
|
||||
|
||||
mark <<= number;
|
||||
if (state)
|
||||
{
|
||||
Write1Byte(0x12, (Read8bit(0x12) | mark));
|
||||
}
|
||||
else
|
||||
{
|
||||
Write1Byte(0x12, (Read8bit(0x12) & (~mark)));
|
||||
}
|
||||
}
|
||||
|
||||
void AXP192::SetLCDRSet(bool state)
|
||||
{
|
||||
uint8_t reg_addr = 0x96;
|
||||
uint8_t gpio_bit = 0x02;
|
||||
uint8_t data;
|
||||
data = Read8bit(reg_addr);
|
||||
|
||||
if (state)
|
||||
{
|
||||
data |= gpio_bit;
|
||||
}
|
||||
else
|
||||
{
|
||||
data &= ~gpio_bit;
|
||||
}
|
||||
|
||||
Write1Byte(reg_addr, data);
|
||||
}
|
||||
|
||||
void AXP192::SetBusPowerMode(uint8_t state)
|
||||
{
|
||||
uint8_t data;
|
||||
if (state == 0)
|
||||
{
|
||||
data = Read8bit(0x91);
|
||||
Write1Byte(0x91, (data & 0X0F) | 0XF0);
|
||||
|
||||
data = Read8bit(0x90);
|
||||
Write1Byte(0x90, (data & 0XF8) | 0X02); //set GPIO0 to LDO OUTPUT , pullup N_VBUSEN to disable supply from BUS_5V
|
||||
|
||||
data = Read8bit(0x91);
|
||||
|
||||
data = Read8bit(0x12); //read reg 0x12
|
||||
Write1Byte(0x12, data | 0x40); //set EXTEN to enable 5v boost
|
||||
}
|
||||
else
|
||||
{
|
||||
data = Read8bit(0x12); //read reg 0x10
|
||||
Write1Byte(0x12, data & 0XBF); //set EXTEN to disable 5v boost
|
||||
|
||||
//delay(2000);
|
||||
|
||||
data = Read8bit(0x90);
|
||||
Write1Byte(0x90, (data & 0xF8) | 0X01); //set GPIO0 to float , using enternal pulldown resistor to enable supply from BUS_5VS
|
||||
}
|
||||
}
|
||||
|
||||
void AXP192::SetLed(uint8_t state)
|
||||
{
|
||||
uint8_t reg_addr=0x94;
|
||||
uint8_t data;
|
||||
data=Read8bit(reg_addr);
|
||||
|
||||
if(state)
|
||||
{
|
||||
data=data&0XFD;
|
||||
}
|
||||
else
|
||||
{
|
||||
data|=0X02;
|
||||
}
|
||||
|
||||
Write1Byte(reg_addr,data);
|
||||
}
|
||||
|
||||
//set led state(GPIO high active,set 1 to enable amplifier)
|
||||
void AXP192::SetSpkEnable(uint8_t state)
|
||||
{
|
||||
uint8_t reg_addr=0x94;
|
||||
uint8_t gpio_bit=0x04;
|
||||
uint8_t data;
|
||||
data=Read8bit(reg_addr);
|
||||
|
||||
if(state)
|
||||
{
|
||||
data|=gpio_bit;
|
||||
}
|
||||
else
|
||||
{
|
||||
data&=~gpio_bit;
|
||||
}
|
||||
|
||||
Write1Byte(reg_addr,data);
|
||||
}
|
||||
|
||||
void AXP192::SetCHGCurrent(uint8_t state)
|
||||
{
|
||||
uint8_t data = Read8bit(0x33);
|
||||
data &= 0xf0;
|
||||
data = data | ( state & 0x0f );
|
||||
Write1Byte(0x33,data);
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
#ifndef __AXP192_H__
|
||||
#define __AXP192_H__
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
#define SLEEP_MSEC(us) (((uint64_t)us) * 1000L)
|
||||
#define SLEEP_SEC(us) (((uint64_t)us) * 1000000L)
|
||||
#define SLEEP_MIN(us) (((uint64_t)us) * 60L * 1000000L)
|
||||
#define SLEEP_HR(us) (((uint64_t)us) * 60L * 60L * 1000000L)
|
||||
|
||||
#define AXP_ADDR 0X34
|
||||
|
||||
#define PowerOff(x) SetSleep(x)
|
||||
|
||||
class AXP192 {
|
||||
public:
|
||||
|
||||
enum CHGCurrent{
|
||||
kCHG_100mA = 0,
|
||||
kCHG_190mA,
|
||||
kCHG_280mA,
|
||||
kCHG_360mA,
|
||||
kCHG_450mA,
|
||||
kCHG_550mA,
|
||||
kCHG_630mA,
|
||||
kCHG_700mA,
|
||||
kCHG_780mA,
|
||||
kCHG_880mA,
|
||||
kCHG_960mA,
|
||||
kCHG_1000mA,
|
||||
kCHG_1080mA,
|
||||
kCHG_1160mA,
|
||||
kCHG_1240mA,
|
||||
kCHG_1320mA,
|
||||
};
|
||||
|
||||
AXP192();
|
||||
void begin(void);
|
||||
void ScreenBreath(uint8_t brightness);
|
||||
bool GetBatState();
|
||||
|
||||
void EnableCoulombcounter(void);
|
||||
void DisableCoulombcounter(void);
|
||||
void StopCoulombcounter(void);
|
||||
void ClearCoulombcounter(void);
|
||||
uint32_t GetCoulombchargeData(void);
|
||||
uint32_t GetCoulombdischargeData(void);
|
||||
float GetCoulombData(void);
|
||||
void PowerOff(void);
|
||||
void SetAdcState(bool state);
|
||||
// -- sleep
|
||||
void PrepareToSleep(void);
|
||||
void RestoreFromLightSleep(void);
|
||||
void DeepSleep(uint64_t time_in_us = 0);
|
||||
void LightSleep(uint64_t time_in_us = 0);
|
||||
uint8_t GetWarningLeve(void);
|
||||
|
||||
public:
|
||||
// void SetChargeVoltage( uint8_t );
|
||||
// void SetChargeCurrent( uint8_t );
|
||||
float GetBatVoltage();
|
||||
float GetBatCurrent();
|
||||
float GetVinVoltage();
|
||||
float GetVinCurrent();
|
||||
float GetVBusVoltage();
|
||||
float GetVBusCurrent();
|
||||
float GetTempInAXP192();
|
||||
float GetBatPower();
|
||||
float GetBatChargeCurrent();
|
||||
float GetAPSVoltage();
|
||||
float GetBatCoulombInput();
|
||||
float GetBatCoulombOut();
|
||||
uint8_t GetWarningLevel(void);
|
||||
void SetCoulombClear();
|
||||
void SetLDO2( bool State );
|
||||
void SetDCDC3( bool State );
|
||||
|
||||
uint8_t AXPInState();
|
||||
bool isACIN();
|
||||
bool isCharging();
|
||||
bool isVBUS();
|
||||
|
||||
void SetLDOVoltage(uint8_t number , uint16_t voltage);
|
||||
void SetDCVoltage(uint8_t number , uint16_t voltage);
|
||||
void SetESPVoltage(uint16_t voltage);
|
||||
void SetLcdVoltage(uint16_t voltage);
|
||||
void SetLDOEnable( uint8_t number ,bool state );
|
||||
void SetLCDRSet( bool state );
|
||||
void SetBusPowerMode( uint8_t state );
|
||||
void SetLed(uint8_t state);
|
||||
void SetSpkEnable(uint8_t state);
|
||||
void SetCHGCurrent(uint8_t state);
|
||||
|
||||
private:
|
||||
void Write1Byte( uint8_t Addr , uint8_t Data );
|
||||
uint8_t Read8bit( uint8_t Addr );
|
||||
uint16_t Read12Bit( uint8_t Addr);
|
||||
uint16_t Read13Bit( uint8_t Addr);
|
||||
uint16_t Read16bit( uint8_t Addr );
|
||||
uint32_t Read24bit( uint8_t Addr );
|
||||
uint32_t Read32bit( uint8_t Addr );
|
||||
void ReadBuff( uint8_t Addr , uint8_t Size , uint8_t *Buff );
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,353 @@
|
|||
#include "BM8563_RTC.h"
|
||||
|
||||
BM8563_RTC::BM8563_RTC()
|
||||
{
|
||||
}
|
||||
|
||||
void BM8563_RTC::begin(void)
|
||||
{
|
||||
Wire1.begin(21, 22);
|
||||
WriteReg(0x00,0x00);
|
||||
WriteReg(0x01,0x00);
|
||||
WriteReg(0x0D,0x00);
|
||||
}
|
||||
|
||||
void BM8563_RTC::WriteReg(uint8_t reg, uint8_t data)
|
||||
{
|
||||
Wire1.beginTransmission(RTC_ADRESS);
|
||||
Wire1.write(reg);
|
||||
Wire1.write(data);
|
||||
Wire1.endTransmission();
|
||||
}
|
||||
|
||||
uint8_t BM8563_RTC::ReadReg(uint8_t reg)
|
||||
{
|
||||
Wire1.beginTransmission(0x51);
|
||||
Wire1.write(reg);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x51, 1);
|
||||
return Wire1.read();
|
||||
}
|
||||
|
||||
void BM8563_RTC::GetBm8563Time(void)
|
||||
{
|
||||
Wire1.beginTransmission(0x51);
|
||||
Wire1.write(0x02);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x51, 7);
|
||||
while (Wire1.available())
|
||||
{
|
||||
|
||||
trdata[0] = Wire1.read();
|
||||
trdata[1] = Wire1.read();
|
||||
trdata[2] = Wire1.read();
|
||||
trdata[3] = Wire1.read();
|
||||
trdata[4] = Wire1.read();
|
||||
trdata[5] = Wire1.read();
|
||||
trdata[6] = Wire1.read();
|
||||
}
|
||||
|
||||
DataMask();
|
||||
Bcd2asc();
|
||||
Str2Time();
|
||||
}
|
||||
|
||||
void BM8563_RTC::Str2Time(void)
|
||||
{
|
||||
|
||||
Second = (asc[0] - 0x30) * 10 + asc[1] - 0x30;
|
||||
Minute = (asc[2] - 0x30) * 10 + asc[3] - 0x30;
|
||||
Hour = (asc[4] - 0x30) * 10 + asc[5] - 0x30;
|
||||
/*
|
||||
uint8_t Hour;
|
||||
uint8_t Week;
|
||||
uint8_t Day;
|
||||
uint8_t Month;
|
||||
uint8_t Year;
|
||||
*/
|
||||
}
|
||||
|
||||
void BM8563_RTC::DataMask()
|
||||
{
|
||||
|
||||
trdata[0] = trdata[0] & 0x7f; //秒
|
||||
trdata[1] = trdata[1] & 0x7f; //分
|
||||
trdata[2] = trdata[2] & 0x3f; //时
|
||||
|
||||
trdata[3] = trdata[3] & 0x3f; //日
|
||||
trdata[4] = trdata[4] & 0x07; //星期
|
||||
trdata[5] = trdata[5] & 0x1f; //月
|
||||
|
||||
trdata[6] = trdata[6] & 0xff; //年
|
||||
}
|
||||
/********************************************************************
|
||||
函 数 名: void Bcd2asc(void)
|
||||
功 能: bcd 码转换成 asc 码,供Lcd显示用
|
||||
说 明:
|
||||
调 用:
|
||||
入口参数:
|
||||
返 回 值:无
|
||||
***********************************************************************/
|
||||
void BM8563_RTC::Bcd2asc(void)
|
||||
{
|
||||
uint8_t i, j;
|
||||
for (j = 0, i = 0; i < 7; i++)
|
||||
{
|
||||
asc[j++] = (trdata[i] & 0xf0) >> 4 | 0x30; /*格式为: 秒 分 时 日 月 星期 年 */
|
||||
asc[j++] = (trdata[i] & 0x0f) | 0x30;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t BM8563_RTC::Bcd2ToByte(uint8_t Value)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
tmp = ((uint8_t)(Value & (uint8_t)0xF0) >> (uint8_t)0x4) * 10;
|
||||
return (tmp + (Value & (uint8_t)0x0F));
|
||||
}
|
||||
|
||||
uint8_t BM8563_RTC::ByteToBcd2(uint8_t Value)
|
||||
{
|
||||
uint8_t bcdhigh = 0;
|
||||
|
||||
while (Value >= 10)
|
||||
{
|
||||
bcdhigh++;
|
||||
Value -= 10;
|
||||
}
|
||||
|
||||
return ((uint8_t)(bcdhigh << 4) | Value);
|
||||
}
|
||||
|
||||
void BM8563_RTC::GetTime(RTC_TimeTypeDef *RTC_TimeStruct)
|
||||
{
|
||||
|
||||
//if()
|
||||
uint8_t buf[3] = {0};
|
||||
|
||||
Wire1.beginTransmission(0x51);
|
||||
Wire1.write(0x02);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x51, 3);
|
||||
|
||||
while (Wire1.available())
|
||||
{
|
||||
|
||||
buf[0] = Wire1.read();
|
||||
buf[1] = Wire1.read();
|
||||
buf[2] = Wire1.read();
|
||||
}
|
||||
|
||||
RTC_TimeStruct->Seconds = Bcd2ToByte(buf[0] & 0x7f); //秒
|
||||
RTC_TimeStruct->Minutes = Bcd2ToByte(buf[1] & 0x7f); //分
|
||||
RTC_TimeStruct->Hours = Bcd2ToByte(buf[2] & 0x3f); //时
|
||||
}
|
||||
|
||||
void BM8563_RTC::SetTime(RTC_TimeTypeDef *RTC_TimeStruct)
|
||||
{
|
||||
|
||||
if (RTC_TimeStruct == NULL)
|
||||
return;
|
||||
|
||||
Wire1.beginTransmission(0x51);
|
||||
Wire1.write(0x02);
|
||||
Wire1.write(ByteToBcd2(RTC_TimeStruct->Seconds));
|
||||
Wire1.write(ByteToBcd2(RTC_TimeStruct->Minutes));
|
||||
Wire1.write(ByteToBcd2(RTC_TimeStruct->Hours));
|
||||
Wire1.endTransmission();
|
||||
}
|
||||
|
||||
void BM8563_RTC::GetDate(RTC_DateTypeDef *RTC_DateStruct)
|
||||
{
|
||||
|
||||
uint8_t buf[4] = {0};
|
||||
|
||||
Wire1.beginTransmission(0x51);
|
||||
Wire1.write(0x05);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x51, 4);
|
||||
|
||||
while (Wire1.available())
|
||||
{
|
||||
|
||||
buf[0] = Wire1.read();
|
||||
buf[1] = Wire1.read();
|
||||
buf[2] = Wire1.read();
|
||||
buf[3] = Wire1.read();
|
||||
}
|
||||
|
||||
RTC_DateStruct->Date = Bcd2ToByte(buf[0] & 0x3f);
|
||||
RTC_DateStruct->WeekDay = Bcd2ToByte(buf[1] & 0x07);
|
||||
RTC_DateStruct->Month = Bcd2ToByte(buf[2] & 0x1f);
|
||||
|
||||
if (buf[2] & 0x80)
|
||||
{
|
||||
RTC_DateStruct->Year = 1900 + Bcd2ToByte(buf[3] & 0xff);
|
||||
}
|
||||
else
|
||||
{
|
||||
RTC_DateStruct->Year = 2000 + Bcd2ToByte(buf[3] & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
void BM8563_RTC::SetDate(RTC_DateTypeDef *RTC_DateStruct)
|
||||
{
|
||||
|
||||
if (RTC_DateStruct == NULL)
|
||||
return;
|
||||
Wire1.beginTransmission(0x51);
|
||||
Wire1.write(0x05);
|
||||
Wire1.write(ByteToBcd2(RTC_DateStruct->Date));
|
||||
Wire1.write(ByteToBcd2(RTC_DateStruct->WeekDay));
|
||||
|
||||
if (RTC_DateStruct->Year < 2000)
|
||||
{
|
||||
|
||||
Wire1.write(ByteToBcd2(RTC_DateStruct->Month) | 0x80);
|
||||
Wire1.write(ByteToBcd2((uint8_t)(RTC_DateStruct->Year % 100)));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* code */
|
||||
Wire1.write(ByteToBcd2(RTC_DateStruct->Month) | 0x00);
|
||||
Wire1.write(ByteToBcd2((uint8_t)(RTC_DateStruct->Year % 100)));
|
||||
}
|
||||
|
||||
Wire1.endTransmission();
|
||||
}
|
||||
|
||||
int BM8563_RTC::SetAlarmIRQ(int afterSeconds)
|
||||
{
|
||||
uint8_t reg_value = 0;
|
||||
reg_value = ReadReg(0x01);
|
||||
|
||||
if (afterSeconds < 0)
|
||||
{
|
||||
reg_value &= ~(1 << 0);
|
||||
WriteReg(0x01, reg_value);
|
||||
reg_value = 0x03;
|
||||
WriteReg(0x0E, reg_value);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t type_value = 2;
|
||||
uint8_t div = 1;
|
||||
if (afterSeconds > 255)
|
||||
{
|
||||
div = 60;
|
||||
type_value = 0x83;
|
||||
}
|
||||
else
|
||||
{
|
||||
type_value = 0x82;
|
||||
}
|
||||
|
||||
afterSeconds = (afterSeconds / div) & 0xFF;
|
||||
WriteReg(0x0F, afterSeconds);
|
||||
WriteReg(0x0E, type_value);
|
||||
|
||||
reg_value |= (1 << 0);
|
||||
reg_value &= ~(1 << 7);
|
||||
WriteReg(0x01, reg_value);
|
||||
return afterSeconds * div;
|
||||
}
|
||||
|
||||
int BM8563_RTC::SetAlarmIRQ(const RTC_TimeTypeDef &RTC_TimeStruct)
|
||||
{
|
||||
uint8_t irq_enable = false;
|
||||
uint8_t out_buf[4] = {0x80, 0x80, 0x80, 0x80};
|
||||
|
||||
if (RTC_TimeStruct.Minutes >= 0)
|
||||
{
|
||||
irq_enable = true;
|
||||
out_buf[0] = ByteToBcd2(RTC_TimeStruct.Minutes) & 0x7f;
|
||||
}
|
||||
|
||||
if (RTC_TimeStruct.Hours >= 0)
|
||||
{
|
||||
irq_enable = true;
|
||||
out_buf[1] = ByteToBcd2(RTC_TimeStruct.Hours) & 0x3f;
|
||||
}
|
||||
|
||||
out_buf[2] = 0x00;
|
||||
out_buf[3] = 0x00;
|
||||
|
||||
uint8_t reg_value = ReadReg(0x01);
|
||||
|
||||
if (irq_enable)
|
||||
{
|
||||
reg_value |= (1 << 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
reg_value &= ~(1 << 1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
WriteReg(0x09 + i, out_buf[i]);
|
||||
}
|
||||
WriteReg(0x01, reg_value);
|
||||
|
||||
return irq_enable ? 1 : 0;
|
||||
}
|
||||
|
||||
int BM8563_RTC::SetAlarmIRQ(const RTC_DateTypeDef &RTC_DateStruct, const RTC_TimeTypeDef &RTC_TimeStruct)
|
||||
{
|
||||
uint8_t irq_enable = false;
|
||||
uint8_t out_buf[4] = {0x80, 0x80, 0x80, 0x80};
|
||||
|
||||
if (RTC_TimeStruct.Minutes >= 0)
|
||||
{
|
||||
irq_enable = true;
|
||||
out_buf[0] = ByteToBcd2(RTC_TimeStruct.Minutes) & 0x7f;
|
||||
}
|
||||
|
||||
if (RTC_TimeStruct.Hours >= 0)
|
||||
{
|
||||
irq_enable = true;
|
||||
out_buf[1] = ByteToBcd2(RTC_TimeStruct.Hours) & 0x3f;
|
||||
}
|
||||
|
||||
if (RTC_DateStruct.Date >= 0)
|
||||
{
|
||||
irq_enable = true;
|
||||
out_buf[2] = ByteToBcd2(RTC_DateStruct.Date) & 0x3f;
|
||||
}
|
||||
|
||||
if (RTC_DateStruct.WeekDay >= 0)
|
||||
{
|
||||
irq_enable = true;
|
||||
out_buf[3] = ByteToBcd2(RTC_DateStruct.WeekDay) & 0x07;
|
||||
}
|
||||
|
||||
uint8_t reg_value = ReadReg(0x01);
|
||||
|
||||
if (irq_enable)
|
||||
{
|
||||
reg_value |= (1 << 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
reg_value &= ~(1 << 1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
WriteReg(0x09 + i, out_buf[i]);
|
||||
}
|
||||
WriteReg(0x01, reg_value);
|
||||
|
||||
return irq_enable ? 1 : 0;
|
||||
}
|
||||
|
||||
void BM8563_RTC::clearIRQ()
|
||||
{
|
||||
uint8_t data = ReadReg(0x01);
|
||||
WriteReg(0x01, data & 0xf3);
|
||||
}
|
||||
void BM8563_RTC::disableIRQ()
|
||||
{
|
||||
clearIRQ();
|
||||
uint8_t data = ReadReg(0x01);
|
||||
WriteReg(0x01, data & 0xfC);
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
#ifndef __RTC_H__
|
||||
#define __RTC_H__
|
||||
|
||||
#include <Wire.h>
|
||||
|
||||
#define RTC_ADRESS 0x51
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t Hours;
|
||||
uint8_t Minutes;
|
||||
uint8_t Seconds;
|
||||
}RTC_TimeTypeDef;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t WeekDay;
|
||||
uint8_t Month;
|
||||
uint8_t Date;
|
||||
uint16_t Year;
|
||||
}RTC_DateTypeDef;
|
||||
|
||||
class BM8563_RTC {
|
||||
public:
|
||||
BM8563_RTC();
|
||||
|
||||
void begin(void);
|
||||
void GetBm8563Time(void);
|
||||
|
||||
void SetTime(RTC_TimeTypeDef* RTC_TimeStruct);
|
||||
void SetDate(RTC_DateTypeDef* RTC_DateStruct);
|
||||
|
||||
void GetTime(RTC_TimeTypeDef* RTC_TimeStruct);
|
||||
void GetDate(RTC_DateTypeDef* RTC_DateStruct);
|
||||
|
||||
int SetAlarmIRQ(int afterSeconds);
|
||||
int SetAlarmIRQ( const RTC_TimeTypeDef &RTC_TimeStruct);
|
||||
int SetAlarmIRQ( const RTC_DateTypeDef &RTC_DateStruct, const RTC_TimeTypeDef &RTC_TimeStruct);
|
||||
|
||||
void clearIRQ();
|
||||
void disableIRQ();
|
||||
|
||||
public:
|
||||
uint8_t Second;
|
||||
uint8_t Minute;
|
||||
uint8_t Hour;
|
||||
uint8_t Week;
|
||||
uint8_t Day;
|
||||
uint8_t Month;
|
||||
uint8_t Year;
|
||||
uint8_t DateString[9];
|
||||
uint8_t TimeString[9];
|
||||
|
||||
uint8_t asc[14];
|
||||
|
||||
|
||||
private:
|
||||
void Bcd2asc(void);
|
||||
void DataMask();
|
||||
void Str2Time(void);
|
||||
void WriteReg(uint8_t reg, uint8_t data);
|
||||
uint8_t ReadReg(uint8_t reg);
|
||||
uint8_t Bcd2ToByte(uint8_t Value);
|
||||
uint8_t ByteToBcd2(uint8_t Value);
|
||||
|
||||
private:
|
||||
|
||||
/*定义数组用来存储读取的时间数据 */
|
||||
uint8_t trdata[7];
|
||||
/*定义数组用来存储转换的 asc 码时间数据*/
|
||||
//uint8_t asc[14];
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,252 @@
|
|||
#include "MPU6886.h"
|
||||
#include <math.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
MPU6886::MPU6886(){
|
||||
|
||||
}
|
||||
|
||||
void MPU6886::I2C_Read_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *read_Buffer){
|
||||
|
||||
Wire1.beginTransmission(driver_Addr);
|
||||
Wire1.write(start_Addr);
|
||||
Wire1.endTransmission(false);
|
||||
uint8_t i = 0;
|
||||
Wire1.requestFrom(driver_Addr,number_Bytes);
|
||||
|
||||
//! Put read results in the Rx buffer
|
||||
while (Wire1.available()) {
|
||||
read_Buffer[i++] = Wire1.read();
|
||||
}
|
||||
}
|
||||
|
||||
void MPU6886::I2C_Write_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *write_Buffer){
|
||||
|
||||
Wire1.beginTransmission(driver_Addr);
|
||||
Wire1.write(start_Addr);
|
||||
Wire1.write(*write_Buffer);
|
||||
Wire1.endTransmission();
|
||||
|
||||
}
|
||||
|
||||
int MPU6886::Init(void){
|
||||
unsigned char tempdata[1];
|
||||
unsigned char regdata;
|
||||
|
||||
Wire1.begin(21,22);
|
||||
|
||||
I2C_Read_NBytes(MPU6886_ADDRESS, MPU6886_WHOAMI, 1, tempdata);
|
||||
if(tempdata[0] != 0x19)
|
||||
return -1;
|
||||
delay(1);
|
||||
|
||||
regdata = 0x00;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_PWR_MGMT_1, 1, ®data);
|
||||
delay(10);
|
||||
|
||||
regdata = (0x01<<7);
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_PWR_MGMT_1, 1, ®data);
|
||||
delay(10);
|
||||
|
||||
regdata = (0x01<<0);
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_PWR_MGMT_1, 1, ®data);
|
||||
delay(10);
|
||||
|
||||
regdata = 0x10;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_ACCEL_CONFIG, 1, ®data);
|
||||
delay(1);
|
||||
|
||||
regdata = 0x18;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_GYRO_CONFIG, 1, ®data);
|
||||
delay(1);
|
||||
|
||||
regdata = 0x01;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_CONFIG, 1, ®data);
|
||||
delay(1);
|
||||
|
||||
regdata = 0x05;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_SMPLRT_DIV, 1,®data);
|
||||
delay(1);
|
||||
|
||||
regdata = 0x00;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_INT_ENABLE, 1, ®data);
|
||||
delay(1);
|
||||
|
||||
regdata = 0x00;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_ACCEL_CONFIG2, 1, ®data);
|
||||
delay(1);
|
||||
|
||||
regdata = 0x00;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_USER_CTRL, 1, ®data);
|
||||
delay(1);
|
||||
|
||||
regdata = 0x00;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_FIFO_EN, 1, ®data);
|
||||
delay(1);
|
||||
|
||||
regdata = 0x22;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_INT_PIN_CFG, 1, ®data);
|
||||
delay(1);
|
||||
|
||||
regdata = 0x01;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_INT_ENABLE, 1, ®data);
|
||||
|
||||
delay(100);
|
||||
getGres();
|
||||
getAres();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MPU6886::getAccelAdc(int16_t* ax, int16_t* ay, int16_t* az){
|
||||
|
||||
uint8_t buf[6];
|
||||
I2C_Read_NBytes(MPU6886_ADDRESS,MPU6886_ACCEL_XOUT_H,6,buf);
|
||||
|
||||
*ax=((int16_t)buf[0]<<8)|buf[1];
|
||||
*ay=((int16_t)buf[2]<<8)|buf[3];
|
||||
*az=((int16_t)buf[4]<<8)|buf[5];
|
||||
|
||||
}
|
||||
void MPU6886::getGyroAdc(int16_t* gx, int16_t* gy, int16_t* gz){
|
||||
|
||||
uint8_t buf[6];
|
||||
I2C_Read_NBytes(MPU6886_ADDRESS,MPU6886_GYRO_XOUT_H,6,buf);
|
||||
|
||||
*gx=((uint16_t)buf[0]<<8)|buf[1];
|
||||
*gy=((uint16_t)buf[2]<<8)|buf[3];
|
||||
*gz=((uint16_t)buf[4]<<8)|buf[5];
|
||||
|
||||
}
|
||||
|
||||
void MPU6886::getTempAdc(int16_t *t){
|
||||
|
||||
uint8_t buf[2];
|
||||
I2C_Read_NBytes(MPU6886_ADDRESS,MPU6886_TEMP_OUT_H,2,buf);
|
||||
|
||||
*t=((uint16_t)buf[0]<<8)|buf[1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
//!俯仰,航向,横滚:pitch,yaw,roll,指三维空间中飞行器的旋转状态。
|
||||
void MPU6886::getAhrsData(float *pitch,float *roll,float *yaw){
|
||||
|
||||
float accX = 0;
|
||||
float accY = 0;
|
||||
float accZ = 0;
|
||||
|
||||
float gyroX = 0;
|
||||
float gyroY = 0;
|
||||
float gyroZ = 0;
|
||||
|
||||
|
||||
getGyroData(&gyroX,&gyroY,&gyroZ);
|
||||
getAccelData(&accX,&accY,&accZ);
|
||||
|
||||
MahonyAHRSupdateIMU(gyroX * DEG_TO_RAD, gyroY * DEG_TO_RAD, gyroZ * DEG_TO_RAD, accX, accY, accZ,pitch,roll,yaw);
|
||||
|
||||
}
|
||||
|
||||
void MPU6886::getGres(){
|
||||
|
||||
switch (Gyscale)
|
||||
{
|
||||
// Possible gyro scales (and their register bit settings) are:
|
||||
case GFS_250DPS:
|
||||
gRes = 250.0/32768.0;
|
||||
break;
|
||||
case GFS_500DPS:
|
||||
gRes = 500.0/32768.0;
|
||||
break;
|
||||
case GFS_1000DPS:
|
||||
gRes = 1000.0/32768.0;
|
||||
break;
|
||||
case GFS_2000DPS:
|
||||
gRes = 2000.0/32768.0;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MPU6886::getAres(){
|
||||
switch (Acscale)
|
||||
{
|
||||
// Possible accelerometer scales (and their register bit settings) are:
|
||||
// 2 Gs (00), 4 Gs (01), 8 Gs (10), and 16 Gs (11).
|
||||
// Here's a bit of an algorith to calculate DPS/(ADC tick) based on that 2-bit value:
|
||||
case AFS_2G:
|
||||
aRes = 2.0/32768.0;
|
||||
break;
|
||||
case AFS_4G:
|
||||
aRes = 4.0/32768.0;
|
||||
break;
|
||||
case AFS_8G:
|
||||
aRes = 8.0/32768.0;
|
||||
break;
|
||||
case AFS_16G:
|
||||
aRes = 16.0/32768.0;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MPU6886::SetGyroFsr(Gscale scale)
|
||||
{
|
||||
//return IIC_Write_Byte(MPU_GYRO_CFG_REG,scale<<3);//设置陀螺仪满量程范围
|
||||
unsigned char regdata;
|
||||
regdata = (scale<<3);
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_GYRO_CONFIG, 1, ®data);
|
||||
delay(10);
|
||||
|
||||
Gyscale = scale;
|
||||
getGres();
|
||||
}
|
||||
|
||||
void MPU6886::SetAccelFsr(Ascale scale)
|
||||
{
|
||||
unsigned char regdata;
|
||||
regdata = (scale<<3);
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_ACCEL_CONFIG, 1, ®data);
|
||||
delay(10);
|
||||
|
||||
Acscale = scale;
|
||||
getAres();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void MPU6886::getAccelData(float* ax, float* ay, float* az){
|
||||
|
||||
|
||||
int16_t accX = 0;
|
||||
int16_t accY = 0;
|
||||
int16_t accZ = 0;
|
||||
getAccelAdc(&accX,&accY,&accZ);
|
||||
|
||||
|
||||
*ax = (float)accX * aRes;
|
||||
*ay = (float)accY * aRes;
|
||||
*az = (float)accZ * aRes;
|
||||
|
||||
}
|
||||
|
||||
void MPU6886::getGyroData(float* gx, float* gy, float* gz){
|
||||
int16_t gyroX = 0;
|
||||
int16_t gyroY = 0;
|
||||
int16_t gyroZ = 0;
|
||||
getGyroAdc(&gyroX,&gyroY,&gyroZ);
|
||||
|
||||
*gx = (float)gyroX * gRes;
|
||||
*gy = (float)gyroY * gRes;
|
||||
*gz = (float)gyroZ * gRes;
|
||||
}
|
||||
|
||||
void MPU6886::getTempData(float *t){
|
||||
|
||||
int16_t temp = 0;
|
||||
getTempAdc(&temp);
|
||||
|
||||
*t = (float)temp / 326.8 + 25.0;
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
Note: The MPU6886 is an I2C sensor and uses the Arduino Wire library.
|
||||
Because the sensor is not 5V tolerant, we are using a 3.3 V 8 MHz Pro Mini or
|
||||
a 3.3 V Teensy 3.1. We have disabled the internal pull-ups used by the Wire
|
||||
library in the Wire.h/twi.c utility file. We are also using the 400 kHz fast
|
||||
I2C mode by setting the TWI_FREQ to 400000L /twi.h utility file.
|
||||
*/
|
||||
#ifndef _MPU6886_H_
|
||||
#define _MPU6886_H_
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Arduino.h>
|
||||
#include "MahonyAHRS.h"
|
||||
|
||||
#define MPU6886_ADDRESS 0x68
|
||||
#define MPU6886_WHOAMI 0x75
|
||||
#define MPU6886_ACCEL_INTEL_CTRL 0x69
|
||||
#define MPU6886_SMPLRT_DIV 0x19
|
||||
#define MPU6886_INT_PIN_CFG 0x37
|
||||
#define MPU6886_INT_ENABLE 0x38
|
||||
#define MPU6886_ACCEL_XOUT_H 0x3B
|
||||
#define MPU6886_ACCEL_XOUT_L 0x3C
|
||||
#define MPU6886_ACCEL_YOUT_H 0x3D
|
||||
#define MPU6886_ACCEL_YOUT_L 0x3E
|
||||
#define MPU6886_ACCEL_ZOUT_H 0x3F
|
||||
#define MPU6886_ACCEL_ZOUT_L 0x40
|
||||
|
||||
#define MPU6886_TEMP_OUT_H 0x41
|
||||
#define MPU6886_TEMP_OUT_L 0x42
|
||||
|
||||
#define MPU6886_GYRO_XOUT_H 0x43
|
||||
#define MPU6886_GYRO_XOUT_L 0x44
|
||||
#define MPU6886_GYRO_YOUT_H 0x45
|
||||
#define MPU6886_GYRO_YOUT_L 0x46
|
||||
#define MPU6886_GYRO_ZOUT_H 0x47
|
||||
#define MPU6886_GYRO_ZOUT_L 0x48
|
||||
|
||||
#define MPU6886_USER_CTRL 0x6A
|
||||
#define MPU6886_PWR_MGMT_1 0x6B
|
||||
#define MPU6886_PWR_MGMT_2 0x6C
|
||||
#define MPU6886_CONFIG 0x1A
|
||||
#define MPU6886_GYRO_CONFIG 0x1B
|
||||
#define MPU6886_ACCEL_CONFIG 0x1C
|
||||
#define MPU6886_ACCEL_CONFIG2 0x1D
|
||||
#define MPU6886_FIFO_EN 0x23
|
||||
|
||||
//#define G (9.8)
|
||||
#define RtA 57.324841
|
||||
#define AtR 0.0174533
|
||||
#define Gyro_Gr 0.0010653
|
||||
|
||||
class MPU6886 {
|
||||
public:
|
||||
enum Ascale {
|
||||
AFS_2G = 0,
|
||||
AFS_4G,
|
||||
AFS_8G,
|
||||
AFS_16G
|
||||
};
|
||||
|
||||
enum Gscale {
|
||||
GFS_250DPS = 0,
|
||||
GFS_500DPS,
|
||||
GFS_1000DPS,
|
||||
GFS_2000DPS
|
||||
};
|
||||
|
||||
Gscale Gyscale = GFS_2000DPS;
|
||||
Ascale Acscale = AFS_8G;
|
||||
public:
|
||||
MPU6886();
|
||||
int Init(void);
|
||||
void getAccelAdc(int16_t* ax, int16_t* ay, int16_t* az);
|
||||
void getGyroAdc(int16_t* gx, int16_t* gy, int16_t* gz);
|
||||
void getTempAdc(int16_t *t);
|
||||
|
||||
void getAccelData(float* ax, float* ay, float* az);
|
||||
void getGyroData(float* gx, float* gy, float* gz);
|
||||
void getTempData(float *t);
|
||||
|
||||
void SetGyroFsr(Gscale scale);
|
||||
void SetAccelFsr(Ascale scale);
|
||||
|
||||
void getAhrsData(float *pitch,float *roll,float *yaw);
|
||||
|
||||
public:
|
||||
float aRes, gRes;
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
void I2C_Read_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *read_Buffer);
|
||||
void I2C_Write_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *write_Buffer);
|
||||
void getGres();
|
||||
void getAres();
|
||||
|
||||
};
|
||||
#endif
|
|
@ -0,0 +1,254 @@
|
|||
//=====================================================================================================
|
||||
// MahonyAHRS.c
|
||||
//=====================================================================================================
|
||||
//
|
||||
// Madgwick's implementation of Mayhony's AHRS algorithm.
|
||||
// See: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms
|
||||
//
|
||||
// Date Author Notes
|
||||
// 29/09/2011 SOH Madgwick Initial release
|
||||
// 02/10/2011 SOH Madgwick Optimised for reduced CPU load
|
||||
//
|
||||
//=====================================================================================================
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Header files
|
||||
|
||||
#include "MahonyAHRS.h"
|
||||
#include "Arduino.h"
|
||||
#include <math.h>
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Definitions
|
||||
|
||||
#define sampleFreq 25.0f // sample frequency in Hz
|
||||
#define twoKpDef (2.0f * 1.0f) // 2 * proportional gain
|
||||
#define twoKiDef (2.0f * 0.0f) // 2 * integral gain
|
||||
|
||||
//#define twoKiDef (0.0f * 0.0f)
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Variable definitions
|
||||
|
||||
volatile float twoKp = twoKpDef; // 2 * proportional gain (Kp)
|
||||
volatile float twoKi = twoKiDef; // 2 * integral gain (Ki)
|
||||
volatile float q0 = 1.0, q1 = 0.0, q2 = 0.0, q3 = 0.0; // quaternion of sensor frame relative to auxiliary frame
|
||||
volatile float integralFBx = 0.0f, integralFBy = 0.0f, integralFBz = 0.0f; // integral error terms scaled by Ki
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Function declarations
|
||||
|
||||
//float invSqrt(float x);
|
||||
|
||||
//====================================================================================================
|
||||
// Functions
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// AHRS algorithm update
|
||||
|
||||
void MahonyAHRSupdate(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz) {
|
||||
float recipNorm;
|
||||
float q0q0, q0q1, q0q2, q0q3, q1q1, q1q2, q1q3, q2q2, q2q3, q3q3;
|
||||
float hx, hy, bx, bz;
|
||||
float halfvx, halfvy, halfvz, halfwx, halfwy, halfwz;
|
||||
float halfex, halfey, halfez;
|
||||
float qa, qb, qc;
|
||||
|
||||
// Use IMU algorithm if magnetometer measurement invalid (avoids NaN in magnetometer normalisation)
|
||||
if((mx == 0.0f) && (my == 0.0f) && (mz == 0.0f)) {
|
||||
//MahonyAHRSupdateIMU(gx, gy, gz, ax, ay, az);
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
|
||||
if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {
|
||||
|
||||
// Normalise accelerometer measurement
|
||||
recipNorm = sqrt(ax * ax + ay * ay + az * az);
|
||||
ax *= recipNorm;
|
||||
ay *= recipNorm;
|
||||
az *= recipNorm;
|
||||
|
||||
// Normalise magnetometer measurement
|
||||
recipNorm = sqrt(mx * mx + my * my + mz * mz);
|
||||
mx *= recipNorm;
|
||||
my *= recipNorm;
|
||||
mz *= recipNorm;
|
||||
|
||||
// Auxiliary variables to avoid repeated arithmetic
|
||||
q0q0 = q0 * q0;
|
||||
q0q1 = q0 * q1;
|
||||
q0q2 = q0 * q2;
|
||||
q0q3 = q0 * q3;
|
||||
q1q1 = q1 * q1;
|
||||
q1q2 = q1 * q2;
|
||||
q1q3 = q1 * q3;
|
||||
q2q2 = q2 * q2;
|
||||
q2q3 = q2 * q3;
|
||||
q3q3 = q3 * q3;
|
||||
|
||||
// Reference direction of Earth's magnetic field
|
||||
hx = 2.0f * (mx * (0.5f - q2q2 - q3q3) + my * (q1q2 - q0q3) + mz * (q1q3 + q0q2));
|
||||
hy = 2.0f * (mx * (q1q2 + q0q3) + my * (0.5f - q1q1 - q3q3) + mz * (q2q3 - q0q1));
|
||||
bx = sqrt(hx * hx + hy * hy);
|
||||
bz = 2.0f * (mx * (q1q3 - q0q2) + my * (q2q3 + q0q1) + mz * (0.5f - q1q1 - q2q2));
|
||||
|
||||
// Estimated direction of gravity and magnetic field
|
||||
halfvx = q1q3 - q0q2;
|
||||
halfvy = q0q1 + q2q3;
|
||||
halfvz = q0q0 - 0.5f + q3q3;
|
||||
halfwx = bx * (0.5f - q2q2 - q3q3) + bz * (q1q3 - q0q2);
|
||||
halfwy = bx * (q1q2 - q0q3) + bz * (q0q1 + q2q3);
|
||||
halfwz = bx * (q0q2 + q1q3) + bz * (0.5f - q1q1 - q2q2);
|
||||
|
||||
// Error is sum of cross product between estimated direction and measured direction of field vectors
|
||||
halfex = (ay * halfvz - az * halfvy) + (my * halfwz - mz * halfwy);
|
||||
halfey = (az * halfvx - ax * halfvz) + (mz * halfwx - mx * halfwz);
|
||||
halfez = (ax * halfvy - ay * halfvx) + (mx * halfwy - my * halfwx);
|
||||
|
||||
// Compute and apply integral feedback if enabled
|
||||
if(twoKi > 0.0f) {
|
||||
integralFBx += twoKi * halfex * (1.0f / sampleFreq); // integral error scaled by Ki
|
||||
integralFBy += twoKi * halfey * (1.0f / sampleFreq);
|
||||
integralFBz += twoKi * halfez * (1.0f / sampleFreq);
|
||||
gx += integralFBx; // apply integral feedback
|
||||
gy += integralFBy;
|
||||
gz += integralFBz;
|
||||
}
|
||||
else {
|
||||
integralFBx = 0.0f; // prevent integral windup
|
||||
integralFBy = 0.0f;
|
||||
integralFBz = 0.0f;
|
||||
}
|
||||
|
||||
// Apply proportional feedback
|
||||
gx += twoKp * halfex;
|
||||
gy += twoKp * halfey;
|
||||
gz += twoKp * halfez;
|
||||
}
|
||||
|
||||
// Integrate rate of change of quaternion
|
||||
gx *= (0.5f * (1.0f / sampleFreq)); // pre-multiply common factors
|
||||
gy *= (0.5f * (1.0f / sampleFreq));
|
||||
gz *= (0.5f * (1.0f / sampleFreq));
|
||||
qa = q0;
|
||||
qb = q1;
|
||||
qc = q2;
|
||||
q0 += (-qb * gx - qc * gy - q3 * gz);
|
||||
q1 += (qa * gx + qc * gz - q3 * gy);
|
||||
q2 += (qa * gy - qb * gz + q3 * gx);
|
||||
q3 += (qa * gz + qb * gy - qc * gx);
|
||||
|
||||
// Normalise quaternion
|
||||
recipNorm = sqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
|
||||
q0 *= recipNorm;
|
||||
q1 *= recipNorm;
|
||||
q2 *= recipNorm;
|
||||
q3 *= recipNorm;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// IMU algorithm update
|
||||
|
||||
void MahonyAHRSupdateIMU(float gx, float gy, float gz, float ax, float ay, float az,float *pitch,float *roll,float *yaw) {
|
||||
float recipNorm;
|
||||
float halfvx, halfvy, halfvz;
|
||||
float halfex, halfey, halfez;
|
||||
float qa, qb, qc;
|
||||
|
||||
|
||||
// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
|
||||
if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {
|
||||
|
||||
// Normalise accelerometer measurement
|
||||
recipNorm = invSqrt(ax * ax + ay * ay + az * az);
|
||||
ax *= recipNorm;
|
||||
ay *= recipNorm;
|
||||
az *= recipNorm;
|
||||
|
||||
// Estimated direction of gravity and vector perpendicular to magnetic flux
|
||||
halfvx = q1 * q3 - q0 * q2;
|
||||
halfvy = q0 * q1 + q2 * q3;
|
||||
halfvz = q0 * q0 - 0.5f + q3 * q3;
|
||||
|
||||
|
||||
|
||||
// Error is sum of cross product between estimated and measured direction of gravity
|
||||
halfex = (ay * halfvz - az * halfvy);
|
||||
halfey = (az * halfvx - ax * halfvz);
|
||||
halfez = (ax * halfvy - ay * halfvx);
|
||||
|
||||
// Compute and apply integral feedback if enabled
|
||||
if(twoKi > 0.0f) {
|
||||
integralFBx += twoKi * halfex * (1.0f / sampleFreq); // integral error scaled by Ki
|
||||
integralFBy += twoKi * halfey * (1.0f / sampleFreq);
|
||||
integralFBz += twoKi * halfez * (1.0f / sampleFreq);
|
||||
gx += integralFBx; // apply integral feedback
|
||||
gy += integralFBy;
|
||||
gz += integralFBz;
|
||||
}
|
||||
else {
|
||||
integralFBx = 0.0f; // prevent integral windup
|
||||
integralFBy = 0.0f;
|
||||
integralFBz = 0.0f;
|
||||
}
|
||||
|
||||
// Apply proportional feedback
|
||||
gx += twoKp * halfex;
|
||||
gy += twoKp * halfey;
|
||||
gz += twoKp * halfez;
|
||||
}
|
||||
|
||||
// Integrate rate of change of quaternion
|
||||
gx *= (0.5f * (1.0f / sampleFreq)); // pre-multiply common factors
|
||||
gy *= (0.5f * (1.0f / sampleFreq));
|
||||
gz *= (0.5f * (1.0f / sampleFreq));
|
||||
qa = q0;
|
||||
qb = q1;
|
||||
qc = q2;
|
||||
q0 += (-qb * gx - qc * gy - q3 * gz);
|
||||
q1 += (qa * gx + qc * gz - q3 * gy);
|
||||
q2 += (qa * gy - qb * gz + q3 * gx);
|
||||
q3 += (qa * gz + qb * gy - qc * gx);
|
||||
|
||||
// Normalise quaternion
|
||||
recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
|
||||
q0 *= recipNorm;
|
||||
q1 *= recipNorm;
|
||||
q2 *= recipNorm;
|
||||
q3 *= recipNorm;
|
||||
|
||||
|
||||
*pitch = asin(-2 * q1 * q3 + 2 * q0* q2); // pitch
|
||||
*roll = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1); // roll
|
||||
*yaw = atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3); //yaw
|
||||
|
||||
*pitch *= RAD_TO_DEG;
|
||||
*yaw *= RAD_TO_DEG;
|
||||
// Declination of SparkFun Electronics (40°05'26.6"N 105°11'05.9"W) is
|
||||
// 8° 30' E ± 0° 21' (or 8.5°) on 2016-07-19
|
||||
// - http://www.ngdc.noaa.gov/geomag-web/#declination
|
||||
*yaw -= 8.5;
|
||||
*roll *= RAD_TO_DEG;
|
||||
|
||||
///Serial.printf("%f %f %f \r\n", pitch, roll, yaw);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Fast inverse square-root
|
||||
// See: http://en.wikipedia.org/wiki/Fast_inverse_square_root
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
float invSqrt(float x) {
|
||||
float halfx = 0.5f * x;
|
||||
float y = x;
|
||||
long i = *(long*)&y;
|
||||
i = 0x5f3759df - (i>>1);
|
||||
y = *(float*)&i;
|
||||
y = y * (1.5f - (halfx * y * y));
|
||||
return y;
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
//====================================================================================================
|
||||
// END OF CODE
|
||||
//====================================================================================================
|
|
@ -0,0 +1,33 @@
|
|||
//=====================================================================================================
|
||||
// MahonyAHRS.h
|
||||
//=====================================================================================================
|
||||
//
|
||||
// Madgwick's implementation of Mayhony's AHRS algorithm.
|
||||
// See: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms
|
||||
//
|
||||
// Date Author Notes
|
||||
// 29/09/2011 SOH Madgwick Initial release
|
||||
// 02/10/2011 SOH Madgwick Optimised for reduced CPU load
|
||||
//
|
||||
//=====================================================================================================
|
||||
#ifndef MahonyAHRS_h
|
||||
#define MahonyAHRS_h
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// Variable declaration
|
||||
|
||||
extern volatile float twoKp; // 2 * proportional gain (Kp)
|
||||
extern volatile float twoKi; // 2 * integral gain (Ki)
|
||||
//volatile float q0, q1, q2, q3; // quaternion of sensor frame relative to auxiliary frame
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Function declarations
|
||||
|
||||
void MahonyAHRSupdate(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz);
|
||||
//void MahonyAHRSupdateIMU(float gx, float gy, float gz, float ax, float ay, float az);
|
||||
void MahonyAHRSupdateIMU(float gx, float gy, float gz, float ax, float ay, float az,float *pitch,float *roll,float *yaw);
|
||||
float invSqrt(float x);
|
||||
#endif
|
||||
//=====================================================================================================
|
||||
// End of file
|
||||
//=====================================================================================================
|
|
@ -1919,6 +1919,19 @@ chknext:
|
|||
fvar = xPortGetCoreID();
|
||||
goto exit;
|
||||
}
|
||||
#ifdef USE_M5STACK_CORE2
|
||||
if (!strncmp(vname, "c2ps(", 5)) {
|
||||
lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0);
|
||||
while (*lp==' ') lp++;
|
||||
float fvar1;
|
||||
lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0);
|
||||
fvar = core2_setaxppin(fvar, fvar1);
|
||||
lp++;
|
||||
len=0;
|
||||
goto exit;
|
||||
}
|
||||
#endif // USE_M5STACK_CORE2
|
||||
|
||||
#ifdef USE_SCRIPT_TASK
|
||||
if (!strncmp(vname, "ct(", 3)) {
|
||||
lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, 0);
|
||||
|
@ -2667,7 +2680,7 @@ chknext:
|
|||
len++;
|
||||
goto exit;
|
||||
}
|
||||
#if defined(ESP32) && (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH))
|
||||
#if defined(ESP32) && (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH) || defined(USE_M5STACK_CORE2))
|
||||
if (!strncmp(vname, "pl(", 3)) {
|
||||
char path[SCRIPT_MAXSSIZE];
|
||||
lp = GetStringArgument(lp + 3, OPER_EQU, path, 0);
|
||||
|
@ -2860,7 +2873,7 @@ chknext:
|
|||
len = 0;
|
||||
goto strexit;
|
||||
}
|
||||
#if defined(ESP32) && (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH))
|
||||
#if defined(ESP32) && (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH) || defined(USE_M5STACK_CORE2))
|
||||
if (!strncmp(vname, "say(", 4)) {
|
||||
char text[SCRIPT_MAXSSIZE];
|
||||
lp = GetStringArgument(lp + 4, OPER_EQU, text, 0);
|
||||
|
@ -3161,7 +3174,7 @@ chknext:
|
|||
goto exit;
|
||||
}
|
||||
#endif // USE_TTGO_WATCH
|
||||
#if defined(USE_TTGO_WATCH) && defined(USE_FT5206)
|
||||
#if defined(USE_FT5206)
|
||||
if (!strncmp(vname, "wtch(", 5)) {
|
||||
lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0);
|
||||
fvar = Touch_Status(fvar);
|
||||
|
@ -7550,7 +7563,7 @@ bool Xdrv10(uint8_t function)
|
|||
// fs on SD card
|
||||
#ifdef ESP32
|
||||
if (PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_MISO) && PinUsed(GPIO_SPI_CLK)) {
|
||||
SPI.begin(Pin(GPIO_SPI_CLK),Pin(GPIO_SPI_MISO),Pin(GPIO_SPI_MOSI), -1);
|
||||
SPI.begin(Pin(GPIO_SPI_CLK), Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_MOSI), -1);
|
||||
}
|
||||
#endif // ESP32
|
||||
fsp = &SD;
|
||||
|
|
|
@ -2089,8 +2089,8 @@ uint32_t Touch_Status(uint32_t sel) {
|
|||
|
||||
|
||||
#ifdef USE_TOUCH_BUTTONS
|
||||
void Touch_MQTT(uint8_t index, const char *cp) {
|
||||
ResponseTime_P(PSTR(",\"FT5206\":{\"%s%d\":\"%d\"}}"), cp, index+1, buttons[index]->vpower.on_off);
|
||||
void Touch_MQTT(uint8_t index, const char *cp, uint32_t val) {
|
||||
ResponseTime_P(PSTR(",\"FT5206\":{\"%s%d\":\"%d\"}}"), cp, index+1, val);
|
||||
MqttPublishTeleSensor();
|
||||
}
|
||||
|
||||
|
@ -2100,6 +2100,10 @@ void Touch_RDW_BUTT(uint32_t count, uint32_t pwr) {
|
|||
else buttons[count]->vpower.on_off = 0;
|
||||
}
|
||||
|
||||
#ifdef USE_M5STACK_CORE2
|
||||
uint8_t tbstate[3];
|
||||
#endif
|
||||
|
||||
// check digitizer hit
|
||||
void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) {
|
||||
uint16_t temp;
|
||||
|
@ -2113,6 +2117,26 @@ uint8_t vbutt=0;
|
|||
|
||||
if (renderer) {
|
||||
|
||||
#ifdef USE_M5STACK_CORE2
|
||||
// handle 3 built in touch buttons
|
||||
uint16_t xcenter = 80;
|
||||
#define TDELTA 30
|
||||
#define TYPOS 275
|
||||
|
||||
for (uint32_t tbut = 0; tbut < 3; tbut++) {
|
||||
if (pLoc.x>(xcenter-TDELTA) && pLoc.x<(xcenter+TDELTA) && pLoc.y>(TYPOS-TDELTA) && pLoc.y<(TYPOS+TDELTA)) {
|
||||
// hit a button
|
||||
if (!(tbstate[tbut] & 1)) {
|
||||
// pressed
|
||||
tbstate[tbut] |= 1;
|
||||
//AddLog_P(LOG_LEVEL_INFO, PSTR("tbut: %d pressed"), tbut);
|
||||
Touch_MQTT(tbut, "BIB", tbstate[tbut] & 1);
|
||||
}
|
||||
}
|
||||
xcenter += 100;
|
||||
}
|
||||
#endif
|
||||
|
||||
rotconvert(&pLoc.x, &pLoc.y);
|
||||
|
||||
//AddLog_P(LOG_LEVEL_INFO, PSTR("touch %d - %d"), pLoc.x, pLoc.y);
|
||||
|
@ -2142,7 +2166,7 @@ uint8_t vbutt=0;
|
|||
cp="PBT";
|
||||
}
|
||||
buttons[count]->xdrawButton(buttons[count]->vpower.on_off);
|
||||
Touch_MQTT(count,cp);
|
||||
Touch_MQTT(count, cp, buttons[count]->vpower.on_off);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2156,6 +2180,16 @@ uint8_t vbutt=0;
|
|||
}
|
||||
} else {
|
||||
// no hit
|
||||
#ifdef USE_M5STACK_CORE2
|
||||
for (uint32_t tbut = 0; tbut < 3; tbut++) {
|
||||
if (tbstate[tbut] & 1) {
|
||||
// released
|
||||
tbstate[tbut] &= 0xfe;
|
||||
Touch_MQTT(tbut, "BIB", tbstate[tbut] & 1);
|
||||
//AddLog_P(LOG_LEVEL_INFO, PSTR("tbut: %d released"), tbut);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for (uint8_t count=0; count<MAXBUTTONS; count++) {
|
||||
if (buttons[count]) {
|
||||
buttons[count]->press(false);
|
||||
|
@ -2164,7 +2198,7 @@ uint8_t vbutt=0;
|
|||
if (buttons[count]->vpower.is_pushbutton) {
|
||||
// push button
|
||||
buttons[count]->vpower.on_off = 0;
|
||||
Touch_MQTT(count,"PBT");
|
||||
Touch_MQTT(count,"PBT", buttons[count]->vpower.on_off);
|
||||
buttons[count]->xdrawButton(buttons[count]->vpower.on_off);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
xdrv_84_core2.ino - ESP32 m5stack core2 support for Tasmota
|
||||
|
||||
Copyright (C) 2020 Gerhard Mutz and Theo Arends
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* remaining work:
|
||||
|
||||
i2s microphone, at least as loudness sensor
|
||||
rtc use after reboot, sync with internet on regular intervals.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef ESP32
|
||||
#ifdef USE_M5STACK_CORE2
|
||||
|
||||
#include <AXP192.h>
|
||||
#include <MPU6886.h>
|
||||
#include <BM8563_RTC.h>
|
||||
#include <i2c_bus.h>
|
||||
#include <soc/rtc.h>
|
||||
|
||||
#define XDRV_84 84
|
||||
|
||||
struct CORE2_globs {
|
||||
AXP192 Axp;
|
||||
MPU6886 Mpu;
|
||||
BM8563_RTC Rtc;
|
||||
bool ready;
|
||||
bool tset;
|
||||
uint32_t shutdownseconds;
|
||||
uint8_t shutdowndelay;
|
||||
|
||||
} core2_globs;
|
||||
|
||||
struct CORE2_ADC {
|
||||
float vbus_v;
|
||||
float batt_v;
|
||||
float temp;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int16_t z;
|
||||
} core2_adc;
|
||||
|
||||
// cause SC card is needed by scripter
|
||||
void CORE2_Module_Init(void) {
|
||||
|
||||
// m5stack uses pin 38 not selectable in tasmota
|
||||
SPI.setFrequency(40000000);
|
||||
SPI.begin(18, 38, 23, -1);
|
||||
// establish power chip on wire1 SDA 21, SCL 22
|
||||
core2_globs.Axp.begin();
|
||||
I2cSetActiveFound(AXP_ADDR, "AXP192");
|
||||
|
||||
core2_globs.Axp.SetAdcState(true);
|
||||
|
||||
core2_globs.Mpu.Init();
|
||||
I2cSetActiveFound(MPU6886_ADDRESS, "MPU6886");
|
||||
|
||||
core2_globs.Rtc.begin();
|
||||
I2cSetActiveFound(RTC_ADRESS, "RTC");
|
||||
|
||||
core2_globs.ready = true;
|
||||
}
|
||||
|
||||
|
||||
void CORE2_Init(void) {
|
||||
|
||||
}
|
||||
|
||||
void CORE2_audio_power(bool power) {
|
||||
core2_globs.Axp.SetSpkEnable(power);
|
||||
}
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
const char HTTP_CORE2[] PROGMEM =
|
||||
"{s}VBUS Voltage" "{m}%s V" "{e}"
|
||||
"{s}BATT Voltage" "{m}%s V" "{e}"
|
||||
"{s}Chip Temperature" "{m}%s C" "{e}";
|
||||
#ifdef USE_MPU6886
|
||||
const char HTTP_CORE2_MPU[] PROGMEM =
|
||||
"{s}MPU x" "{m}%d mg" "{e}"
|
||||
"{s}MPU y" "{m}%d mg" "{e}"
|
||||
"{s}MPU z" "{m}%d mg" "{e}";
|
||||
#endif // USE_MPU6886
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
|
||||
void CORE2_loop(uint32_t flg) {
|
||||
}
|
||||
|
||||
void CORE2_WebShow(uint32_t json) {
|
||||
|
||||
char vstring[32];
|
||||
char bvstring[32];
|
||||
char tstring[32];
|
||||
dtostrfd(core2_adc.vbus_v, 3, vstring);
|
||||
dtostrfd(core2_adc.batt_v, 3, bvstring);
|
||||
dtostrfd(core2_adc.temp, 2, tstring);
|
||||
|
||||
if (json) {
|
||||
ResponseAppend_P(PSTR(",\"CORE2\":{\"VBV\":%s,\"BV\":%s,\"CT\":%s"), vstring, bvstring, tstring);
|
||||
|
||||
#ifdef USE_MPU6886
|
||||
ResponseAppend_P(PSTR(",\"MPUX\":%d,\"MPUY\":%d,\"MPUZ\":%d"), core2_adc.x, core2_adc.y, core2_adc.z);
|
||||
#endif
|
||||
ResponseJsonEnd();
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_CORE2, vstring, bvstring, tstring);
|
||||
|
||||
#ifdef USE_MPU6886
|
||||
WSContentSend_PD(HTTP_CORE2_MPU, core2_adc.x, core2_adc.y, core2_adc.z);
|
||||
#endif // USE_MPU6886
|
||||
}
|
||||
}
|
||||
|
||||
const char CORE2_Commands[] PROGMEM = "CORE2|"
|
||||
"SHUTDOWN";
|
||||
|
||||
void (* const CORE2_Command[])(void) PROGMEM = {
|
||||
&CORE2_Shutdown};
|
||||
|
||||
|
||||
void CORE2_Shutdown(void) {
|
||||
if (XdrvMailbox.payload >= 30) {
|
||||
core2_globs.shutdownseconds = XdrvMailbox.payload;
|
||||
core2_globs.shutdowndelay = 10;
|
||||
}
|
||||
ResponseCmndNumber(XdrvMailbox.payload -2);
|
||||
}
|
||||
|
||||
void CORE2_DoShutdown(void) {
|
||||
SettingsSaveAll();
|
||||
RtcSettingsSave();
|
||||
core2_globs.Rtc.clearIRQ();
|
||||
core2_globs.Rtc.SetAlarmIRQ(core2_globs.shutdownseconds);
|
||||
delay(10);
|
||||
core2_globs.Axp.PowerOff();
|
||||
}
|
||||
|
||||
extern uint8_t tbstate[3];
|
||||
|
||||
float core2_setaxppin(uint32_t sel, uint32_t val) {
|
||||
switch (sel) {
|
||||
case 0:
|
||||
core2_globs.Axp.SetLed(val);
|
||||
break;
|
||||
case 1:
|
||||
core2_globs.Axp.SetLDOEnable(3, val);
|
||||
break;
|
||||
case 2:
|
||||
if (val<1 || val>3) val = 1;
|
||||
return tbstate[val - 1] & 1;
|
||||
break;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void core2_disp_pwr(uint8_t on) {
|
||||
core2_globs.Axp.SetDCDC3(on);
|
||||
}
|
||||
|
||||
// display dimmer ranges from 0-15
|
||||
// very little effect
|
||||
void core2_disp_dim(uint8_t dim) {
|
||||
uint16_t voltage = 2200;
|
||||
|
||||
voltage += ((uint32_t)dim*1200)/15;
|
||||
core2_globs.Axp.SetLcdVoltage(voltage);
|
||||
|
||||
|
||||
// core2_globs.Axp.ScreenBreath(dim);
|
||||
|
||||
}
|
||||
|
||||
void CORE2_EverySecond(void) {
|
||||
if (core2_globs.ready) {
|
||||
CORE2_GetADC();
|
||||
|
||||
if (RtcTime.year>2000 && core2_globs.tset==false) {
|
||||
RTC_TimeTypeDef RTCtime;
|
||||
RTCtime.Hours = RtcTime.hour;
|
||||
RTCtime.Minutes = RtcTime.minute;
|
||||
RTCtime.Seconds = RtcTime.second;
|
||||
core2_globs.Rtc.SetTime(&RTCtime);
|
||||
core2_globs.tset = true;
|
||||
}
|
||||
|
||||
if (core2_globs.shutdowndelay) {
|
||||
core2_globs.shutdowndelay--;
|
||||
if (!core2_globs.shutdowndelay) {
|
||||
CORE2_DoShutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// currents are not supported by hardware implementation
|
||||
void CORE2_GetADC(void) {
|
||||
core2_adc.vbus_v = core2_globs.Axp.GetVBusVoltage();
|
||||
core2_adc.batt_v = core2_globs.Axp.GetBatVoltage();
|
||||
core2_adc.temp = core2_globs.Axp.GetTempInAXP192();
|
||||
#ifdef USE_MPU6886
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
core2_globs.Mpu.getAccelData(&x, &y, &z);
|
||||
core2_adc.x=x*1000;
|
||||
core2_adc.y=y*1000;
|
||||
core2_adc.z=z*1000;
|
||||
#endif // USE_MPU6886
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xdrv84(uint8_t function) {
|
||||
bool result = false;
|
||||
|
||||
switch (function) {
|
||||
|
||||
case FUNC_WEB_SENSOR:
|
||||
#ifdef USE_WEBSERVER
|
||||
CORE2_WebShow(0);
|
||||
#endif
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
CORE2_WebShow(1);
|
||||
break;
|
||||
case FUNC_COMMAND:
|
||||
result = DecodeCommand(CORE2_Commands, CORE2_Command);
|
||||
break;
|
||||
case FUNC_MODULE_INIT:
|
||||
CORE2_Module_Init();
|
||||
break;
|
||||
case FUNC_INIT:
|
||||
CORE2_Init();
|
||||
break;
|
||||
case FUNC_EVERY_SECOND:
|
||||
CORE2_EverySecond();
|
||||
break;
|
||||
case FUNC_LOOP:
|
||||
CORE2_loop(1);
|
||||
break;
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_M5STACK_CORE2
|
||||
#endif // ESP32
|
|
@ -20,7 +20,7 @@
|
|||
//#ifdef USE_SPI
|
||||
#ifdef USE_SPI
|
||||
#ifdef USE_DISPLAY
|
||||
#ifdef USE_DISPLAY_ILI9341_2
|
||||
#if (defined(USE_DISPLAY_ILI9341_2) || defined(USE_DISPLAY_ILI9342))
|
||||
|
||||
#define XDSP_13 13
|
||||
|
||||
|
@ -42,9 +42,13 @@ extern uint8_t *buffer;
|
|||
extern uint8_t color_type;
|
||||
ILI9341_2 *ili9341_2;
|
||||
|
||||
#ifdef USE_FT5206
|
||||
#include <FT5206.h>
|
||||
#undef FT6336_address
|
||||
#define FT6336_address 0x38
|
||||
uint8_t ili9342_ctouch_counter = 0;
|
||||
#endif // USE_FT5206
|
||||
|
||||
#undef BACKPLANE_PIN
|
||||
#define BACKPLANE_PIN 4
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
|
@ -54,6 +58,7 @@ void ILI9341_2_InitDriver()
|
|||
Settings.display_model = XDSP_13;
|
||||
}
|
||||
|
||||
|
||||
if (XDSP_13 == Settings.display_model) {
|
||||
|
||||
if (Settings.display_width != ILI9341_2_TFTWIDTH) {
|
||||
|
@ -70,13 +75,17 @@ void ILI9341_2_InitDriver()
|
|||
fg_color = ILI9341_2_WHITE;
|
||||
bg_color = ILI9341_2_BLACK;
|
||||
|
||||
|
||||
#ifdef USE_M5STACK_CORE2
|
||||
ili9341_2 = new ILI9341_2(5, -2, 15, -2);
|
||||
#else
|
||||
// init renderer, may use hardware spi, however we use SSPI defintion because SD card uses SPI definition (2 spi busses)
|
||||
if (PinUsed(GPIO_SSPI_CS) && PinUsed(GPIO_OLED_RESET) && PinUsed(GPIO_BACKLIGHT) && PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_MISO) && PinUsed(GPIO_SSPI_SCLK) && PinUsed(GPIO_SSPI_DC)) {
|
||||
ili9341_2 = new ILI9341_2(Pin(GPIO_SSPI_CS), Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_MISO), Pin(GPIO_SSPI_SCLK), Pin(GPIO_OLED_RESET), Pin(GPIO_SSPI_DC), Pin(GPIO_BACKLIGHT));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ili9341_2->init(Settings.display_width,Settings.display_height);
|
||||
renderer = ili9341_2;
|
||||
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font);
|
||||
|
@ -92,9 +101,79 @@ void ILI9341_2_InitDriver()
|
|||
|
||||
color_type = COLOR_COLOR;
|
||||
|
||||
#ifdef ESP32
|
||||
#ifdef USE_FT5206
|
||||
// start digitizer with fixed adress and pins for esp32
|
||||
#define SDA_2 21
|
||||
#define SCL_2 22
|
||||
Wire1.begin(SDA_2, SCL_2, 400000);
|
||||
Touch_Init(Wire1);
|
||||
#endif // USE_FT5206
|
||||
#endif // ESP32
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void core2_disp_pwr(uint8_t on);
|
||||
void core2_disp_dim(uint8_t dim);
|
||||
|
||||
void ili9342_bpwr(uint8_t on) {
|
||||
#ifdef USE_M5STACK_CORE2
|
||||
core2_disp_pwr(on);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ili9342_dimm(uint8_t dim) {
|
||||
#ifdef USE_M5STACK_CORE2
|
||||
core2_disp_dim(dim);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ESP32
|
||||
#ifdef USE_FT5206
|
||||
#ifdef USE_TOUCH_BUTTONS
|
||||
|
||||
void ili9342_RotConvert(int16_t *x, int16_t *y) {
|
||||
|
||||
int16_t temp;
|
||||
if (renderer) {
|
||||
uint8_t rot=renderer->getRotation();
|
||||
switch (rot) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
temp=*y;
|
||||
*y=renderer->height()-*x;
|
||||
*x=temp;
|
||||
break;
|
||||
case 2:
|
||||
*x=renderer->width()-*x;
|
||||
*y=renderer->height()-*y;
|
||||
break;
|
||||
case 3:
|
||||
temp=*y;
|
||||
*y=*x;
|
||||
*x=renderer->width()-temp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check digitizer hit
|
||||
void ili9342_CheckTouch() {
|
||||
ili9342_ctouch_counter++;
|
||||
if (2 == ili9342_ctouch_counter) {
|
||||
// every 100 ms should be enough
|
||||
ili9342_ctouch_counter = 0;
|
||||
Touch_Check(ili9342_RotConvert);
|
||||
}
|
||||
}
|
||||
#endif // USE_TOUCH_BUTTONS
|
||||
#endif // USE_FT5206
|
||||
#endif // ESP32
|
||||
|
||||
|
||||
/*********************************************************************************************/
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
|
@ -111,6 +190,15 @@ bool Xdsp13(uint8_t function)
|
|||
case FUNC_DISPLAY_MODEL:
|
||||
result = true;
|
||||
break;
|
||||
#ifdef USE_FT5206
|
||||
#ifdef USE_TOUCH_BUTTONS
|
||||
case FUNC_DISPLAY_EVERY_50_MSECOND:
|
||||
if (FT5206_found) {
|
||||
ili9342_CheckTouch();
|
||||
}
|
||||
break;
|
||||
#endif // USE_TOUCH_BUTTONS
|
||||
#endif // USE_FT5206
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
Loading…
Reference in New Issue