Multitasking: Programming the OBLCD

Note: If you are using a controller with dialect 16 or later you can ignore this section. Such controllers have a fully buffered LCD driver, which eliminates the timing concerns addressed here.

It is important in multitasking programs never to hold up the processor for any amount of time. That may be a consideration with the Onboard LCD (OBLCD). It takes a certain amount of time to send stuff out to the OBLCD. See OBLCD: Timing considerations for details.

In many programs a few milliseconds delay, while the LCD is being updated, won't matter. For example, if you are writing a menu system for a device that cannot be operating while it is also being configured, then there is no problem. If on the other hand you have a time-critical controller with constant LCD updates, then you must take care. An example of this would be counting pulses from an encoder and updating the display in real time.

There are two OBLCD instructions designed for this situation: OBLCD_GoIfBusy and OBLCD_GoIfIdle.

The following code shows these being used in a task that constantly updates the OBLCD with the value in RAM location Count for as long as semaphore ShowCount is true (assume some other code controls ShowCount).

DC_Update:
         Resume         DC_Address
DC_0:
         Suspend
         RetIfSF        ShowCount
DC_1:
         Suspend        DC_Address
         OBLCD_GoIfBusy DC_1          ;Wait for OBLCD to be free
         OBLCD_ SetCur  1,5           ;Position cursor
DC_2:
         Suspend        DC_Address
         OBLCD_GoIfBusy DC_2          ;Wait for OBLCD to be free
         OBLCD_UDecDispMFW Count      ;Display count

         GoTo           DC_0

Some notes on this code:

  1. There is no initialization entry point. I am relying on the fact that a non-initialized resume address defaults to falling through (in this case to DC_0).
  2. I used a RetIfSF rather that a GoIfSF at DC_0. By doing a Return the suspend address is unchanged, so next time around it will come back to DC_0 again.
  3. If I didn't use Suspend/Resume in this function, and it was called very frequently, it would be almost guaranteed to consume about 6mS every time. That could slow down a critical program considerably.
  4. It generally turns out to be the most economical of code if you place a Suspend at each line that is the target of a GoTo. That means that sometimes the Suspend will seemingly be executed at an inappropriate time, like the one at DC_0 on the very first call. Usually that really doesn't matter.