Teensy 3.0 and u8glib

Status
Not open for further replies.

dmf3030

Member
I'm just getting my first teensy 3.0 up and running and while I'm well versed in arduino, im self taught and prob lacking some of the skills I need to diagnose the issues im bumping into moving to the arm libraries.

I'm trying to get the u8glib lcd library up and running on the teensy and I've bumped into this error while trying to compile the basic test example included with the library

U8glib/utility/u8g_delay.c.o: In function `u8g_MicroDelay':
/Users/MEGA/R&D/Arduino/libraries/U8glib/utility/u8g_delay.c:151: undefined reference to `delayMicroseconds'
collect2: error: ld returned 1 exit status


as I understood it there is a delayMicroseconds function which is compatible with teensy 3.0 already, so I wonder if this is an issue with the library re-defining that function or if the two functions clash. Additionally I guess the question is how do I go about tweaking the library to fix said problem. Below is the code in the offending u8g_delay.c file.

Thanks,
Duncan

Code:
/*

  u8g_delay.c

  Universal 8bit Graphics Library
  
  Copyright (c) 2011, olikraus@gmail.com
  All rights reserved.

  Redistribution and use in source and binary forms, with or without modification, 
  are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice, this list 
    of conditions and the following disclaimer.
    
  * Redistributions in binary form must reproduce the above copyright notice, this 
    list of conditions and the following disclaimer in the documentation and/or other 
    materials provided with the distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
  
  
*/


#include "u8g.h"

/*==== Part 1: Derive suitable delay procedure ====*/

#if defined(ARDUINO)
#  if defined(__AVR__)
#    define USE_AVR_DELAY
#  elif defined(__PIC32MX)
#    define USE_PIC32_DELAY
#  elif defined(__arm__)		/* Arduino Due */
#    define USE_ARDUINO_DELAY
#  else
#    define USE_ARDUINO_DELAY
#  endif
#elif defined(__AVR__)
#  define USE_AVR_DELAY
#elif defined(__18CXX)
#  define USE_PIC18_DELAY
#else
#  define USE_DUMMY_DELAY
#endif



/*==== Part 2: Definition of the delay procedures ====*/

/*== AVR Delay ==*/

#if defined(USE_AVR_DELAY)
#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>

/*
  Delay by the provided number of milliseconds.
  Thus, a 16 bit value will allow a delay of 0..65 seconds
  Makes use of the _delay_loop_2
  
  _delay_loop_2 will do a delay of n * 4 prozessor cycles.
  with f = F_CPU cycles per second,
  n = f / (1000 * 4 )
  with f = 16000000 the result is 4000
  with f = 1000000 the result is 250
  
  the millisec loop, gcc requires the following overhead:
  - movev 1
  - subwi 2x2
  - bne i 2
  ==> 7 cycles
  ==> must be devided by 4, rounded up 7/4 = 2
*/
void u8g_Delay(uint16_t val)
{
  /* old version did a call to the arduino lib: delay(val); */
  while( val != 0 )
  {
    _delay_loop_2( (F_CPU / 4000 ) -2);
    val--;
  }
}

/* delay by one micro second */
void u8g_MicroDelay(void)
{
#if (F_CPU / 4000000 ) > 0 
  _delay_loop_2( (F_CPU / 4000000 ) );
#endif
}

/* delay by 10 micro seconds */
void u8g_10MicroDelay(void)
{
#if (F_CPU / 400000 ) > 0 
  _delay_loop_2( (F_CPU / 400000 ) );
#endif
}

#endif 


/*== Delay for PIC18 (not tested) ==*/

#if defined(USE_PIC18_DELAY)
#include <delays.h>
#define GetSystemClock()		(64000000ul)      // Hz
#define GetInstructionClock()	(GetSystemClock()/4)

void u8g_Delay(uint16_t val)
{/*
	unsigned int _iTemp = (val);
	while(_iTemp--)		
		Delay1KTCYx((GetInstructionClock()+999999)/1000000);
		*/
}
void u8g_MicroDelay(void)
{
  /* not implemented */
}
void u8g_10MicroDelay(void)
{
  /* not implemented */
}
#endif


/*== Arduino Delay ==*/
#if defined(USE_ARDUINO_DELAY)
void u8g_Delay(uint16_t val)
{
	delay(val);
}
void u8g_MicroDelay(void)
{
	delayMicroseconds(1);
}
void u8g_10MicroDelay(void)
{
	delayMicroseconds(10);
}
#endif

#if defined(USE_PIC32_DELAY)
/* 
  Assume chipkit here with F_CPU correctly defined
  The problem was, that u8g_Delay() is called within the constructor.
  It seems that the chipkit is not fully setup at this time, so a
  call to delay() will not work. So here is my own implementation.

*/
#define CPU_COUNTS_PER_SECOND (F_CPU/2UL)
#define TICKS_PER_MILLISECOND  (CPU_COUNTS_PER_SECOND/1000UL)
#include "plib.h"
void u8g_Delay(uint16_t val)
{
	uint32_t d;
	uint32_t s;
	d = val;
	d *= TICKS_PER_MILLISECOND;
	s = ReadCoreTimer();
	while ( (uint32_t)(ReadCoreTimer() - s) < d )
		;
} 

void u8g_MicroDelay(void)
{
	uint32_t d;
	uint32_t s;
	d = TICKS_PER_MILLISECOND/1000;
	s = ReadCoreTimer();
	while ( (uint32_t)(ReadCoreTimer() - s) < d )
		;
} 

void u8g_10MicroDelay(void)
{
	uint32_t d;
	uint32_t s;
	d = TICKS_PER_MILLISECOND/100;
	s = ReadCoreTimer();
	while ( (uint32_t)(ReadCoreTimer() - s) < d )
		;
} 

#endif

/*== Any other systems: Dummy Delay ==*/
#if defined(USE_DUMMY_DELAY)
void u8g_Delay(uint16_t val)
{
	/* do not know how to delay... */
}
void u8g_MicroDelay(void)
{
}
void u8g_10MicroDelay(void)
{
}
#endif
 
My first impression is this looks like they're using delayMicroseconds() without including the Arduino.h header which defines it. That's called an implicit function declaration, and it's pretty bad coding form. If you enable verbose message from File > Preferences, you'll probably see a warning about implicit definition of delayMicroseconds.

Try adding #include "Arduino.h", like this:

Code:
/*== Arduino Delay ==*/
#if defined(USE_ARDUINO_DELAY)
#include "Arduino.h"                      //  <--- add this line
void u8g_Delay(uint16_t val)
{
	delay(val);
}
void u8g_MicroDelay(void)
{
	delayMicroseconds(1);
}
void u8g_10MicroDelay(void)
{
	delayMicroseconds(10);
}
#endif

If that makes it work, please contact the library author to see if they'll update their code.

The reason this works on regular Arduino is because their delayMicroseconds is implemented as an ordinary function that happens to match the implicit declaration (the assumption the compiler must make, because it wasn't properly defined).

For Teensy, I implemented delayMicroseconds() as in inline function with assembly language optimization. The result is much more accurate delays, even for 1 microsecond, and usually smaller code size (for a variety of complex reasons I won't go into here).

At least that's my first guess, from the code you posted. If that doesn't work, please post a link to where I can download the entire library and I'll try to take a closer look.
 
You nailed it Paul, made the small change you suggested and the library compiled fine and worked once I set my pins. I'll shoot an email to the u8glib library owner to see if they'll make an official change.

image.jpg
 
Last edited:
Hello.
I bought my first Teensy 3.0 and same lcd screen,and thanks to this forum and U8GLIB i can control this screen.After making changes to u8g_delay.c file,screen works now,but i have
another problem,same screen works lot faster with teensy 2++ then with Teensy 3.0.
I although Teensy 3.0 has 48 Mhz CPU clock and much faster then Teensy 2++.I need fast screen driver.So,maybe you guys can help me with this problem.
Thanks
 
Maybe it's replacing a single cycle AVR port write with emulation code doing 8 single bit writes?

Earlier it seems I found this code, even though there's no links above. But I don't seem to have a copy anymore. Could you please post some links to the library and the places that sell this display?
 
Ok, I ordered one of those Newhaven displays for testing.

I can't promise when I'll be able to work on this library, but it's definitely on my to-do list and the display will hopefully be here in a week or so.
 
I'm still waiting for update. The display is working for me, but it's very slow. I'm using U8GLIB library and the connection is SPI 4 wire.The display(the driver is sSSD1322) is more slower with teensy 3. I wish, somebody will spend time to fegurout the problem.Thanks
 
What speed is your SPI running at? If it's slow, you can't have fast display updates. Are you sure you are using the hardware SPI and not software SPI driven by u8glib?

I'm working with the ARM port of u8glib now (which is very generic) and it is indeed slow, but speed can be improved by making individual modifications for your very own setup.
 
Hello.Thank you for this replay.I will answer you questions soon,i'm new in this thing.
Mean time,let me tell you how is the screen is weird.Im using NHD‐3.12‐25664UCY2,and it's set to 4‐wire SPI mode,by connecting MPU Interface Pin Selections,BS0 and BS1 to ground. I'm using U8GLIB, and the (U8GLIB_NHD31OLED_GR u8g(13, 11, 10, 9) // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9)
is selected.
Thank you
 
You are using the software SPI, this will definitely not be fast. The display you mention is not listed in u8g's device list (or the list is not up to date because there was a new release a few days ago). Try using U8GLIB_NHD31OLED_GR u8g(10, 9) instead, this will automatically try to use the hardware SPI. The function overload with 4 arguments will do software SPI on the specified pins.
 
Hello.U8g(10,9) only activates 2 pin's on Arduino, i did check the other pins with my oscilloscope,pin10 connected to SC,and pin 9 to D/C on the screen side,the screen was set first to 3 wire and then 4 wire SPI mode,the screen was black on eider mode. From the screens Manual,the 4‐wire mode needs SCLK, SDIN, D/C, and CS and 3-wire SCLK, SDIN, CS.
So maybe this library don't have HW SPI mode for this screen. Any other suggestions,maybe i can try.
Thank you for your help
 
Hi,

so the hardware SPI seems to be left uninitialized. However, if your code compiles, using the hardware SPI is certainly meant to be supported. The u8glib author is working on this display I think, telling from the activity on the wiki pages and the issues (see homepage).

I can give you my own (slow!) code for the ARM port which is written for the SSD1351_128x128 display. It provides a low-level interface to u8glib and handles the mk20dx128's SPI.

Regards

Christoph
 
Any updates on this? I have a project built for Arduino which is based on this display and U8GLIB. I would like to use the Teensy.
 
The SSD1322 256x64 and the Teensy 3.

I opened a simple example from the u8glib examples list and attempted to compile it for the Teensy 3 with the NHD 3.12 but received various errors which is why I ask.

Thanks
 
Cool... :cool:

Mine is actually an EastRising brand but I think they are the functional equivalent. The u8glib library for the NHD worked with it under Arduino anyway.
 
I too am interested in this u8glib working with teensy3.1.

I have an Adafruit 1.5in oled with SSD1351 chip, and the refresh rate is dog slow, like .1 sec to black and .1 sec to draw, the flicker is horrible. This is when using the Adafruit libs and hw spi.
I would really to be flicker free. Pointers to any approach would be helpful.

When I try to use u8glib, arduino1.0.5 and the dev teensyduino 1.18rc I get a build error.

The problem is in u8glib, related to the SPI object.
This is simply building the HelloWorld demo and commenting out one of the ssd1351 lines.

Code:
  This report would have more information with
  "Show verbose output during compilation"
  enabled in File > Preferences.
Arduino: 1.0.5 (Windows XP), Board: "Teensy 3.1"
C:\src\arduino\projects\libraries\U8glib\utility\u8g_com_arduino_hw_spi.c: In function 'u8g_spi_out':
C:\src\arduino\projects\libraries\U8glib\utility\u8g_com_arduino_hw_spi.c:302:15: error: invalid type argument of '->' (have 'SPI_t')
C:\src\arduino\projects\libraries\U8glib\utility\u8g_com_arduino_hw_spi.c:302:26: error: 'SPI_SR_TDRE' undeclared (first use in this function)
C:\src\arduino\projects\libraries\U8glib\utility\u8g_com_arduino_hw_spi.c:302:26: note: each undeclared identifier is reported only once for each function it appears in
C:\src\arduino\projects\libraries\U8glib\utility\u8g_com_arduino_hw_spi.c:305:7: error: invalid type argument of '->' (have 'SPI_t')

Thanks.
 
"dead slow" is as good as it gets, and u8glib won't let you do much about it, because it doesn't support asynchronous updating of the display. I have theadafruit ssd1351 1.5" as well and it has some flicker by itself, plus it emits a high pitch sound when the overall image is very bright.

I've started to write my own gfx lib with dma, which currently gives me 22 fps. No fonts yet, though
 
I recently worked on the ST7735 library, adding optimizations similar to Peter Loveday's earlier work. The latest code is here:

https://github.com/PaulStoffregen/Adafruit_ST7735

Eventually I'm going to port this to u8glib (in SPI mode) and other display libraries. A couple days ago I started it on the very similar Adafruit_ILI9340 library, but I broke something along the way and haven't figured out what's wrong yet.

I have the Newhaven OLED display here on my desk, wired up to a Teensy3 (just wired it up a couple days ago). I hit the same compile error with the latest u8glib. I'm going to dig into that code soon.
 
Hmm. Thats very disappointing. So much so that I don't think I will ever get anything form adafruit again, this is like the 3rd item I have gotten that was nowhere near what it was advertised for. You would think a display would like, you know, be usable to update text 1once per second. But the redraw is so slow as to be unusable.

Perhaps you could share your dma code? I don't know much about dma type coding. I suppose I could learn dma.

Or get a more appropriate display.

Thanks.
 
Could you please post a link to this specific Adafruit product?

Edit: some of their libraries use bit bashing, which is horribly slow. Some use faster SPI if you use one constructor, usually the one without the MOSI and SCK pins, and slow bit bashing if you use the other one. I can't know if this applies to your situation, but it's possible you might be able to get much better speed by simply using the other constructor.
 
Last edited:
Status
Not open for further replies.
Back
Top