we're getttng C to work
C deez nuts
This commit is contained in:
133
src/lcd.c
Normal file
133
src/lcd.c
Normal file
@@ -0,0 +1,133 @@
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include "log.h"
|
||||
#include "lcd.h"
|
||||
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
int lcd_open(struct lcd_t* lcd, const bool reopen) {
|
||||
applog(LOG_INF, "Opening serial port at %s", lcd->port);
|
||||
if (lcd->fd <= 0 || reopen)
|
||||
lcd->fd = open(lcd->port, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||
if (lcd->fd <= 0) {
|
||||
applog(LOG_ERR, "Error opening serial port %s", lcd->port); // err
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lcd_close(struct lcd_t* lcd) {
|
||||
if (lcd->fd >= 0) {
|
||||
close(lcd->fd);
|
||||
applog(LOG_INF, "LCD port closed");
|
||||
}
|
||||
lcd->fd = -1;
|
||||
}
|
||||
|
||||
void lcd_write(struct lcd_t* lcd, const uint8_t* cmdbuf, const uint8_t len) {
|
||||
if (!write(lcd->fd, cmdbuf, len)) {
|
||||
applog(LOG_ERR, "failed to execute write(), lost access to port?");
|
||||
lcd_open(lcd, true);
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_clear(struct lcd_t* lcd) {
|
||||
constexpr uint8_t cmdbuf[] = {254, 88};
|
||||
lcd_write(lcd, cmdbuf, sizeof(cmdbuf));
|
||||
}
|
||||
|
||||
void lcd_set_contrast(struct lcd_t* lcd, const uint8_t contrast) {
|
||||
applog(LOG_INF, "Set contrast to %d", contrast);
|
||||
const uint8_t cmdbuf[] = {254, 80, contrast};
|
||||
lcd_write(lcd, cmdbuf, sizeof(cmdbuf));
|
||||
}
|
||||
|
||||
void lcd_set_backlight(struct lcd_t* lcd, const bool enabled) {
|
||||
applog(LOG_INF, "Set backlight to %s", enabled ? "true" : "false");
|
||||
const uint8_t cmdbuf[] = {254, (enabled ? 66 : 70), 255};
|
||||
lcd_write(lcd, cmdbuf, enabled ? 3 : 2);
|
||||
}
|
||||
|
||||
void lcd_set_cursor(struct lcd_t* lcd, const uint8_t row, const uint8_t col) {
|
||||
const uint8_t cmdbuf[] = {254, 71, (col + 1), (row + 1)};
|
||||
lcd_write(lcd, cmdbuf, sizeof(cmdbuf));
|
||||
}
|
||||
|
||||
/* reconsider so im not writing every time. prepend custom chars to the write buffer? */
|
||||
void lcd_set_custom_char(struct lcd_t* lcd, const uint8_t index, const lcd_glyph_t* glyph) {
|
||||
uint8_t cmdbuf[] = {254, 78, index, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
memcpy(&cmdbuf[3], &glyph, sizeof(glyph));
|
||||
lcd_write(lcd, cmdbuf, sizeof(cmdbuf));
|
||||
}
|
||||
|
||||
/* immediately writes string to the lcd at current cursor pos */
|
||||
void lcd_write_str(struct lcd_t* lcd, const char* str, const uint8_t len) {
|
||||
lcd_write(lcd, (const uint8_t*)str, len);
|
||||
}
|
||||
|
||||
void lcd_write_str_pos(struct lcd_t* lcd, const char* str, const uint8_t len, const uint8_t posX, const uint8_t posY) {
|
||||
lcd_set_cursor(lcd, posX, posY);
|
||||
lcd_write(lcd, (const uint8_t*)str, len);
|
||||
}
|
||||
|
||||
/* writes string to write buffer at calculated pos, we trust it to be null terminated */
|
||||
void lcd_write_buf(struct lcd_t* lcd, const uint8_t row, const uint8_t col, const char* str) {
|
||||
size_t len = 0;
|
||||
while (str[len] != '\0')
|
||||
len++;
|
||||
|
||||
len = MIN(len, sizeof(lcd->writebuf) - col);
|
||||
uint8_t pos = 4 + col + (LCD_COLS * (row % 2)); // skip 4 bytes to leave room for set cursor command
|
||||
if (row >= 2) pos += 2 * LCD_COLS + 4; // if we're writing to disp2, skip another 4 bytes for set cursor command and 2*40 bytes of disp 1
|
||||
memcpy(&lcd->writebuf[pos], str, len);
|
||||
}
|
||||
|
||||
|
||||
void lcd_clear_buf(struct lcd_t* lcd) {
|
||||
memset(lcd->writebuf, ' ', sizeof(lcd->writebuf));
|
||||
}
|
||||
|
||||
/* flushes writebuffer to lcd, hyperoptmized, flushes buffer and commands in a single write operation */
|
||||
void lcd_flush_buf(struct lcd_t* lcd) {
|
||||
constexpr uint8_t set_disp[] = {254, 71, 1, 1}; // set cursor to char 1, line 1
|
||||
memcpy(&lcd->writebuf[0], set_disp, 4);
|
||||
memcpy(&lcd->writebuf[2 * LCD_COLS + 4], set_disp, 4);
|
||||
lcd->writebuf[2 * LCD_COLS + 7] = 3; // overwrite set cursor c1 l1 to c1 l3
|
||||
lcd_write(lcd, (const uint8_t*)lcd->writebuf, sizeof(lcd->writebuf));
|
||||
}
|
||||
|
||||
// i have a whole flushbuf func to avoid too many writes, but im writing on every bar, need to rethink this.
|
||||
// we could have a separate pre-char buffer and put all the setCustomChar commands to that?
|
||||
char lcd_bar(struct lcd_t* lcd, const uint8_t char_id, const double value) {
|
||||
uint8_t b[8];
|
||||
memset(b, 0b01110, sizeof(b));
|
||||
for (uint8_t i = 0; i < (1.0 - value) * 8; i++)
|
||||
b[i] = 0;
|
||||
lcd_set_custom_char(lcd, char_id, &b);
|
||||
return cc(char_id);
|
||||
}
|
||||
|
||||
int lcd_init(struct lcd_t* lcd) {
|
||||
const int ret = lcd_open(lcd, false);
|
||||
if (ret < 0) {
|
||||
lcd_close(lcd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
applog(LOG_INF, "ret %d, fd %d", ret, lcd->fd);
|
||||
|
||||
struct termios term = {};
|
||||
term.c_cflag = lcd->baud | CS8 | CLOCAL | CREAD;
|
||||
|
||||
tcflush(lcd->fd, TCIFLUSH);
|
||||
tcsetattr(lcd->fd, TCSANOW, &term);
|
||||
|
||||
lcd_clear_buf(lcd);
|
||||
constexpr uint8_t cmdbuf[] = {254, 75, 254, 84};
|
||||
lcd_write(lcd, cmdbuf, sizeof(cmdbuf));
|
||||
|
||||
lcd_clear(lcd);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user