Go Down

Topic: Display speed. Code written but dissappointed with my efforts (Read 258 times) previous topic - next topic

tasmod

Background.

I'm a licensed radio amateur.  I built a complete short wave transceiver using a Mega and a 16 x 2 lcd display.  In it's present form it works great, tuning well onscreen with the frequency digits etc changing with nothing untoward. All switching working as it should. Great.

Now.  I decided to make it more up to date and use a Mega with a 3.5 inch mcufriend shield. I used Adafruit GFX and Mcufriend kbv libraries for the shield which reported as 4381. All works.

I have spent many hours designing the onscreen code on a spare Mega and the same screen without connecting it to any external controls.  Just doing the layout onscreen took ages to get the co-ordinates right.

I wish however I had tested the simple part first !! That is to say the frequency digit change.

When I finally hooked up a rotary encoder for frequency tuning I was extremely dissappointed to discover the 'draw' rate was so slow it had a completely discernable change screen write.  I had a small frequency rectangle displaying the digits which obviously needed an overwrite each time the digit changed to get a clear display.

I tried code that just only did the frequency part with no other code in the ino. Still the same.  That's when I discovered it wasn't the code as I thought, but the display that couldn't refresh fast enough compared to a simple lcd display !

The pic is of the screen during design. The black line test rectangle around the digits is the area I am refreshing to keep the rewrite speed as tight as possible.  I have tried a simple ino with just the frequency change code and just the digits onscreen. It is still slow.

The point of all this is to ask if there is a better display that can handle this. 

Have I used the wrong libraries?  Is it just not possible, am I asking too much of these simple displays?

Any sensible suggestions would be welcome.

Rob

david_prentice

#1
Sep 14, 2018, 11:35 am Last Edit: Sep 14, 2018, 11:50 am by david_prentice
1.   A Uno shield on a Mega is slower than Uno shield on a Uno.   This is because that data port is on random PORT pins with a Mega.

2.   You are using a FreeFont.    Adafruit_GFX always draws letters in transparent mode.   You see a blink when the background is re-painted.

3.   Either use some intelligence e.g. only redraw the '6' if that digit changes.    Many proportional fonts use a fixed width for digits.   Probably a narrow width for a period.

4.   Or persuade me to implement printing FreeFonts in rubout mode which changes standard GFX behaviour.

5.   I can print letters with background in hardware much faster than the inherited transparent letter drawing.  

David.

Edit.   I do not recognise ID 4381 (0x1135)

tasmod

Thanks for your reply David.

I used the Mega because of my many switching requirements so plenty of pins were necessary.  I will try out the barebones code on an Uno. If push comes to shove I can use MCP23017 which has 16 ports. I need two ports per freq band filters. Bpf and lpf. Plus other function pins etc.

I must admit my coding is functional (sic) rather than elegant.  However I did try out just basic code and no free font.  The picture was during design and was a font tryout, I posted to show the area I was refreshing.

I did think maybe I could code the display digit change based upon the step rate (there are 7 steps). The pic shows the step as 100Hz so only the 100Hz single digit would change with a rollover at 9.  So conditional code would have to be written to care for that. The period actually stays on all the time. Hmm food for thought.
I have a keypad for direct frequency entry for broadcast bands.

Ooo your offer to change to rubout mode sounds very interesting :-)

Displays are a black art to me. I just tinker with Arduino coding for the sheer fun of it and to keep my old brain active.  I have mucho $ black box commercial transceivers but nothing beats achieving the same thing, but by my own efforts.

* The id was a brain mistake typo. It is 9481.

Rob

david_prentice

It looks as if you have FreeFonts for G4NQX, 7.160.000, Rx, CQ, ...
And regular system 7x5 for Adafruit_GFX_Buttons like 40m

You could use System font for 7.160.000 @ X6 but it would look very blocky.

It is a little fiddly to calculate background, paint it, draw the updated 7.130.000 where the '6' has changed to '3'.    But let's face it.   You just write the code once.

I would suggest update_text(x, y, colour, background, new_text, old_text);

The helper function would detect the changed letters.      The pixel dimensions of the old letter.   Where to repaint the background and draw new letter.
A human might even like seeing a single digit change.    They certainly don't like to see all 9 letters blinking when only one changes.

If you posted your code,   someone might even do the helper function for you.

I would take some persuasion to handle rubout text with proportional fonts instead of straight inheritance of the standard Adafruit_GFX class.    I fear a lot of grief if I were to overrule the expected behaviour.
In practice,   it is only numeric values that require updating on the fly.

David.

tasmod

Thank you again David.

Yes just changing the single digit or pair on rollover appears to be how it is handled on the commercial transceiver (who knows.....)

The picture was taken during work in progress and doesn't reflect what I want to achieve.  I'm quite happy with the Gfx font alone if that would do it but it doesn't even with barebones code. Probably due to my limited knowledge of displays..  I did try the 7 segment font which is only numbers and it looked good but obviously the same occurred.

This has me ?

 "The helper function would detect the changed letters. The pixel dimensions of the old letter.  Where to repaint the background and draw new letter."

Is this 'helper' a library function or just the code to change a single digit?

I will copy the barebones code and post it. It's on my programming laptop just now.

Rob

tasmod

Barebones code.  For those reading it just changes display of digits it doesn't do the actual vfo synthesiser coding.

Code: [Select]


#include <Rotary.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>

// The control pins for the TFT LCD
#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0
#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin

MCUFRIEND_kbv tft;

// Assign human-readable names to some common 16-bit color values for TFT:
// Color definitions
#define BLACK       0x0000      /*   0,   0,   0 */
#define LIGHTGREY   0xC618      /* 192, 192, 192 */
#define WHITE       0xFFFF      /* 255, 255, 255 */

#define ENCODER_A       67   // Encoder pin A is A13 on Mega "A**" two digit designations don't work?
#define ENCODER_B       68  // Encoder pin B is A14 on Mega

Rotary r = Rotary(ENCODER_A, ENCODER_B);

volatile uint32_t vfo;
volatile uint32_t radix = 100;  // 100Hz step size
boolean changed_f = 0;  // freq change counter, f contains freq

//########### Frequency save variables ###################
byte ones, tens, hundreds, thousands, tenthousands, hundredthousands, millions ; //Placeholders

void setup() {
  uint16_t g_identifier = 0x9481;  // identify display driver chip for library
  tft.begin(g_identifier);        // setup to use driver
  tft.setRotation(1); // turn lcd sideways
  tft.fillScreen(LIGHTGREY); // setup blank screen
  tft.fillRoundRect(13, 35, 452, 80, 14, WHITE);     // freq box outline - freq box segment update set in freq display
  tft.fillRoundRect(17, 38, 445, 75, 10, LIGHTGREY); // first frequency box to fill across area


  PCICR |= (1 << PCIE2);           // Enable pin change interrupt for the encoder
  PCMSK2 |= (1 << PCINT21) | (1 << PCINT22); // MEGA interrupt pins mapped to A14 A13
  sei();   // start interrupts

  display_frequency();  // Update the local display at power on
}

/**************************************/
/* Interrupt service routine for      */
/* encoder frequency change           */
/**************************************/

ISR(PCINT2_vect) {
  unsigned char result = r.process();

  if (result == DIR_CW)
    set_frequency(1);
  else if (result == DIR_CCW)
    set_frequency(-1);
}


/**************************************/
/* Change the frequency               */
/* dir = 1    Increment               */
/* dir = -1   Decrement               */
/**************************************/
void set_frequency(short dir)
{
  if (dir == 1)
    vfo += radix;
  if (dir == -1)
    vfo -= radix;
  changed_f = 1;
}

/**************************************/
/* Displays the frequency from f */
/**************************************/
unsigned long F_MIN = 7000000UL;  // just for test
unsigned long F_MAX = 7200000UL ;


void display_frequency()
{
  tft.fillRoundRect(48, 38, 355, 75, 10, LIGHTGREY);   // only refreshes a section of display
  tft.drawRoundRect(70, 38, 320, 75, 10, BLACK); // testing section boundary outline
  tft.setTextSize(5);
  tft.setTextColor(WHITE);

  if (vfo > F_MAX) // Prevents going out of band limits
    vfo = F_MAX;  // Resets frequency if try to tune over/under limit
  if (vfo < F_MIN)
    vfo = F_MIN;

  millions = int(vfo / 1000000);
  hundredthousands = ((vfo / 100000) % 10);
  tenthousands = ((vfo / 10000) % 10);
  thousands = ((vfo / 1000) % 10);
  hundreds = ((vfo / 100) % 10);
  tens = ((vfo / 10) % 10);
  ones = ((vfo / 1) % 10);

  if (millions > 9) {
    tft.setCursor(85, 57); // moves displayed freq if MHz double digit
  }
  else {
    tft.setCursor(110, 57); // or here for single MHz digit
  }
  tft.print(millions);
  tft.print(".");
  tft.print(hundredthousands);
  tft.print(tenthousands);
  tft.print(thousands);
  tft.print(".");
  tft.print(hundreds);
  tft.print(tens);
  tft.print(ones);
}

void loop() {
  // Update the display if the frequency has been changed
  if (changed_f)
  {
    display_frequency();

    changed_f = 0;

  }
}


bodmer

@tasmod

Unfortunately the Adafruit free fonts are very slow to render as they are drawn pixel by pixel.

I had a similar problem and created fast rendering fonts.  The Mega can drive 16 bit displays fast as repeat pixels can be drawn by simply toggling a line, this means that pixels can be rendered at 4 Mpixels/s as shown here.
Formerly Rowboteer (now a broken user profile!)

tasmod

Ok back from working away.

I've written very clunky code that uses GFX font and rewrites to a single digit position with background overlay colour first then the new digit.  This nearly works but the rollover code at 0 cause a slight strobe effect on the upper digits from the one selected.
This may be hardware as I'm using a click detent encoder for testing rather than the optical encoder in the actual unit.

@bodmer

I freely admit I know nothing of displays and fonts bar the bare minimum.  I'm redrawing a rectangle in background colour (28x34 pixels) over the original digit then printing the current digit value.

I only need a numerical font for the frequency part of the display that will update the digits as per your video.  The orange seven segment looks great.  Finding a font of the size I want is even proving difficult.


Go Up