ST7920 display using u8glib works on atmega328 but not on atxmega128A3U

Go To Last Post
41 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have a couple of 128x64 ST7920 based LCD displays.  Using u8glib, I have the "Hello World!" example running perfectly (along with the other examples).  As I have been working more and more with the xmega (to try and bring myself up speed), I thought this would be a great project to port to the xmega...

 

To port it, I created a new basic project (no ASF) for the atxmega128A3U and copied the relevant files from the working atmega code to the new project.  The edits to make it speak xmega was fairly straight forward, especially since I was hard coding in SPIE on PORTE (this was a test, not a library creation project).  Everything compiles and I do get output.  But nothing ever displays.

 

At this point, I have hooked up my little logic analyzer and verified that both boards are outputting identical initialization commands bit-for-bit and byte-for-byte.  Both are outputting the draw commands as well, but I have not verified them bit for bit (yet.  next step I think).  I have also verified the timings on both boards.  Per the datasheet (http://www.digole.com/images/fil...) on page 37, it shows that the clock cycle time for SPI is 400ns at 4.5V and only 600ns at 2.7V (Vmin).  In addition, I have also verified that chip select is working correctly (The ST7920 is backwards from most and is active high.  The u8g library takes this into account and the logic analyzer shows it is doing what it should).

 

What I found interesting is the working atmega328 board is actually running faster than spec at 300ns clock cycle time.  I have tried assorted different speeds on the atxmega from the same speed at the atmega328 (300ns) all the way down to 2500ns.  The same results occur ever time, nothing is displayed.

 

I have two of these displays and they both work exactly the same: Will work on the atmega328, won't work on the atxmega.  I SUSPECT the problem is with the voltage, but at this point, I'm asking for any suggestions on what to check or ideas on what might be the problem. 

 

If anyone has a working library for this display, I would be very grateful to take a look at it if possible.  I know the problem is probably pretty simple and probably right in front of my face as well!

 

Thanks!

 

Clint

Last Edited: Sun. Mar 22, 2015 - 10:42 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One other question: Would it be possible to run the display on 5V while leaving the xmega at 3.3V?  The board handles 5V inputs and there is no MISO pin on this display, so everything should be one-way from the xmega to the display.

 

Has anyone tried something like this, or is there a pit of dragons I have completely overlooked here?

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AFIK,   the ST7920 will run fine at 3.3V

And it will generate the relevant internal contrast voltages.

 

I am p*ssed at the moment.    I might try it with a real ST7920 tomorrow.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:

I am p*ssed at the moment.

 

Been there.  Done that!

 

david.prentice wrote:
I might try it with a real ST7920 tomorrow.

 

Thanks!  I know the datasheet says 2.7V, but it also says 400ns clock and I know it will run at 300ns.  I've been scratching my head over this for the last day or so and it is getting a bit irritated.

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, just for fun, I hooked the xmega up to my scope and took a more detailed look at the output.  I can't speak for the data being sent, but the waveform looked good.  The timing matched what I was seeing on my (cheap) logic analyzer and the timing was right at 1us for a clock (min is 600ns at 2.7V), so I should be well within range.  I think I am going to have to do some byte by byte comparisions between the two boards and see if I can find the difference.  Maybe in the timing between bytes?

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, I might have found the problem.  The datasheet I have says the ST7920 works from 2.7V to 5.5V.  I just found another datasheet that states 4.5V to 5.5V...  Given the age of this board (mid 2000's), that is MUCH more believable to me.

 

I've got a couple of SPI level shifter ICs on order, so I should know in a few days.

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry,   I had promised to try the ST7920 at 3.3V.

 

Anyway,  I powered the UNO via the STK500 programmable voltage.

The display module is very readable for 4.5V-5.5V

 

As you reduce the voltage,   the contrast becomes less distinct.   The module is unreadable at 3.3V

 

Looking at the ST7920 data sheet,   it should be perfectly functional at 3.3V

It looks as if you need to use the Voltage Doubler output VOUT

 

My module (from Hobby Components) is 5V only.   It is not populated for the R12 that connects to the VOUT pin.    And I suspect that you need to populate C3, C4 etc.

 

Of course,  there is probably a proper manual somewhere.    After all,  most systems will be 3.3V nowadays.    If you can find proper instructions,  I am guessing that you just need to alter links for 3.3V or 5V operation.    Otherwise,  you will need to trace the pcb of your module and work it out for yourself.

 

As my module came out of the box,   it will plug directly into a 16-pin DIL socket designed for a 5V HD44780 or a 20-pin DIL designed for a 5V KS0108 module.

Note that if you start populating the pcb,   you will lose the 'plug-in' convenience of using an existing HD44780 socket.

 

If you are unsure of the pcb (as I am),   it is probably easiest to run it at 5V with level-shifters for the Xmega SPI.    Parallel is a real pain because you would need to change direction ref the RW pin for the DB0-DB7 level-shifters.   

 

David.

Last Edited: Wed. Mar 25, 2015 - 10:17 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank David!  I'll dig back into the datasheet and see exactly what it has to say about the VOUT configuration and see if I can get that working.  If not, I'll try it on Thursday when the level translators arrive.  Currently, I have a mix of 5V megas (and tinys) and 3.3V xmegas, so using an external level translator is probably the best bet at this time.  Of course, that all depends on what project this thing ends up in.

 

I really appreciate you looking into this for me!

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Level-translating SPI is pretty easy.    The ST7920 is always a Slave.    So you know exactly which direction each signal goes.    In fact you omit the MISO line.

 

In other words,   if you power the ST7920 module with 5V,   it will be perfectly happy with 3.3V logic signals from the Xmega.   e.g. CS, SCLK and SID (and hard-wire the PSC input for Serial)

 

Those modules look after the contrast etc.    You only need to connect VCC, GND, CS, SCLK, SID, PSC.     Some modules may default to Serial,   in which case you don't even need to connect PSC.

 

Incidentally,   you can almost drive the ST7920 as if it was a HD44780 16x4 display.    Except that the inbuilt font looks pretty horrible.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried it at 5V on the display and at least got a stripe of noise at the top of the display.  Of course, I might have messed up the u8g code with all my "testing" so I need to go through it before I try it again.  If not, the level translators should be here tomorrow. 

But seeing some pixels light up is a positive result!
 

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So if I am reading the datasheet correctly, I will have to get the voltage double working or wait on the level translator.  I say this because logic high has a minimum value of 0.7*Vcc or 0.7*5V = 3.7V.  The xmega is only putting out 3.3V, so no joy there.

 

Now I just need to figure out the voltage double stuff...

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would put money on the 5V display working correctly with 3.3V logic signals.

 

Yes,   you are at the limit of logic thresholds.    But why not just try it?

As I said earlier,   the SPI i/f is input only.   So it will never 'send' 5V to the Xmega.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually I did! ;) 

 

I tried it at 5V on the display and at least got a stripe of noise at the top of the display.

With 3.3V to the xmega and 5V to the display, I only got a strip of noise through the top 1/4 or so of the display.  I considered that a positive result as before I hadn't been able to get ANYTHING out of it with the xmega.  Switching it back to 3.3V on both and it reacted just like before.  Nothing.

 

I haven't been able to find any information on the PCB and the datasheet on the driver doesn't have much information on how to configure the voltage doubler, but I haven't given up on that.

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, the level translator got things talking.  Noise is an issue now with my test setup (no surprise actually), so I'm going to make up some short cables and see if that gets things cleaned up enough so I can move on with the testing.  I really wish this display used RS485 instead of SPI...

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The level translator did the trick.  I initially connected it using ribbon cable (an old IDE cable sliced up) that was bout 12" total with the translator in the middle of it (this is development hardware after all!).  While I could FINALLY get noise and other stuff on the screen, I still couldn't get it to properly display my "Hello World!". 

 

So, I rewired it with about 8" total of cat5e cable using the extra wire as ground in each pair for the data lines.  That did the trick.

 

Now I can get busy and actually rewrite u8g to properly support the xmega by allowing you to pass the SPI port and such in the initialization function.  Actually, given how simple the edits were to get it working on xmega (hardware issues aside!), I'm kind of surprised it hasn't formally been ported yet.

 

Clint

Last Edited: Thu. Apr 2, 2015 - 10:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you actually planning to port it to xmega?

I think it would be a great succes ;) (Many would appreciate it)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I want to use u8glib with Xmega in my project.

Can you send me your source code with updated u8glib library.

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Rolfiboy wrote:

Are you actually planning to port it to xmega?

I think it would be a great succes ;) (Many would appreciate it)

 

It basically IS ported.  They way u8g has the hardware abstracted, it was very easy to modify the avr/arduino code to work with the xmega.  I just need to go through it and use there method of use ifdef <__blah__> to add new sections for the xmega and basically copy and edit the "mega" hardware files to make new ones for the xmega.  My current hack is just to edit the existing avr code to work with the xmega, so that is no good for integrating it into the code base.

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Bulka_cz wrote:

Hi,

 

I want to use u8glib with Xmega in my project.

Can you send me your source code with updated u8glib library.

Thanks

 

Let me get it properly ported first.  I'll try to do that tomorrow.

 

But I would recommend you get the avr u8g lib, set it for a mega168 or something and make sure it complies, then switch to your xmega and start editing it to work with that chip.  It is pretty well abstracted, so there are only a few files that need to be edited and the edits are very straight forward if you have basic familiarity with the xmega (which I BARELY had starting this project.  Better now!) 

 

As long as you don't try to run a display that needs 5V off your xmega, it should be pretty straight forward.

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually I will give it a try tomorrow, I have a xm64 development board with a xmega128A3U and I have a SH1106 1,3" Oled which have both SPI and TWI interface possibility. Think I also have some other oled displays laying around.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am newbie in atmel, this is my first project. I want to use atmel as composite device (HID joystick - already running and cdc virtual COM port).

 

So I will wait for your progress

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am my self a newbie, well not to C and electronics, but to xmega, and its some time since i programmed megas, but i am a fast learner :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

RRRoamer: You use sections like this?

 

#if defined(__AVR_XMEGA__)

#else if defined(__AVR__)

#endif

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Rolfiboy wrote:

RRRoamer: You use sections like this?

 

#if defined(__AVR_XMEGA__)

#else if defined(__AVR__)

#endif

 

Yes.  In the avr branch of u8g it has sections for atmega and arduino already defined.  I've already added the xmega sections like you have shown.

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Nice, how long are you in process?

Well i have been added code to com_atmega_hw_spi.c to support xmega, but only SPIC, need a switch to set the other hardware SPI ports. The same for com_i2c.c which i am looking at now.

 

I think there also need some changes to the internal pinmapping/index....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That is what I am working on now.  When I first edited it to test, I just hard coded SPIE and PORTE and I had to bypass the pin mapping OR and ANDing stuff.  Getting that to work in the GENERAL case is quite a bit trickier than the specific case!

 

We need to be able to specify exactly which SPI unit to use as the xmega has multiple units and more than one may be in use, so I have edited the function definitions to take an additional SPI_t argument.  I'm trying to get around also having to pass an additional PORT_t argument as well (see other thread I just created).

 

I'm not sure how I am going to handle the pin mapping stuff u8g uses.  My instinct says to handle it with #defines in the u8g.h file, but I have no idea if my instincts are correct on this.  For example, this bit of code:

case U8G_COM_MSG_RESET:
      u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val);
      break;

from u8g_com_atmega_st7920_hw_spi.c handles setting and clearing the reset pin on this display and u8g_SetPILevel is defined as:

void u8g_SetPILevel(u8g_t *u8g, uint8_t pi, uint8_t level)
{
  uint8_t pin;
  pin = u8g->pin_list[pi];
  if ( pin != U8G_PIN_NONE )
    u8g_SetPinLevel(pin, level);
}

which if you follow the u8g_SetPinLevel function through you finally get to a define like

#    define U8G_ATOMIC_AND(ptr, val) 	do { uint8_t tmpSREG = SREG; cli(); (*(ptr) &= (val)); SREG = tmpSREG; } while(0)

And that is going to have to be edited to work with the atxmega chips.  Well, at least I THINK it is going to have to be reworked!  My memory tells me this would not work with the xmega and I changed it (hard coded) in my tests to a "normal"

PORTE.OUTSET = PIN3_bm;

for example.

 

Which brings up a question that I hope someone here can answer:

 

Do we need to worry about writing interrupt safe code by disabling and then reenabling interrupts around the .OUTSET amd OUTCLR calls?  I would think the answer to that is "no", but my thinking has gotten me into trouble before...

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I did some reading in AVR1313 and came across this:

Note that it is important that the multi-pin configuration is not interrupted by a task that writes to a PINnCTRL register. If the PINMASK register is already written, an interrupt is executed, and the interrupt service routine (ISR) writes to any PINnCTRL register,pins belonging to a different I/O port than intended will be configured. The recommended solution is to store and then disable the global interrupt flag before doing a multi-pin configuration and restore the global interrupt flag after the configuration has been written.

The implication of this is that you DO need to worry about interrupts when using the multi-pin features, but there is NO warning when using single bit set/clear commands.  So we SHOULD be able to get rid of that interrupt safe code from u8g safely.

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well thinking about adding some global variables, in the u8g.h file, like SPIN TWIN, which value from 0-3 repressents respectfully SPIC, SPID, SPIE, SPIF and TWIC, TWID, TWIE, TWIF.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The problem with global variables is that you still get stuck with only using a single interface.  I can envision a case were you might have two displays on the same controller and that would break that.

 

Also, if you ARE going to do a global #define, use something like #define SPI   SPIE, #define TWI   TWIC instead of using a number that then has to be decoded to mean what you want.  It's already fixed in stone, might as well fix it with what you need.

 

But it is also YOUR code, so do what you want!  :)
 

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are right :)

 

Could you add like a variable to the  input/configuration string, like: u8g_InitI2C(&u8g, &u8g_dev_ssd1306_128x64_i2c, U8G_I2C_OPT_FAST_TWIC);

 

 

But i dont think you can use it to affect the pin mapping, or yes maybe you can, if you bypass the PI index in u8g.h with the ifdef xmega.???

 

I can see its more complicated than first thought, but its a good learning curve :)

Last Edited: Mon. Apr 6, 2015 - 07:59 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Rolfiboy wrote:

You are right :)

 

Could you add like a variable to the  input/configuration string, like: u8g_InitI2C(&u8g, &u8g_dev_ssd1306_128x64_i2c, U8G_I2C_OPT_FAST_TWIC);

 

That is the approach I took with the SPI portion of u9g.  The I2C part is being a bit more irritating as it basically has no parameters (there are "options" that appear to be defined as they I2C states).  I posted a thread on the u8g site to see how this SHOULD be handled, if anyone has anything to say that is.

 

 

Rolfiboy wrote:
But i dont think you can use it to affect the pin mapping, or yes maybe you can, if you bypass the PI index in u8g.h with the ifdef xmega.???

 

That whole PI mapping is a bit of mess, at least to my understanding.  I THINK I know why they did it that way (flexibility and the ability to store the pin in an array), but it does get a bit confusion come decode time.  Especially if you didn't design and implement it in the first place.

 

Rolfiboy wrote:
I can see its more complicated than first thought, but its a good learning curve :)

 

That is the truth!  Doing a simple "make it work on SPIE by hard coding" was very much trivial.  Getting it to work with ALL the SPI ports on an xmega is another thing.  It IS making me knock a LOT of rust off my pointer knowledge.

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think I have about convinced myself that I am just going to #define this problem away, at the cost of making the code a bit harder to read.  The bright side, it is a method already used in this code fork!  For example:

#if defined(__AVR__)
... All the standard AVR specific stuff such as...
void u8g_i2c_init(uint8_t options)
{ hard coded to SPI unit here }

void blah(blah) {}
...
...

#elif defined(__AVR_XMEGA__)
-- The new ATXmega specific code such as...
void u8g_i2c_init(SPI_t SPI, uint8_t options)
{ Configures specific SPI uint as passed by the SPI variable }

void blah(SPI_t SPI, blah){}
...
...

#endif

The other approach WOULD lead to simpler code base, but it would further splinter ug8.  Right now, the AVR related stuff is in it's own fork.  This includes the run of the mill AVR code as well as the Arduino stuff.  I'm currently trying to fold the xmega code into this fork by creating new blah_atxmega_hw_spi.c (or what ever) files and then editing the u8g.h and other files to integrate them.

 

At this point, I'm not too sure it doesn't make more sense to create a pure xmega fork and be done with it.  That would get rid of a LOT of junk that just isn't needed and make it easier to read.  It would help keep the original AVR code "easier" to read as well.

With a "pure" xmega fork, I could rewrite all the initialization stuff to use an SPI variable.  I also probably wouldn't waste my time porting the software SPI stuff either (why when you have so many hardware SPI ports available?).  I would also drop a lot of the #define stuff they did to allow it to work with so many different architectures.

 

One reason I am thinking of going this route is that the majority of the u8g code is NOT hardware specific at all, so newer releases could still be used with this hardware specific code with no issues or with fairly simple edits.

 

Any thoughts on this?

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I needed a break from thinking about it... But yes i think the pure xmega TWI and SPI fork, would be better. Software SPI and TWi are not really needed when you use xmega processors. They are like the 8bit worlds Swiss army knife.

 

When you have code ready i am fully interrested in testing it, i allready have some SH1106, SSD1306 and have a SSD1322 256x64 display on the way with the postman, for my next project where its used together with a xmega.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Having thought about this for a while, I have decided that I am going to go the fork it route.  There is a LOT of crap in the arduino side of the house, so dumping ALL the avr mega stuff would clean things up quite a bit (including a butt load of "#ifdef blah" statements) and would create a stand alone library for the xmega.  Then I could edit it to directly support the xmega without worrying about breaking anything on the other platforms.

 

That is the upside.  The downside is I am heading to Alamogordo in the morning for a few days to take care of a few projects for my mom, so I probably won't get back to this until this weekend.

Oh well.  Gives me brain time to think about how I want to implement this.

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey have you had any progress?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Some.  I just got back from Alamogordo and I have started to clean out the u8g.h file.  I should have time to finish the edits tomorrow.

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi sorry for the time it took to reply, have been a little busy.
 

Does it work now, or did run into some problems?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

are you still working on this?

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes and no!  Sorry! 

 

I need to build another voltage translator so I can test this out with my xmega.  Of course, this got buried with other stuff and I basically forgot about it!

 

The edits are done and it compiles just fine, but I do not know if it works AT ALL.  And I will only be able to actually test it on the HD44780 display that I have.  All the other interfaces are officially in the "who knows?" category.

 

If you are still interested, I can zip it up and you can test on your own.  If nothing else, it should give you a starting point.  I DO know that when I had it hard coded, it worked fine (before I broke the getto voltage translator I had built).  The edits to make it addressable by parameter compile and SHOULD work, but I am not a professional coder by any stretch.

 

Let me know if you want me to upload it.  Eventually I will get around to testing it...

 

Clint

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

Can you upload it somewhere? Ican test it with SSD1322 and SSD1106.

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Absolutely NO guarantees!  It DOES compile, but that is all I can say about it.  The hard coded version for the ST7920 (on portE) worded, but I have not even tested the parameter based version at all.  And I didn't do anything but look at the SSD code, so...

 

Hopefully, it will give you a place to start.

 

I'm hosting this on my server, so let me know if you have any issues getting to it: http://www.clcorbin.com/Resources/u8glib_atxmega.zip

 

Clint