worked on SPI, fixed some bugs
adjusted LCD code added code for INA3221 worked on UI
This commit is contained in:
120
ext/lcd/ST7735.h
120
ext/lcd/ST7735.h
@@ -84,80 +84,88 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
#define V 128
|
static constexpr const int V = 128;
|
||||||
#define H 160
|
static constexpr const int H = 160;
|
||||||
|
|
||||||
void waitLong() {
|
inline void waitLong() {
|
||||||
for (int i = 0; i < 50; ++i) {
|
//vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||||
//os_delay_us(10*1000);
|
for (int i = 0; i < 0x1FFFFF; ++i) {asm("nop");} // vTaskDelay seems not to block? maybe when display is allocated outside of a function?
|
||||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void waitShort() {
|
inline void waitShort() {
|
||||||
//os_delay_us(10*1000);
|
//vTaskDelay(20 / portTICK_PERIOD_MS);
|
||||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
for (int i = 0; i < 0xFFFF; ++i) {asm("nop");}
|
||||||
}
|
}
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
|
|
||||||
//spi::init();
|
debugMod(NAME, "init()");
|
||||||
|
|
||||||
|
select();
|
||||||
|
sendCommand(ST7735_SWRESET); // 1: Software reset, 0 args
|
||||||
|
deselect();
|
||||||
|
waitLong();
|
||||||
|
|
||||||
|
select();
|
||||||
|
sendCommand(ST7735_SLPOUT); // 2: Out of sleep mode, 0 args
|
||||||
|
deselect();
|
||||||
|
waitLong();
|
||||||
|
|
||||||
select();
|
select();
|
||||||
|
|
||||||
sendCommand(ST7735_SWRESET); // 1: Software reset, 0 args
|
|
||||||
waitLong();
|
|
||||||
|
|
||||||
sendCommand(ST7735_SLPOUT); // 2: Out of sleep mode, 0 args
|
|
||||||
waitLong();
|
|
||||||
|
|
||||||
sendCommand(ST7735_FRMCTR1); // 3: Frame rate ctrl - normal mode) 3 args: 0xb1
|
sendCommand(ST7735_FRMCTR1); // 3: Frame rate ctrl - normal mode) 3 args: 0xb1
|
||||||
sendData(0x01); sendData(0x2C); sendData(0x2D); // Rate = fosc/(1x2+40) * (LINE+2C+2D)
|
sendData(0x01); sendData(0x2C); sendData(0x2D); // Rate = fosc/(1x2+40) * (LINE+2C+2D)
|
||||||
|
waitShort();
|
||||||
|
|
||||||
sendCommand(ST7735_FRMCTR2); // 4: Frame rate control - idle mode) 3 args: 0xb2
|
sendCommand(ST7735_FRMCTR2); // 4: Frame rate control - idle mode) 3 args: 0xb2
|
||||||
sendData(0x01); sendData(0x2C); sendData(0x2D); // Rate = fosc/(1x2+40) * (LINE+2C+2D)
|
sendData(0x01); sendData(0x2C); sendData(0x2D); // Rate = fosc/(1x2+40) * (LINE+2C+2D)
|
||||||
|
waitShort();
|
||||||
|
|
||||||
sendCommand(ST7735_FRMCTR3); // 5: Frame rate ctrl - partial mode) 6 args: 0xb3
|
sendCommand(ST7735_FRMCTR3); // 5: Frame rate ctrl - partial mode) 6 args: 0xb3
|
||||||
sendData(0x01); sendData(0x2C); sendData(0x2D); // Dot inversion mode
|
sendData(0x01); sendData(0x2C); sendData(0x2D); // Dot inversion mode
|
||||||
sendData(0x01); sendData(0x2C); sendData(0x2D); // Line inversion mode
|
sendData(0x01); sendData(0x2C); sendData(0x2D); // Line inversion mode
|
||||||
|
waitShort();
|
||||||
|
|
||||||
sendCommand(ST7735_INVCTR); // 6: Display inversion ctrl) 1 arg) no delay: 0xb4
|
sendCommand(ST7735_INVCTR); // 6: Display inversion ctrl) 1 arg) no delay: 0xb4
|
||||||
sendData(0x07); // No inversion
|
sendData(0x07); // No inversion
|
||||||
|
|
||||||
sendCommand(ST7735_PWCTR1); // 7: Power control) 3 args) no delay: 0xc0
|
sendCommand(ST7735_PWCTR1); // 7: Power control) 3 args) no delay: 0xc0
|
||||||
sendData(0xA2);
|
sendData(0xA2);
|
||||||
sendData(0x02); // -4.6V
|
sendData(0x02); // -4.6V
|
||||||
sendData(0x84); // AUTO mode
|
sendData(0x84); // AUTO mode
|
||||||
|
|
||||||
sendCommand(ST7735_PWCTR2); // 8: Power control) 1 arg) no delay: 0xc1
|
sendCommand(ST7735_PWCTR2); // 8: Power control) 1 arg) no delay: 0xc1
|
||||||
sendData(0xC5); // VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD
|
sendData(0xC5); // VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD
|
||||||
|
|
||||||
sendCommand(ST7735_PWCTR3); // 9: Power control) 2 args) no delay: 0xc2
|
sendCommand(ST7735_PWCTR3); // 9: Power control) 2 args) no delay: 0xc2
|
||||||
sendData(0x0A); // Opamp current small
|
sendData(0x0A); // Opamp current small
|
||||||
sendData(0x00); // Boost frequency
|
sendData(0x00); // Boost frequency
|
||||||
|
|
||||||
sendCommand(ST7735_PWCTR4); // 10: Power control) 2 args) no delay:
|
sendCommand(ST7735_PWCTR4); // 10: Power control) 2 args) no delay:
|
||||||
sendData(0x8A); // BCLK/2) Opamp current small & Medium low
|
sendData(0x8A); // BCLK/2) Opamp current small & Medium low
|
||||||
sendData(0x2A);
|
sendData(0x2A);
|
||||||
|
|
||||||
sendCommand(ST7735_PWCTR5); // 11: Power control) 2 args) no delay:
|
sendCommand(ST7735_PWCTR5); // 11: Power control) 2 args) no delay:
|
||||||
sendData(0x8A); sendData(0xEE);
|
sendData(0x8A); sendData(0xEE);
|
||||||
|
|
||||||
sendCommand(ST7735_VMCTR1); // 12: Power control) 1 arg) no delay:
|
sendCommand(ST7735_VMCTR1); // 12: Power control) 1 arg) no delay:
|
||||||
sendData(0x0E);
|
sendData(0x0E);
|
||||||
|
|
||||||
sendCommand(ST7735_INVOFF); // 13: Don't invert display) no args) no delay 0x20
|
sendCommand(ST7735_INVOFF); // 13: Don't invert display) no args) no delay 0x20
|
||||||
|
|
||||||
sendCommand(ST7735_MADCTL); // 14: Memory access control (directions)) 1 arg:
|
sendCommand(ST7735_MADCTL); // 14: Memory access control (directions)) 1 arg:
|
||||||
sendData(0xC8); // row addr/col addr); bottom to top refresh
|
sendData(0xC8); // row addr/col addr); bottom to top refresh
|
||||||
|
waitShort();
|
||||||
|
|
||||||
sendCommand(ST7735_COLMOD); // 15: set color mode); 1 arg); no delay:
|
sendCommand(ST7735_COLMOD); // 15: set color mode); 1 arg); no delay:
|
||||||
sendData(0x05); // 16-bit color
|
sendData(0x05); // 16-bit color
|
||||||
|
|
||||||
|
deselect();
|
||||||
|
|
||||||
|
// required??? adjusts colors or something???
|
||||||
|
if (1 == 1) {
|
||||||
|
|
||||||
// required???
|
select();
|
||||||
if (1 == 1) {
|
|
||||||
|
|
||||||
sendCommand(ST7735_GMCTRP1); // 1: Magical unicorn dust, 16 args, no delay:
|
sendCommand(ST7735_GMCTRP1); // 1: Magical unicorn dust, 16 args, no delay:
|
||||||
sendData(0x02); sendData(0x1c); sendData(0x07); sendData(0x12);
|
sendData(0x02); sendData(0x1c); sendData(0x07); sendData(0x12);
|
||||||
sendData(0x37); sendData(0x32); sendData(0x29); sendData(0x2d);
|
sendData(0x37); sendData(0x32); sendData(0x29); sendData(0x2d);
|
||||||
@@ -169,17 +177,20 @@ private:
|
|||||||
sendData(0x2E); sendData(0x2C); sendData(0x29); sendData(0x2D);
|
sendData(0x2E); sendData(0x2C); sendData(0x29); sendData(0x2D);
|
||||||
sendData(0x2E); sendData(0x2E); sendData(0x37); sendData(0x3F);
|
sendData(0x2E); sendData(0x2E); sendData(0x37); sendData(0x3F);
|
||||||
sendData(0x00); sendData(0x00); sendData(0x02); sendData(0x10);
|
sendData(0x00); sendData(0x00); sendData(0x02); sendData(0x10);
|
||||||
|
deselect();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
select();
|
||||||
|
|
||||||
sendCommand(ST7735_NORON); // 3: Normal display on, no args
|
sendCommand(ST7735_NORON); // 3: Normal display on, no args
|
||||||
waitShort();
|
|
||||||
|
|
||||||
sendCommand(ST7735_DISPON); // 4: Main screen turn on, no args
|
|
||||||
waitLong();
|
|
||||||
|
|
||||||
deselect();
|
deselect();
|
||||||
|
waitLong();
|
||||||
|
|
||||||
|
select();
|
||||||
|
sendCommand(ST7735_DISPON); // 4: Main screen turn on, no args
|
||||||
|
deselect();
|
||||||
|
waitLong();
|
||||||
|
|
||||||
debugMod(NAME, "init() done");
|
debugMod(NAME, "init() done");
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -223,21 +234,22 @@ public:
|
|||||||
|
|
||||||
select();
|
select();
|
||||||
|
|
||||||
sendCommand(ST7735_CASET); // Column addr set
|
sendCommand(ST7735_CASET); // Column addr set
|
||||||
sendData(0x00);
|
sendData(0x00);
|
||||||
sendData(0); // XSTART
|
sendData(0); // XSTART
|
||||||
sendData(0x00);
|
sendData(0x00);
|
||||||
sendData(V-1); // XEND
|
sendData(V-1); // XEND
|
||||||
|
|
||||||
sendCommand(ST7735_RASET); // Row addr set
|
sendCommand(ST7735_RASET); // Row addr set
|
||||||
sendData(0x00);
|
sendData(0x00);
|
||||||
sendData(0); // YSTART
|
sendData(0); // YSTART
|
||||||
sendData(0x00);
|
sendData(0x00);
|
||||||
sendData(H-1); // YEND
|
sendData(H-1); // YEND
|
||||||
|
|
||||||
sendCommand(ST7735_RAMWR);
|
sendCommand(ST7735_RAMWR);
|
||||||
|
|
||||||
modeData();
|
modeData();
|
||||||
|
/*
|
||||||
for (int i = 0; i < (V*H); ++i) {
|
for (int i = 0; i < (V*H); ++i) {
|
||||||
const uint16_t color = data[i];
|
const uint16_t color = data[i];
|
||||||
//const uint8_t lo = color & 0xFF;
|
//const uint8_t lo = color & 0xFF;
|
||||||
@@ -246,7 +258,9 @@ public:
|
|||||||
//sendData(hi);
|
//sendData(hi);
|
||||||
//spi::writeWord(color);
|
//spi::writeWord(color);
|
||||||
spi.writeWord(color);
|
spi.writeWord(color);
|
||||||
}
|
}*/
|
||||||
|
spi.write((const uint8_t*)data, V*H*sizeof(uint16_t));
|
||||||
|
|
||||||
|
|
||||||
deselect();
|
deselect();
|
||||||
|
|
||||||
@@ -258,43 +272,31 @@ private:
|
|||||||
|
|
||||||
void sendData(uint8_t data) {
|
void sendData(uint8_t data) {
|
||||||
modeData();
|
modeData();
|
||||||
//select();
|
|
||||||
//spi::writeByte(data);
|
|
||||||
spi.writeByte(data);
|
spi.writeByte(data);
|
||||||
//deselect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendCommand(uint8_t cmd) {
|
void sendCommand(uint8_t cmd) {
|
||||||
modeCommand();
|
modeCommand();
|
||||||
//select();
|
|
||||||
//spi::writeByte(cmd);
|
|
||||||
spi.writeByte(cmd);
|
spi.writeByte(cmd);
|
||||||
//deselect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** switch D/C line low */
|
/** switch D/C line low */
|
||||||
inline void modeCommand() {
|
inline void modeCommand() {
|
||||||
//GPIO5_OUTPUT_SET;
|
|
||||||
//GPIO5_L;
|
|
||||||
MyGPIO::clear(PIN_DATA_COMMAND);
|
MyGPIO::clear(PIN_DATA_COMMAND);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** switch D/C line high */
|
/** switch D/C line high */
|
||||||
inline void modeData() {
|
inline void modeData() {
|
||||||
//GPIO5_OUTPUT_SET;
|
|
||||||
//GPIO5_H;
|
|
||||||
MyGPIO::set(PIN_DATA_COMMAND);
|
MyGPIO::set(PIN_DATA_COMMAND);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** set CS = low */
|
/** set CS = low */
|
||||||
inline void select() {
|
inline void select() {
|
||||||
MyGPIO::clear(PIN_CS);
|
MyGPIO::clear(PIN_CS);
|
||||||
//spi::chipSelect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** set CS = high */
|
/** set CS = high */
|
||||||
inline void deselect() {
|
inline void deselect() {
|
||||||
//spi::chipDeselect();
|
|
||||||
MyGPIO::set(PIN_CS);
|
MyGPIO::set(PIN_CS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,15 +44,16 @@ class UI {
|
|||||||
UIPainter p;
|
UIPainter p;
|
||||||
UIElement root;
|
UIElement root;
|
||||||
|
|
||||||
UIElement* eFocused = nullptr;
|
int focusIdx = 0;
|
||||||
|
//UIElement* eFocused = nullptr;
|
||||||
UIElement* eDown = nullptr;
|
UIElement* eDown = nullptr;
|
||||||
|
|
||||||
Color cBackground = Color::fromRGB(180,240,180);
|
Color cBackground = Color::fromRGB(180,240,180);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
UI() {
|
UI(int w, int h) {
|
||||||
root.setRect(0,0,240,320);
|
root.setRect(0,0,w,h);
|
||||||
root.setVisible(true);
|
root.setVisible(true);
|
||||||
p.setFG(cBackground);
|
p.setFG(cBackground);
|
||||||
p.fillRect(root.getRect());
|
p.fillRect(root.getRect());
|
||||||
@@ -77,7 +78,6 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onTouchDone() {
|
void onTouchDone() {
|
||||||
@@ -87,13 +87,28 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void focusNext() {
|
||||||
|
root.children[focusIdx]->setFocus(false);
|
||||||
|
focusIdx = (focusIdx + 1) % root.children.size();
|
||||||
|
root.children[focusIdx]->setFocus(true);
|
||||||
|
}
|
||||||
|
void focusPrev() {
|
||||||
|
root.children[focusIdx]->setFocus(false);
|
||||||
|
focusIdx = ((focusIdx - 1) + root.children.size()) % root.children.size();
|
||||||
|
root.children[focusIdx]->setFocus(true);
|
||||||
|
}
|
||||||
|
|
||||||
void draw() {
|
void draw() {
|
||||||
//debugMod1("UI", "draw %zu elements", elements.size());
|
//debugMod1("UI", "draw %zu elements", elements.size());
|
||||||
// for (UIElement* e : elements) {
|
// for (UIElement* e : elements) {
|
||||||
// e->_draw(p);
|
// e->_draw(p);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
//p.setFG(cBackground);
|
||||||
|
//p.fillRect(root.getRect());
|
||||||
|
|
||||||
root._draw(p);
|
root._draw(p);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ private:
|
|||||||
|
|
||||||
const Color fillNormal = Color::fromRGB(180,180,180);
|
const Color fillNormal = Color::fromRGB(180,180,180);
|
||||||
const Color fillDown = Color::fromRGB(120,120,120);
|
const Color fillDown = Color::fromRGB(120,120,120);
|
||||||
|
const Color fillFocus = Color::fromRGB(120,120,140);
|
||||||
|
|
||||||
|
|
||||||
const Color frameBright = Color::fromRGB(230,230,230);
|
const Color frameBright = Color::fromRGB(230,230,230);
|
||||||
const Color frameDark = Color::fromRGB(50,50,50);
|
const Color frameDark = Color::fromRGB(50,50,50);
|
||||||
|
|
||||||
@@ -58,7 +61,11 @@ public:
|
|||||||
|
|
||||||
void draw(UIPainter& p) override {
|
void draw(UIPainter& p) override {
|
||||||
|
|
||||||
p.setFG( down ? fillDown : fillNormal );
|
if (focus) {
|
||||||
|
p.setFG( fillFocus );
|
||||||
|
} else {
|
||||||
|
p.setFG( down ? fillDown : fillNormal );
|
||||||
|
}
|
||||||
p.fillRect(rect);
|
p.fillRect(rect);
|
||||||
|
|
||||||
p.setFG( down ? frameDark : frameBright );
|
p.setFG( down ? frameDark : frameBright );
|
||||||
|
|||||||
@@ -15,13 +15,20 @@ protected:
|
|||||||
UIRect rect;
|
UIRect rect;
|
||||||
bool _visible = true;
|
bool _visible = true;
|
||||||
bool _needsRedraw = true;
|
bool _needsRedraw = true;
|
||||||
|
|
||||||
|
bool opaque = true;
|
||||||
|
bool focus = false;
|
||||||
|
|
||||||
std::vector<UIElement*> children;
|
std::vector<UIElement*> children;
|
||||||
|
|
||||||
static constexpr const char* TAG = "UIElement";
|
static constexpr const char* TAG = "UIElement";
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
void setOpaque(bool opaque) {
|
||||||
|
this->opaque = opaque;
|
||||||
|
}
|
||||||
|
|
||||||
void setRect(const UIRect r) {
|
void setRect(const UIRect r) {
|
||||||
this->rect = r;
|
this->rect = r;
|
||||||
setNeedsRedraw();
|
setNeedsRedraw();
|
||||||
@@ -44,6 +51,11 @@ public:
|
|||||||
return this->_visible;
|
return this->_visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setFocus(bool focus) {
|
||||||
|
this->focus = focus;
|
||||||
|
setNeedsRedraw();
|
||||||
|
}
|
||||||
|
|
||||||
void setNeedsRedraw() {
|
void setNeedsRedraw() {
|
||||||
this->_needsRedraw = true;
|
this->_needsRedraw = true;
|
||||||
}
|
}
|
||||||
@@ -99,7 +111,7 @@ protected:
|
|||||||
|
|
||||||
void _draw(UIPainter& p) {
|
void _draw(UIPainter& p) {
|
||||||
|
|
||||||
// if hidde, ignore for me and children
|
// if hiden, ignore for me and children
|
||||||
if (!_visible) {return;}
|
if (!_visible) {return;}
|
||||||
|
|
||||||
// draw myself (if needed)
|
// draw myself (if needed)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
class UILabel : public UIElement {
|
class UILabel : public UIElement {
|
||||||
|
|
||||||
std::string txt;
|
std::string txt;
|
||||||
|
|
||||||
Color cBackground = Color::fromRGB(255,255,255);
|
Color cBackground = Color::fromRGB(255,255,255);
|
||||||
Color cText = Color::fromRGB(0,0,0);
|
Color cText = Color::fromRGB(0,0,0);
|
||||||
|
|
||||||
@@ -21,18 +21,21 @@ public:
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** set the text to draw */
|
||||||
void setText(const std::string& txt) {
|
void setText(const std::string& txt) {
|
||||||
this->txt = txt;
|
this->txt = txt;
|
||||||
setNeedsRedraw();
|
setNeedsRedraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void draw(UIPainter& p) {
|
/** draw the label */
|
||||||
|
void draw(UIPainter& p) override {
|
||||||
|
|
||||||
p.setFG(cBackground);
|
if (opaque) {
|
||||||
p.fillRect(rect);
|
p.setFG(cBackground);
|
||||||
|
p.fillRect(rect);
|
||||||
//const uint16_t txtW = fnt_f1.getWidth(txt);
|
}
|
||||||
//const uint16_t txtH = fnt_f1.getHeight();
|
|
||||||
|
|
||||||
p.setFG(cText);
|
p.setFG(cText);
|
||||||
p.drawText(rect.x, rect.y, txt.c_str());
|
p.drawText(rect.x, rect.y, txt.c_str());
|
||||||
|
|||||||
@@ -380,9 +380,11 @@ private:
|
|||||||
|
|
||||||
/** check the chip's version */
|
/** check the chip's version */
|
||||||
void check() {
|
void check() {
|
||||||
|
idle();
|
||||||
uint8_t version = readRegister(REG_VERSION);
|
uint8_t version = readRegister(REG_VERSION);
|
||||||
debugMod1(NAME, "version %d", version);
|
debugMod1(NAME, "version %d", version);
|
||||||
if (version != 0x12) {debugMod(NAME, "!! unsupported chip version detected");}
|
if (version != 0x12) {debugMod(NAME, "!! unsupported chip version detected");}
|
||||||
|
sleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** what exactly is this? */
|
/** what exactly is this? */
|
||||||
|
|||||||
89
ext/sens/INA3221.h
Normal file
89
ext/sens/INA3221.h
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#ifndef SENS_INA_3221
|
||||||
|
#define SENS_INA_3221
|
||||||
|
|
||||||
|
/** 3-Channel i2c volt/ampere sensor */
|
||||||
|
|
||||||
|
template <typename I2C> class INA3221 {
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
I2C& i2c;
|
||||||
|
static constexpr const uint8_t ADDR = 0b1000000;
|
||||||
|
static constexpr const char* NAME = "INA3221";
|
||||||
|
|
||||||
|
static constexpr const uint8_t REG_CFG = 0x00;
|
||||||
|
|
||||||
|
static constexpr const uint8_t REG_CH1_VS = 0x01; // shunt voltage
|
||||||
|
static constexpr const uint8_t REG_CH1_VB = 0x02; // bus voltage
|
||||||
|
|
||||||
|
static constexpr const uint8_t REG_CH2_VS = 0x03;
|
||||||
|
static constexpr const uint8_t REG_CH2_VB = 0x04;
|
||||||
|
|
||||||
|
static constexpr const uint8_t REG_CH3_VS = 0x05;
|
||||||
|
static constexpr const uint8_t REG_CH3_VB = 0x06;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
struct Channel {
|
||||||
|
int16_t vShunt;
|
||||||
|
int16_t vBus;
|
||||||
|
};
|
||||||
|
struct Voltages {
|
||||||
|
Channel ch1;
|
||||||
|
Channel ch2;
|
||||||
|
Channel ch3;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
INA3221(I2C& i2c) : i2c(i2c) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** get the current config */
|
||||||
|
uint16_t getConfig() {
|
||||||
|
uint16_t res = 0;
|
||||||
|
i2c.readReg(ADDR, REG_CFG, 2, (uint8_t*)&res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** read all 6 voltages (3 channels, each shunt and bus) */
|
||||||
|
Voltages getVoltages() {
|
||||||
|
|
||||||
|
uint8_t buf[2];
|
||||||
|
Voltages res;
|
||||||
|
|
||||||
|
i2c.readReg(ADDR, REG_CH1_VS, sizeof(buf), buf);
|
||||||
|
res.ch1.vShunt = getVoltage(buf);
|
||||||
|
i2c.readReg(ADDR, REG_CH1_VB, sizeof(buf), buf);
|
||||||
|
res.ch1.vBus = getVoltage(buf);
|
||||||
|
|
||||||
|
i2c.readReg(ADDR, REG_CH2_VS, sizeof(buf), buf);
|
||||||
|
res.ch2.vShunt = getVoltage(buf);
|
||||||
|
i2c.readReg(ADDR, REG_CH2_VB, sizeof(buf), buf);
|
||||||
|
res.ch2.vBus = getVoltage(buf);
|
||||||
|
|
||||||
|
i2c.readReg(ADDR, REG_CH3_VS, sizeof(buf), buf);
|
||||||
|
res.ch3.vShunt = getVoltage(buf);
|
||||||
|
i2c.readReg(ADDR, REG_CH3_VB, sizeof(buf), buf);
|
||||||
|
res.ch3.vBus = getVoltage(buf);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** is an INA3221 present on the bus? */
|
||||||
|
bool isPresent() {
|
||||||
|
return i2c.query(ADDR);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** convert to bytes into a mV reading */
|
||||||
|
int16_t getVoltage(const uint8_t* buf) {
|
||||||
|
return ((buf[0] << 8) | (buf[1] << 0)); // the lowest 3 bits are always zero. no shift required!
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SENS_INA_3221
|
||||||
22
io/GPIO.h
22
io/GPIO.h
@@ -98,6 +98,11 @@
|
|||||||
|
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
|
|
||||||
|
// NOTE from the manual
|
||||||
|
// GPIO 6-11 are usually used for SPI flash.
|
||||||
|
// GPIO 34-39 can only be set as input mode and do not have software pullup or pulldown functions.
|
||||||
|
|
||||||
|
|
||||||
struct MyGPIO {
|
struct MyGPIO {
|
||||||
|
|
||||||
static inline bool get(const uint8_t num) {
|
static inline bool get(const uint8_t num) {
|
||||||
@@ -134,7 +139,7 @@
|
|||||||
io_conf.pin_bit_mask = (1<<num);
|
io_conf.pin_bit_mask = (1<<num);
|
||||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||||
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
|
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||||
gpio_config(&io_conf);
|
ESP_ERROR_CHECK(gpio_config(&io_conf));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void setInput(const uint8_t num) {
|
static inline void setInput(const uint8_t num) {
|
||||||
@@ -148,7 +153,20 @@
|
|||||||
io_conf.pin_bit_mask = (1<<num);
|
io_conf.pin_bit_mask = (1<<num);
|
||||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||||
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
|
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||||
gpio_config(&io_conf);
|
ESP_ERROR_CHECK(gpio_config(&io_conf));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void setInputPullUp(const uint8_t num) {
|
||||||
|
setInputPullUp((gpio_num_t)num);
|
||||||
|
}
|
||||||
|
static inline void setInputPullUp(const gpio_num_t num) {
|
||||||
|
gpio_config_t io_conf;
|
||||||
|
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||||
|
io_conf.mode = GPIO_MODE_INPUT;
|
||||||
|
io_conf.pin_bit_mask = (1<<num);
|
||||||
|
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||||
|
io_conf.pull_up_en = GPIO_PULLUP_ENABLE; // here
|
||||||
|
ESP_ERROR_CHECK(gpio_config(&io_conf));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void toggleBuiltInLED() {
|
static void toggleBuiltInLED() {
|
||||||
|
|||||||
28
io/HardSPI.h
28
io/HardSPI.h
@@ -51,7 +51,7 @@ private:
|
|||||||
buscfg.sclk_io_num = PIN_NUM_CLK;
|
buscfg.sclk_io_num = PIN_NUM_CLK;
|
||||||
buscfg.quadwp_io_num = -1;
|
buscfg.quadwp_io_num = -1;
|
||||||
buscfg.quadhd_io_num = -1;
|
buscfg.quadhd_io_num = -1;
|
||||||
buscfg.max_transfer_sz = MAX_LEN;//320*240*2;
|
buscfg.max_transfer_sz = MAX_LEN;
|
||||||
buscfg.flags = 0;
|
buscfg.flags = 0;
|
||||||
buscfg.intr_flags = 0;
|
buscfg.intr_flags = 0;
|
||||||
|
|
||||||
@@ -80,9 +80,12 @@ public:
|
|||||||
void write(const uint8_t* data, size_t len) {
|
void write(const uint8_t* data, size_t len) {
|
||||||
|
|
||||||
spi_transaction_t t;
|
spi_transaction_t t;
|
||||||
memset(&t, 0, sizeof(spi_transaction_t));
|
|
||||||
|
|
||||||
while(len > 0) {
|
while(len > 0) {
|
||||||
|
|
||||||
|
// ensure the transaction is reset to defaults.
|
||||||
|
// this is mandatory! as the ESP adjusts some parameters while/after sending!
|
||||||
|
memset(&t, 0, sizeof(spi_transaction_t));
|
||||||
|
|
||||||
const size_t chunkLen = min(MAX_LEN, (len));
|
const size_t chunkLen = min(MAX_LEN, (len));
|
||||||
t.length = 8 * chunkLen; // in bits
|
t.length = 8 * chunkLen; // in bits
|
||||||
@@ -136,6 +139,23 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** send 4 bytes onto the bus while reading 4 bytes response */
|
||||||
|
uint8_t readWriteByte(uint8_t write) {
|
||||||
|
|
||||||
|
spi_transaction_t t;
|
||||||
|
memset(&t, 0, sizeof(spi_transaction_t));
|
||||||
|
t.length = 8*1;
|
||||||
|
t.rxlength = 8*1;
|
||||||
|
t.tx_data[0] = (write >> 0) & 0xFF;
|
||||||
|
t.flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA;
|
||||||
|
|
||||||
|
esp_err_t ret = spi_device_polling_transmit(spi, &t);
|
||||||
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
|
return (static_cast<uint32_t>(t.rx_data[0]));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/** send 4 bytes onto the bus while reading 4 bytes response */
|
/** send 4 bytes onto the bus while reading 4 bytes response */
|
||||||
uint32_t readWriteQuad(uint32_t write) {
|
uint32_t readWriteQuad(uint32_t write) {
|
||||||
|
|
||||||
@@ -220,6 +240,10 @@ public:
|
|||||||
ESP_ERROR_CHECK(ret);
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t min(size_t a, size_t b) {
|
||||||
|
return (a < b) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
16
io/SoftI2C.h
16
io/SoftI2C.h
@@ -24,8 +24,7 @@ template <int PIN_SDA, int PIN_SCL, bool fast> class SoftI2C {
|
|||||||
inline void sclLo() {MyGPIO::clear(PIN_SCL);}
|
inline void sclLo() {MyGPIO::clear(PIN_SCL);}
|
||||||
|
|
||||||
inline void waitLong() {
|
inline void waitLong() {
|
||||||
for (uint8_t i = 0; i < 240; ++i) {
|
for (uint16_t i = 0; i < 1024; ++i) {
|
||||||
__asm__ __volatile__("nop");
|
|
||||||
__asm__ __volatile__("nop");
|
__asm__ __volatile__("nop");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,7 +32,6 @@ template <int PIN_SDA, int PIN_SCL, bool fast> class SoftI2C {
|
|||||||
inline void waitShort() {
|
inline void waitShort() {
|
||||||
for (uint8_t i = 0; i < 240; ++i) {
|
for (uint8_t i = 0; i < 240; ++i) {
|
||||||
__asm__ __volatile__("nop");
|
__asm__ __volatile__("nop");
|
||||||
__asm__ __volatile__("nop");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,14 +154,14 @@ public:
|
|||||||
|
|
||||||
// select register(s) to read
|
// select register(s) to read
|
||||||
ok = startWrite(addr);
|
ok = startWrite(addr);
|
||||||
if (!ok) {debugMod(NAME, "failed start write1\n"); return false;}
|
if (!ok) {debugMod(NAME, "failed start write(1)"); return false;}
|
||||||
ok = writeByteAndCheck(reg);
|
ok = writeByteAndCheck(reg);
|
||||||
if (!ok) {debugMod(NAME, "failed select register\n"); return false;}
|
if (!ok) {debugMod(NAME, "failed select register"); return false;}
|
||||||
stop();
|
stop();
|
||||||
|
|
||||||
// read register(s)
|
// read register(s)
|
||||||
ok = startRead(addr);
|
ok = startRead(addr);
|
||||||
if (!ok) {debugMod(NAME, "failed start write2\n"); return false;}
|
if (!ok) {debugMod(NAME, "failed start write(2)"); return false;}
|
||||||
readBytes(dst, len);
|
readBytes(dst, len);
|
||||||
stop();
|
stop();
|
||||||
|
|
||||||
@@ -178,11 +176,11 @@ public:
|
|||||||
|
|
||||||
// address the slave in write mode and select the first register to read
|
// address the slave in write mode and select the first register to read
|
||||||
ok = startWrite(addr);
|
ok = startWrite(addr);
|
||||||
if (!ok) {debugMod(NAME, "failed start write\n"); return false;}
|
if (!ok) {debugMod(NAME, "failed start write"); return false;}
|
||||||
ok = writeByteAndCheck(reg);
|
ok = writeByteAndCheck(reg);
|
||||||
if (!ok) {debugMod1(NAME, "failed to select register %d\n", addr); return false;}
|
if (!ok) {debugMod1(NAME, "failed to select register %d", addr); return false;}
|
||||||
ok = writeBytesAndCheck(src, len);
|
ok = writeBytesAndCheck(src, len);
|
||||||
if (!ok) {debugMod(NAME, "failed to write register contents \n"); return false;}
|
if (!ok) {debugMod(NAME, "failed to write register contents"); return false;}
|
||||||
|
|
||||||
// done
|
// done
|
||||||
stop();
|
stop();
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#pragma GCC push_options
|
#pragma GCC push_options
|
||||||
#pragma GCC optimize ("O3")
|
#pragma GCC optimize ("O2")
|
||||||
|
|
||||||
|
|
||||||
template <int PIN_MISO, int PIN_MOSI, int PIN_CLK, bool fast> class SoftSPI {
|
template <int PIN_MISO, int PIN_MOSI, int PIN_CLK, bool fast> class SoftSPI {
|
||||||
|
|||||||
Reference in New Issue
Block a user