aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Kconfig3
-rw-r--r--src/Makefile1
-rw-r--r--src/avr/Kconfig1
-rw-r--r--src/lcd_st7920.c121
4 files changed, 126 insertions, 0 deletions
diff --git a/src/Kconfig b/src/Kconfig
index c28cec14..564073eb 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -36,6 +36,9 @@ config HAVE_GPIO_SPI
config HAVE_GPIO_HARD_PWM
bool
default n
+config HAVE_USER_INTERFACE
+ bool
+ default n
config NO_UNSTEP_DELAY
# Slow micro-controllers do not require a delay before returning a
diff --git a/src/Makefile b/src/Makefile
index ce626faa..b316bb66 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -5,3 +5,4 @@ src-$(CONFIG_HAVE_GPIO) += gpiocmds.c stepper.c endstop.c
src-$(CONFIG_HAVE_GPIO_ADC) += adccmds.c
src-$(CONFIG_HAVE_GPIO_SPI) += spicmds.c
src-$(CONFIG_HAVE_GPIO_HARD_PWM) += pwmcmds.c
+src-$(CONFIG_HAVE_USER_INTERFACE) += lcd_st7920.c
diff --git a/src/avr/Kconfig b/src/avr/Kconfig
index 9a4500c1..77f002e2 100644
--- a/src/avr/Kconfig
+++ b/src/avr/Kconfig
@@ -9,6 +9,7 @@ config AVR_SELECT
select HAVE_GPIO_ADC
select HAVE_GPIO_SPI
select HAVE_GPIO_HARD_PWM
+ select HAVE_USER_INTERFACE
select NO_UNSTEP_DELAY
config BOARD_DIRECTORY
diff --git a/src/lcd_st7920.c b/src/lcd_st7920.c
new file mode 100644
index 00000000..4351d6ac
--- /dev/null
+++ b/src/lcd_st7920.c
@@ -0,0 +1,121 @@
+// Commands for sending messages to an st7920 lcd driver
+//
+// Copyright (C) 2018 Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU GPLv3 license.
+
+#include "basecmd.h" // oid_alloc
+#include "board/gpio.h" // gpio_out_write
+#include "board/irq.h" // irq_poll
+#include "board/misc.h" // timer_from_us
+#include "command.h" // DECL_COMMAND
+#include "sched.h" // DECL_SHUTDOWN
+
+struct st7920 {
+ uint32_t last_cmd_time, cmd_wait_ticks;
+ struct gpio_out sclk, sid;
+};
+
+
+/****************************************************************
+ * Transmit functions
+ ****************************************************************/
+
+#define SYNC_CMD 0xf8
+#define SYNC_DATA 0xfa
+
+// Write eight bits to the st7920 via the serial interface
+static void
+st7920_xmit_byte(struct st7920 *s, uint8_t data)
+{
+ struct gpio_out sclk = s->sclk, sid = s->sid;
+ uint8_t i;
+ for (i=0; i<8; i++) {
+ if (data & 0x80) {
+ gpio_out_toggle(sid);
+ data = ~data;
+ }
+ gpio_out_toggle(sclk);
+ data <<= 1;
+ gpio_out_toggle(sclk);
+ }
+}
+
+// Transmit a series of command bytes to the chip
+static void
+st7920_xmit(struct st7920 *s, uint8_t count, uint8_t *cmds)
+{
+ uint32_t last_cmd_time=s->last_cmd_time, cmd_wait_ticks=s->cmd_wait_ticks;
+ while (count--) {
+ uint8_t cmd = *cmds++;
+ st7920_xmit_byte(s, cmd & 0xf0);
+ // Can't complete transfer until delay complete
+ while (timer_read_time() - last_cmd_time < cmd_wait_ticks)
+ irq_poll();
+ st7920_xmit_byte(s, cmd << 4);
+ last_cmd_time = timer_read_time();
+ }
+ s->last_cmd_time = last_cmd_time;
+}
+
+
+/****************************************************************
+ * Interface
+ ****************************************************************/
+
+void
+command_config_st7920(uint32_t *args)
+{
+ struct st7920 *s = oid_alloc(args[0], command_config_st7920, sizeof(*s));
+ s->sclk = gpio_out_setup(args[2], 0);
+ s->sid = gpio_out_setup(args[3], 0);
+ gpio_out_setup(args[1], 1);
+
+ // Calibrate cmd_wait_ticks
+ st7920_xmit_byte(s, SYNC_CMD);
+ st7920_xmit_byte(s, 0x20);
+ irq_disable();
+ uint32_t start = timer_read_time();
+ st7920_xmit_byte(s, 0x00);
+ uint32_t end = timer_read_time();
+ irq_enable();
+ s->last_cmd_time = end;
+ uint32_t diff = end - start, delay_ticks = args[4];
+ if (delay_ticks > diff)
+ s->cmd_wait_ticks = delay_ticks - diff;
+}
+DECL_COMMAND(command_config_st7920,
+ "config_st7920 oid=%c cs_pin=%u sclk_pin=%u sid_pin=%u"
+ " delay_ticks=%u");
+
+void
+command_st7920_send_cmds(uint32_t *args)
+{
+ struct st7920 *s = oid_lookup(args[0], command_config_st7920);
+ st7920_xmit_byte(s, SYNC_CMD);
+ uint8_t len = args[1], *cmds = (void*)(size_t)args[2];
+ st7920_xmit(s, len, cmds);
+}
+DECL_COMMAND(command_st7920_send_cmds, "st7920_send_cmds oid=%c cmds=%*s");
+
+void
+command_st7920_send_data(uint32_t *args)
+{
+ struct st7920 *s = oid_lookup(args[0], command_config_st7920);
+ st7920_xmit_byte(s, SYNC_DATA);
+ uint8_t len = args[1], *data = (void*)(size_t)args[2];
+ st7920_xmit(s, len, data);
+}
+DECL_COMMAND(command_st7920_send_data, "st7920_send_data oid=%c data=%*s");
+
+void
+st7920_shutdown(void)
+{
+ uint8_t i;
+ struct st7920 *s;
+ foreach_oid(i, s, command_config_st7920) {
+ gpio_out_write(s->sclk, 0);
+ gpio_out_write(s->sid, 0);
+ }
+}
+DECL_SHUTDOWN(st7920_shutdown);