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>
This commit is contained in:
Kevin O'Connor 2018-06-22 22:07:48 -04:00
parent 74de181e59
commit f08a0c5e93
4 changed files with 33 additions and 22 deletions

View File

@ -539,10 +539,6 @@
#sid_pin: #sid_pin:
# The pins connected to an st7920 type lcd. These parameters must be # The pins connected to an st7920 type lcd. These parameters must be
# provided when using an st7920 display. # 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 # Custom thermistors (one may define any number of sections with a

View File

@ -93,8 +93,3 @@ max_z_accel: 100
#cs_pin: P0.16 #cs_pin: P0.16
#sclk_pin: P0.15 #sclk_pin: P0.15
#sid_pin: P0.18 #sid_pin: P0.18
#chip_delay needs to be set to the below for the LCD to initialise correctly.
#chip_delay: .000040

View File

@ -161,7 +161,9 @@ HD44780_chars = [
# ST7920 (128x64 graphics) lcd chip # 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: class ST7920:
char_right_arrow = '\x1a' char_right_arrow = '\x1a'
@ -182,7 +184,6 @@ class ST7920:
self.mcu = mcu self.mcu = mcu
self.oid = self.mcu.create_oid() self.oid = self.mcu.create_oid()
self.mcu.add_config_object(self) 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.send_data_cmd = self.send_cmds_cmd = None
self.is_extended = False self.is_extended = False
# framebuffers # framebuffers
@ -195,9 +196,10 @@ class ST7920:
def build_config(self): def build_config(self):
self.mcu.add_config_cmd( self.mcu.add_config_cmd(
"config_st7920 oid=%u cs_pin=%s sclk_pin=%s sid_pin=%s" "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.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() cmd_queue = self.mcu.alloc_command_queue()
self.send_cmds_cmd = self.mcu.lookup_command( self.send_cmds_cmd = self.mcu.lookup_command(
"st7920_send_cmds oid=%c cmds=%*s", cq=cmd_queue) "st7920_send_cmds oid=%c cmds=%*s", cq=cmd_queue)

View File

@ -12,7 +12,7 @@
#include "sched.h" // DECL_SHUTDOWN #include "sched.h" // DECL_SHUTDOWN
struct st7920 { 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; struct gpio_out sclk, sid;
}; };
@ -45,16 +45,31 @@ st7920_xmit_byte(struct st7920 *s, uint8_t data)
static void static void
st7920_xmit(struct st7920 *s, uint8_t count, uint8_t *cmds) 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; if (!count)
while (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++; uint8_t cmd = *cmds++;
st7920_xmit_byte(s, cmd & 0xf0); st7920_xmit_byte(s, cmd & 0xf0);
// Can't complete transfer until delay complete while (timer_read_time() - last_cmd_time < wait_ticks)
while (timer_read_time() - last_cmd_time < cmd_wait_ticks) // Can't complete transfer until delay complete
irq_poll(); irq_poll();
st7920_xmit_byte(s, cmd << 4); st7920_xmit_byte(s, cmd << 4);
last_cmd_time = timer_read_time(); last_cmd_time = timer_read_time();
} }
s->last_cmd_time = last_cmd_time; s->last_cmd_time = last_cmd_time;
} }
@ -80,13 +95,16 @@ command_config_st7920(uint32_t *args)
uint32_t end = timer_read_time(); uint32_t end = timer_read_time();
irq_enable(); irq_enable();
s->last_cmd_time = end; s->last_cmd_time = end;
uint32_t diff = end - start, delay_ticks = args[4]; uint32_t diff = end - start, sync_delay_ticks = args[4];
if (delay_ticks > diff) if (sync_delay_ticks > diff)
s->cmd_wait_ticks = 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, DECL_COMMAND(command_config_st7920,
"config_st7920 oid=%c cs_pin=%u sclk_pin=%u sid_pin=%u" "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 void
command_st7920_send_cmds(uint32_t *args) command_st7920_send_cmds(uint32_t *args)