aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2018-06-22 22:07:48 -0400
committerKevin O'Connor <kevin@koconnor.net>2018-06-22 23:47:09 -0400
commitf08a0c5e93b92a6efa72d16a3d53968f3e54bf1c (patch)
treeef562213a7898d4c0dcc95c5fb0718c4f20769d9
parent74de181e59fcc6f2d8d86190e73a1382810add8b (diff)
downloadkutter-f08a0c5e93b92a6efa72d16a3d53968f3e54bf1c.tar.gz
kutter-f08a0c5e93b92a6efa72d16a3d53968f3e54bf1c.tar.xz
kutter-f08a0c5e93b92a6efa72d16a3d53968f3e54bf1c.zip
lcd_st7920: Use a longer delay at the start of each command/data
It appears the st7920 requires a longer delay when switching from command to data mode (and vice-versa). Slower MCUs don't show a problem because the klipper command processing time results in a sufficient delay. However, some of the faster MCUs can process klipper commands fast enough that the next st7920 transfer is sent too fast. Add an additional delay to account for this. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
-rw-r--r--config/example-extras.cfg4
-rw-r--r--config/generic-re-arm.cfg5
-rw-r--r--klippy/extras/display.py10
-rw-r--r--src/lcd_st7920.c36
4 files changed, 33 insertions, 22 deletions
diff --git a/config/example-extras.cfg b/config/example-extras.cfg
index 1398f992..81231f75 100644
--- a/config/example-extras.cfg
+++ b/config/example-extras.cfg
@@ -539,10 +539,6 @@
#sid_pin:
# The pins connected to an st7920 type lcd. These parameters must be
# provided when using an st7920 display.
-#chip_delay:
-# This parameter specifies the internal command delay (in seconds)
-# on st7920 displays. It may be necessary to increase this if the
-# display shows garbled data. The default is 0.000020.
# Custom thermistors (one may define any number of sections with a
diff --git a/config/generic-re-arm.cfg b/config/generic-re-arm.cfg
index 4a9c9fab..13a2c792 100644
--- a/config/generic-re-arm.cfg
+++ b/config/generic-re-arm.cfg
@@ -93,8 +93,3 @@ max_z_accel: 100
#cs_pin: P0.16
#sclk_pin: P0.15
#sid_pin: P0.18
-#chip_delay needs to be set to the below for the LCD to initialise correctly.
-#chip_delay: .000040
-
-
-
diff --git a/klippy/extras/display.py b/klippy/extras/display.py
index e68c3db7..00a4777d 100644
--- a/klippy/extras/display.py
+++ b/klippy/extras/display.py
@@ -161,7 +161,9 @@ HD44780_chars = [
# ST7920 (128x64 graphics) lcd chip
######################################################################
-ST7920_DELAY = .000020 # Spec says 72us, but faster is possible in practice
+# Spec says 72us, but faster is possible in practice
+ST7920_CMD_DELAY = .000020
+ST7920_SYNC_DELAY = .000045
class ST7920:
char_right_arrow = '\x1a'
@@ -182,7 +184,6 @@ class ST7920:
self.mcu = mcu
self.oid = self.mcu.create_oid()
self.mcu.add_config_object(self)
- self.chip_delay = config.getfloat('chip_delay', ST7920_DELAY, minval=0.)
self.send_data_cmd = self.send_cmds_cmd = None
self.is_extended = False
# framebuffers
@@ -195,9 +196,10 @@ class ST7920:
def build_config(self):
self.mcu.add_config_cmd(
"config_st7920 oid=%u cs_pin=%s sclk_pin=%s sid_pin=%s"
- " delay_ticks=%d" % (
+ " sync_delay_ticks=%d cmd_delay_ticks=%d" % (
self.oid, self.pins[0], self.pins[1], self.pins[2],
- self.mcu.seconds_to_clock(self.chip_delay)))
+ self.mcu.seconds_to_clock(ST7920_SYNC_DELAY),
+ self.mcu.seconds_to_clock(ST7920_CMD_DELAY)))
cmd_queue = self.mcu.alloc_command_queue()
self.send_cmds_cmd = self.mcu.lookup_command(
"st7920_send_cmds oid=%c cmds=%*s", cq=cmd_queue)
diff --git a/src/lcd_st7920.c b/src/lcd_st7920.c
index 4351d6ac..8cd76c50 100644
--- a/src/lcd_st7920.c
+++ b/src/lcd_st7920.c
@@ -12,7 +12,7 @@
#include "sched.h" // DECL_SHUTDOWN
struct st7920 {
- uint32_t last_cmd_time, cmd_wait_ticks;
+ uint32_t last_cmd_time, sync_wait_ticks, cmd_wait_ticks;
struct gpio_out sclk, sid;
};
@@ -45,16 +45,31 @@ st7920_xmit_byte(struct st7920 *s, uint8_t data)
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--) {
+ if (!count)
+ return;
+
+ // Send first byte (with longer delay)
+ uint32_t last_cmd_time = s->last_cmd_time, wait_ticks = s->sync_wait_ticks;
+ uint8_t cmd = *cmds++;
+ st7920_xmit_byte(s, cmd & 0xf0);
+ while (timer_read_time() - last_cmd_time < wait_ticks)
+ // Can't complete transfer until delay complete
+ irq_poll();
+ st7920_xmit_byte(s, cmd << 4);
+ last_cmd_time = timer_read_time();
+
+ // Send subsequent bytes
+ 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)
+ while (timer_read_time() - last_cmd_time < wait_ticks)
+ // Can't complete transfer until delay complete
irq_poll();
st7920_xmit_byte(s, cmd << 4);
last_cmd_time = timer_read_time();
}
+
s->last_cmd_time = last_cmd_time;
}
@@ -80,13 +95,16 @@ command_config_st7920(uint32_t *args)
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;
+ uint32_t diff = end - start, sync_delay_ticks = args[4];
+ if (sync_delay_ticks > diff)
+ s->sync_wait_ticks = sync_delay_ticks - diff;
+ uint32_t cmd_delay_ticks = args[5];
+ if (cmd_delay_ticks > diff)
+ s->cmd_wait_ticks = cmd_delay_ticks - diff;
}
DECL_COMMAND(command_config_st7920,
"config_st7920 oid=%c cs_pin=%u sclk_pin=%u sid_pin=%u"
- " delay_ticks=%u");
+ " sync_delay_ticks=%u cmd_delay_ticks=%u");
void
command_st7920_send_cmds(uint32_t *args)