worked on SPI, fixed some bugs

adjusted LCD code
added code for INA3221
worked on UI
This commit is contained in:
2020-06-24 21:28:44 +02:00
parent 6dfce7803a
commit ccd7f119d3
11 changed files with 258 additions and 88 deletions

View File

@@ -84,80 +84,88 @@ public:
private:
#define V 128
#define H 160
static constexpr const int V = 128;
static constexpr const int H = 160;
void waitLong() {
for (int i = 0; i < 50; ++i) {
//os_delay_us(10*1000);
vTaskDelay(10 / portTICK_PERIOD_MS);
}
inline void waitLong() {
//vTaskDelay(200 / portTICK_PERIOD_MS);
for (int i = 0; i < 0x1FFFFF; ++i) {asm("nop");} // vTaskDelay seems not to block? maybe when display is allocated outside of a function?
}
void waitShort() {
//os_delay_us(10*1000);
vTaskDelay(10 / portTICK_PERIOD_MS);
inline void waitShort() {
//vTaskDelay(20 / portTICK_PERIOD_MS);
for (int i = 0; i < 0xFFFF; ++i) {asm("nop");}
}
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();
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
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
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
sendData(0x01); sendData(0x2C); sendData(0x2D); // Dot inversion mode
sendData(0x01); sendData(0x2C); sendData(0x2D); // Line inversion mode
waitShort();
sendCommand(ST7735_INVCTR); // 6: Display inversion ctrl) 1 arg) no delay: 0xb4
sendData(0x07); // No inversion
sendCommand(ST7735_PWCTR1); // 7: Power control) 3 args) no delay: 0xc0
sendData(0xA2);
sendData(0x02); // -4.6V
sendData(0x84); // AUTO mode
sendCommand(ST7735_PWCTR2); // 8: Power control) 1 arg) no delay: 0xc1
sendData(0xC5); // VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD
sendCommand(ST7735_PWCTR3); // 9: Power control) 2 args) no delay: 0xc2
sendData(0x0A); // Opamp current small
sendData(0x00); // Boost frequency
sendCommand(ST7735_PWCTR4); // 10: Power control) 2 args) no delay:
sendData(0x8A); // BCLK/2) Opamp current small & Medium low
sendData(0x2A);
sendCommand(ST7735_PWCTR5); // 11: Power control) 2 args) no delay:
sendData(0x8A); sendData(0xEE);
sendCommand(ST7735_VMCTR1); // 12: Power control) 1 arg) no delay:
sendData(0x0E);
sendCommand(ST7735_INVOFF); // 13: Don't invert display) no args) no delay 0x20
sendCommand(ST7735_MADCTL); // 14: Memory access control (directions)) 1 arg:
sendData(0xC8); // row addr/col addr); bottom to top refresh
waitShort();
sendCommand(ST7735_COLMOD); // 15: set color mode); 1 arg); no delay:
sendData(0x05); // 16-bit color
deselect();
// required??? adjusts colors or something???
if (1 == 1) {
// required???
if (1 == 1) {
select();
sendCommand(ST7735_GMCTRP1); // 1: Magical unicorn dust, 16 args, no delay:
sendData(0x02); sendData(0x1c); sendData(0x07); sendData(0x12);
sendData(0x37); sendData(0x32); sendData(0x29); sendData(0x2d);
@@ -169,17 +177,20 @@ private:
sendData(0x2E); sendData(0x2C); sendData(0x29); sendData(0x2D);
sendData(0x2E); sendData(0x2E); sendData(0x37); sendData(0x3F);
sendData(0x00); sendData(0x00); sendData(0x02); sendData(0x10);
deselect();
}
}
select();
sendCommand(ST7735_NORON); // 3: Normal display on, no args
waitShort();
sendCommand(ST7735_DISPON); // 4: Main screen turn on, no args
waitLong();
deselect();
waitLong();
select();
sendCommand(ST7735_DISPON); // 4: Main screen turn on, no args
deselect();
waitLong();
debugMod(NAME, "init() done");
}
@@ -223,21 +234,22 @@ public:
select();
sendCommand(ST7735_CASET); // Column addr set
sendCommand(ST7735_CASET); // Column addr set
sendData(0x00);
sendData(0); // XSTART
sendData(0); // XSTART
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(0); // YSTART
sendData(0); // YSTART
sendData(0x00);
sendData(H-1); // YEND
sendData(H-1); // YEND
sendCommand(ST7735_RAMWR);
modeData();
/*
for (int i = 0; i < (V*H); ++i) {
const uint16_t color = data[i];
//const uint8_t lo = color & 0xFF;
@@ -246,7 +258,9 @@ public:
//sendData(hi);
//spi::writeWord(color);
spi.writeWord(color);
}
}*/
spi.write((const uint8_t*)data, V*H*sizeof(uint16_t));
deselect();
@@ -258,43 +272,31 @@ private:
void sendData(uint8_t data) {
modeData();
//select();
//spi::writeByte(data);
spi.writeByte(data);
//deselect();
}
void sendCommand(uint8_t cmd) {
modeCommand();
//select();
//spi::writeByte(cmd);
spi.writeByte(cmd);
//deselect();
}
/** switch D/C line low */
inline void modeCommand() {
//GPIO5_OUTPUT_SET;
//GPIO5_L;
MyGPIO::clear(PIN_DATA_COMMAND);
}
/** switch D/C line high */
inline void modeData() {
//GPIO5_OUTPUT_SET;
//GPIO5_H;
MyGPIO::set(PIN_DATA_COMMAND);
}
/** set CS = low */
inline void select() {
MyGPIO::clear(PIN_CS);
//spi::chipSelect();
}
/** set CS = high */
inline void deselect() {
//spi::chipDeselect();
MyGPIO::set(PIN_CS);
}

View File

@@ -44,15 +44,16 @@ class UI {
UIPainter p;
UIElement root;
UIElement* eFocused = nullptr;
int focusIdx = 0;
//UIElement* eFocused = nullptr;
UIElement* eDown = nullptr;
Color cBackground = Color::fromRGB(180,240,180);
public:
UI() {
root.setRect(0,0,240,320);
UI(int w, int h) {
root.setRect(0,0,w,h);
root.setVisible(true);
p.setFG(cBackground);
p.fillRect(root.getRect());
@@ -77,7 +78,6 @@ public:
}
}
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() {
//debugMod1("UI", "draw %zu elements", elements.size());
// for (UIElement* e : elements) {
// e->_draw(p);
// }
//p.setFG(cBackground);
//p.fillRect(root.getRect());
root._draw(p);
}
};

View File

@@ -23,6 +23,9 @@ private:
const Color fillNormal = Color::fromRGB(180,180,180);
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 frameDark = Color::fromRGB(50,50,50);
@@ -58,7 +61,11 @@ public:
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.setFG( down ? frameDark : frameBright );

View File

@@ -15,13 +15,20 @@ protected:
UIRect rect;
bool _visible = true;
bool _needsRedraw = true;
bool opaque = true;
bool focus = false;
std::vector<UIElement*> children;
static constexpr const char* TAG = "UIElement";
public:
void setOpaque(bool opaque) {
this->opaque = opaque;
}
void setRect(const UIRect r) {
this->rect = r;
setNeedsRedraw();
@@ -44,6 +51,11 @@ public:
return this->_visible;
}
void setFocus(bool focus) {
this->focus = focus;
setNeedsRedraw();
}
void setNeedsRedraw() {
this->_needsRedraw = true;
}
@@ -99,7 +111,7 @@ protected:
void _draw(UIPainter& p) {
// if hidde, ignore for me and children
// if hiden, ignore for me and children
if (!_visible) {return;}
// draw myself (if needed)

View File

@@ -11,7 +11,7 @@
class UILabel : public UIElement {
std::string txt;
Color cBackground = Color::fromRGB(255,255,255);
Color cText = Color::fromRGB(0,0,0);
@@ -21,18 +21,21 @@ public:
;
}
/** set the text to draw */
void setText(const std::string& txt) {
this->txt = txt;
setNeedsRedraw();
}
void draw(UIPainter& p) {
/** draw the label */
void draw(UIPainter& p) override {
p.setFG(cBackground);
p.fillRect(rect);
//const uint16_t txtW = fnt_f1.getWidth(txt);
//const uint16_t txtH = fnt_f1.getHeight();
if (opaque) {
p.setFG(cBackground);
p.fillRect(rect);
}
p.setFG(cText);
p.drawText(rect.x, rect.y, txt.c_str());

View File

@@ -380,9 +380,11 @@ private:
/** check the chip's version */
void check() {
idle();
uint8_t version = readRegister(REG_VERSION);
debugMod1(NAME, "version %d", version);
if (version != 0x12) {debugMod(NAME, "!! unsupported chip version detected");}
sleep();
}
/** what exactly is this? */

89
ext/sens/INA3221.h Normal file
View 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