Skip to content

Commit

Permalink
Rename LCD -> I2C
Browse files Browse the repository at this point in the history
  • Loading branch information
keirf committed Oct 8, 2019
1 parent 9a9bc53 commit d91fbf9
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 97 deletions.
8 changes: 4 additions & 4 deletions inc/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,10 @@ struct display {
};

/* LCD / FF-OSD I2C Protocol. */
void lcd_init(void);
void lcd_process(void);
extern struct display lcd_display;
extern bool_t ff_osd_i2c_protocol;
void i2c_init(void);
void i2c_process(void);
extern struct display i2c_display;
extern bool_t i2c_osd_protocol;
extern uint8_t i2c_buttons_rx; /* Gotek -> FF_OSD */
extern struct __packed i2c_osd_info {
uint8_t protocol_ver;
Expand Down
2 changes: 1 addition & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ OBJS += build_info.o
OBJS += cancellation.o
OBJS += config.o
OBJS += console.o
OBJS += lcd.o
OBJS += i2c.o
OBJS += main.o
OBJS += string.o
OBJS += stm32f10x.o
Expand Down
6 changes: 3 additions & 3 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ static void config_write_flash(struct config *conf)

static void lcd_display_update(void)
{
lcd_display.rows = config.rows;
lcd_display.cols = config.min_cols;
i2c_display.rows = config.rows;
i2c_display.cols = config.min_cols;
}

void config_init(void)
Expand Down Expand Up @@ -179,7 +179,7 @@ void config_process(uint8_t b)
config_printk(&config);
lcd_display_update();
}
if ((config_state == C_rows) && ff_osd_i2c_protocol) {
if ((config_state == C_rows) && i2c_osd_protocol) {
/* Skip LCD config options if using the extended OSD protocol. */
config_state = C_save;
}
Expand Down
170 changes: 91 additions & 79 deletions src/lcd.c → src/i2c.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
/*
* lcd.c
* i2c.c
*
* 1. HD44780 LCD controller via a PCF8574 I2C backpack.
* I2C communications to the host:
* 1. Emulate HD44780 LCD controller via a PCF8574 I2C backpack.
* 2. Support extended custom protocol with bidirectional comms.
*
* Written & released by Keir Fraser <[email protected]>
*
Expand Down Expand Up @@ -44,11 +46,17 @@ static uint16_t d_cons, d_prod;
static uint16_t t_ring[8];
static uint16_t t_cons, t_prod;

/* Display state, exported to display routines. */
struct display i2c_display;

/* LCD state. */
static bool_t lcd_inc;
static uint8_t lcd_ddraddr;
struct display lcd_display;
uint8_t i2c_buttons_rx;
struct i2c_osd_info i2c_osd_info;

/* I2C custom protocol state. */
bool_t i2c_osd_protocol; /* using the custom protocol? */
uint8_t i2c_buttons_rx; /* button state: Gotek -> OSD */
struct i2c_osd_info i2c_osd_info; /* state: OSD -> Gotek */

/* I2C Error ISR: As slave with clock stretch we can only receive:
* Bus error (BERR): Peripheral automatically recovers
Expand Down Expand Up @@ -89,63 +97,6 @@ static void IRQ_i2c_event(void)
}
}

static void process_cmd(uint8_t cmd)
{
uint8_t x = 0x80;
int c = 0;

if (!cmd)
return;

while (!(cmd & x)) {
x >>= 1;
c++;
}

switch (c) {
case 0: /* Set DDR Address */
lcd_ddraddr = cmd & 127;
break;
case 1: /* Set CGR Address */
break;
case 2: /* Function Set */
break;
case 3: /* Cursor or Display Shift */
break;
case 4: /* Display On/Off Control */
break;
case 5: /* Entry Mode Set */
lcd_inc = !!(cmd & 2);
break;
case 6: /* Return Home */
lcd_ddraddr = 0;
break;
case 7: /* Clear Display */
memset(lcd_display.text, ' ', sizeof(lcd_display.text));
lcd_ddraddr = 0;
break;
}
}

static void process_dat(uint8_t dat)
{
int x, y;
if (lcd_ddraddr >= 0x68)
lcd_ddraddr = 0x00; /* jump to line 2 */
if ((lcd_ddraddr >= 0x28) && (lcd_ddraddr < 0x40))
lcd_ddraddr = 0x40; /* jump to line 1 */
x = lcd_ddraddr & 0x3f;
y = lcd_ddraddr >> 6;
if ((lcd_display.rows == 4) && (x >= 20)) {
x -= 20;
y += 2;
}
lcd_display.text[y][x] = dat;
lcd_ddraddr++;
if (x >= lcd_display.cols)
lcd_display.cols = min_t(unsigned int, x+1, config.max_cols);
}

/* FF OSD command set */
#define OSD_BACKLIGHT 0x00 /* [0] = backlight on */
#define OSD_DATA 0x02 /* next columns*rows bytes are text data */
Expand Down Expand Up @@ -186,36 +137,36 @@ static void ff_osd_process(void)
}
if (ff_osd_y != 0) {
/* Character Data. */
lcd_display.text[ff_osd_y-1][ff_osd_x] = x;
if (++ff_osd_x >= lcd_display.cols) {
i2c_display.text[ff_osd_y-1][ff_osd_x] = x;
if (++ff_osd_x >= i2c_display.cols) {
ff_osd_x = 0;
if (++ff_osd_y > lcd_display.rows)
if (++ff_osd_y > i2c_display.rows)
ff_osd_y = 0;
}
} else {
/* Command. */
if ((x & 0xc0) == OSD_COLUMNS) {
/* 0-40 */
lcd_display.cols = min_t(uint16_t, 40, x & 0x3f);
i2c_display.cols = min_t(uint16_t, 40, x & 0x3f);
} else {
switch (x & 0xf0) {
case OSD_BUTTONS:
i2c_buttons_rx = x & 0x0f;
break;
case OSD_ROWS:
/* 0-3 */
lcd_display.rows = x & 0x03;
i2c_display.rows = x & 0x03;
break;
case OSD_HEIGHTS:
lcd_display.heights = x & 0x0f;
i2c_display.heights = x & 0x0f;
break;
case OSD_BACKLIGHT:
switch (x & 0x0f) {
case 0:
lcd_display.on = FALSE;
i2c_display.on = FALSE;
break;
case 1:
lcd_display.on = TRUE;
i2c_display.on = TRUE;
break;
case 2:
ff_osd_x = 0;
Expand All @@ -231,21 +182,75 @@ static void ff_osd_process(void)
t_cons = t_c;
}

void lcd_process(void)
static void lcd_process_cmd(uint8_t cmd)
{
uint8_t x = 0x80;
int c = 0;

if (!cmd)
return;

while (!(cmd & x)) {
x >>= 1;
c++;
}

switch (c) {
case 0: /* Set DDR Address */
lcd_ddraddr = cmd & 127;
break;
case 1: /* Set CGR Address */
break;
case 2: /* Function Set */
break;
case 3: /* Cursor or Display Shift */
break;
case 4: /* Display On/Off Control */
break;
case 5: /* Entry Mode Set */
lcd_inc = !!(cmd & 2);
break;
case 6: /* Return Home */
lcd_ddraddr = 0;
break;
case 7: /* Clear Display */
memset(i2c_display.text, ' ', sizeof(i2c_display.text));
lcd_ddraddr = 0;
break;
}
}

static void lcd_process_dat(uint8_t dat)
{
int x, y;
if (lcd_ddraddr >= 0x68)
lcd_ddraddr = 0x00; /* jump to line 2 */
if ((lcd_ddraddr >= 0x28) && (lcd_ddraddr < 0x40))
lcd_ddraddr = 0x40; /* jump to line 1 */
x = lcd_ddraddr & 0x3f;
y = lcd_ddraddr >> 6;
if ((i2c_display.rows == 4) && (x >= 20)) {
x -= 20;
y += 2;
}
i2c_display.text[y][x] = dat;
lcd_ddraddr++;
if (x >= i2c_display.cols)
i2c_display.cols = min_t(unsigned int, x+1, config.max_cols);
}

static void lcd_process(void)
{
uint16_t d_c, d_p = d_prod;
static uint16_t dat = 1;
static bool_t rs;

if (ff_osd_i2c_protocol)
return ff_osd_process();

/* Process the command sequence. */
for (d_c = d_cons; d_c != d_p; d_c++) {
uint8_t x = d_ring[MASK(d_ring, d_c)];
if ((x & (_EN|_RW)) != _EN)
continue;
lcd_display.on = !!(x & _BL);
i2c_display.on = !!(x & _BL);
if (rs != !!(x & _RS)) {
rs ^= 1;
dat = 1;
Expand All @@ -254,20 +259,27 @@ void lcd_process(void)
dat |= x >> 4;
if (dat & 0x100) {
if (rs)
process_dat(dat);
lcd_process_dat(dat);
else
process_cmd(dat);
lcd_process_cmd(dat);
dat = 1;
}
}

d_cons = d_c;
}

void lcd_init(void)
void i2c_process(void)
{
return i2c_osd_protocol ? ff_osd_process() : lcd_process();
}

void i2c_init(void)
{
char *p;

i2c_osd_protocol = gpio_pins_connected(gpioa, 0, gpioa, 1);

i2c_osd_info.protocol_ver = 0;
i2c_osd_info.fw_major = strtol(fw_ver, &p, 10);
i2c_osd_info.fw_minor = strtol(p+1, NULL, 10);
Expand All @@ -289,7 +301,7 @@ void lcd_init(void)

/* Initialise I2C. */
i2c->cr1 = 0;
i2c->oar1 = (ff_osd_i2c_protocol ? 0x10 : 0x27) << 1;
i2c->oar1 = (i2c_osd_protocol ? 0x10 : 0x27) << 1;
i2c->cr2 = (I2C_CR2_FREQ(36) |
I2C_CR2_ITERREN |
I2C_CR2_ITEVTEN |
Expand Down
15 changes: 5 additions & 10 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,6 @@ const static uint8_t irqs[] = {

int EXC_reset(void) __attribute__((alias("main")));

/* Are we using the FF OSD custom I2C protocol? */
bool_t ff_osd_i2c_protocol;

#include "font.h"

/* Guard the stacks with known values. */
Expand Down Expand Up @@ -166,7 +163,7 @@ static void button_timer_fn(void *unused)
uint8_t b = B_PROCESSED;

/* Rotary Encoder is not supported with FF OSD custom I2C protocol. */
if (!ff_osd_i2c_protocol)
if (!i2c_osd_protocol)
b |= get_buttons();

/* Latch final button state and reset the timer. */
Expand All @@ -181,7 +178,7 @@ static int hline, frame;

#define MAX_DISPLAY_HEIGHT 52
static uint16_t display_dat[MAX_DISPLAY_HEIGHT][40/2+1];
static struct display *cur_display = &lcd_display;
static struct display *cur_display = &i2c_display;
static uint16_t display_height;

static void slave_arr_update(void)
Expand Down Expand Up @@ -549,9 +546,7 @@ int main(void)
stm32_init();
time_init();
console_init();

ff_osd_i2c_protocol = gpio_pins_connected(gpioa, 0, gpioa, 1);
lcd_init();
i2c_init();

/* PC13: Blue Pill Indicator LED (Active Low) */
gpio_configure_pin(gpioc, 13, GPI_pull_up);
Expand Down Expand Up @@ -744,7 +739,7 @@ int main(void)

/* Work out what to display next frame. */
cur_display = config_active ? &config_display
: osd_on ? &lcd_display : &no_display;
: osd_on ? &i2c_display : &no_display;
if (notify.on) {
if (time_diff(notify_time, time_now()) > time_ms(2000)) {
notify.on = FALSE;
Expand Down Expand Up @@ -804,7 +799,7 @@ int main(void)
config_process(b & ~B_PROCESSED);
}

lcd_process();
i2c_process();
}

return 0;
Expand Down

0 comments on commit d91fbf9

Please sign in to comment.