Shop OBEX P1 Docs P2 Docs Learn Events
LCD driver structuring and code layout ideas — Parallax Forums

LCD driver structuring and code layout ideas

Timothy D. SwieterTimothy D. Swieter Posts: 1,613
edited 2008-11-19 12:47 in Propeller 1
This thread started out as trying to solve my code structuring problems which were eventually solved with a "ret" (head/hand smack!). Below though there is discussion on structuring code for an LCD driver.

I am setting up a new driver for an LCD display I have in my latest project. The driver will be in assembly. I also want the driver to be of the format where a spin routine sends a command to the assembly driver. The assembly driver executes the command. Some commands may wait to finish, others may allow the main code to continue.

So, I was looking at Float32 and Graphics as examples of how an assembly routine can be structured for the program I am envisioning. The assembly code waits for a command, when it receives one it does a little processing, finds where to branch to, branches, executes the command and returns. I attached my code for what I got so far and pasted part of it below.

CmdWait
              rdlong    t0,     par        wz   'Check for a command being present
        if_z  jmp       #CmdWait                'If there is no command, jump to check again

              mov       t1,     t0              'Move the address of the command + parameter
              rdlong    paramA, t1              'Get parameter A value
              add       t1,     #4              'Increment the address pointer by four bytes
              rdlong    paramB, t1              'Get parameter B value
              add       t1,     #4              'Increment the address pointer by four bytes
              rdlong    paramC, t1              'Get parameter C value
              add       t1,     #4              'Increment the address pointer by four bytes
              rdlong    paramD, t1              'Get parameter D value

              shr       t0,     #16        wz   'Get the command
              cmp       t0,     #(_backLight>>16)+1 wc  'Check for valid command
        if_z_or_nc jmp  #:CmdExit               'Command is invalid so exit loop
              shl       t0,     #1
              add       t0,     #:CmdTable-2
              jmp       t0                      'Jump to the command

              'The table of commands that can be called
:CmdTable     call      #reset                  'Reset the LCD, but doesn't initialize
              jmp       #:CmdExit
              call      #initLCD                'Initializes the LCD
              jmp       #:CmdExit
              call      #screenUpdate           'Update the data on the display
              jmp       #:CmdExit
              call      #bl                     'Backlight on/off/intensity
              jmp       #:CmdExit
:CmdTableEnd  

              'End of processing a command
:CmdExit      wrlong    zero,   par             'Clear the command status
              jmp       #CmdWait                'Go back to waiting for a new command
'-----------------------------------------------------------------------------------------------------
reset
             nop                        
reset_ret

'-----------------------------------------------------------------------------------------------------
initLCD
             nop                        
initLCD_ret
'-----------------------------------------------------------------------------------------------------
screenUpdate
             nop                        
screenUpdate_ret

'-----------------------------------------------------------------------------------------------------
'Command sub-routine to adjust the backlight to a certain intensity
bl
              nop
bl_ret




The first thing I don't have clear in my mind is how the parameters are getting passed. I see the code and believe it, but I don't have good words or a picture in my mind to help me troubleshoot this in case it is not working. The next portion I don't understand yet is the getting of the command and calculating where to jump to. If someone can help me with a description of what is going on there that my help clear the fog in my mind.

With the attached code I see a problem on the I/O lines even though the code shouldn't be doing anything with the I/O. In the attached code there are routines after the bl routine shown above. If those routines that are after are commented out, like they are in the file, then the preset state of "reset" and "rs" and "bl" lines are at the appropriate 0V or 3.3V. If however I uncommented those extra routines then the I/O pins are showing voltage of 0.7V or 2.1V even though the code shouldn't be touching them or running through those other routines. I suspect that the problem is in calculating the parameters or the jump to address in o the command table or similar. I suspect that portion because I don't understand it.

So, if someone can help me to understand how the commands/parameters are getting passed into the ASM that would be a start. If there is other code like Float32 or Graphics that I could also reference on how to structure a "wait for command" style assembly that would help too.

Thank you,

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto for SunSPOT, BitScope
www.tdswieter.com

Post Edited (Timothy D. Swieter) : 11/18/2008 6:54:57 AM GMT

Comments

  • Erik FriesenErik Friesen Posts: 1,071
    edited 2008-11-16 00:34
    Here is my 6800 style interface driver for a 128x64. It is a version of my original attempt at assembly so it will have some things you may laugh at. It likely would drive your lcd with a few mods. I also have one that includes a backlight driver. I set up a counter that updates every cycle from a hub memory variable located after the byte variables declared in the lcd object. It is similar to the way the contrast is adjusted in this object.

    I am assuming you are using a lm9033a chip driving a monochrome lcd and that it can be configured so you can set it up in the 6800 style interface.

    I think it would be easier to split your commands into separate variables, but other voices may say different.
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-16 05:57
    Thank you for posting your code Erik, I will have a look at it.

    The LM9033A is the part number for the display that I am using and not the IC. I will be selling this display soon through the Brilldea my web site. I am awaiting delivery of the stock and I need to create my example code based on the driver I am writing now. The display is flexible in that it can receive input in a parallel (6800/8080) or SPI (3 or 4 wire). By default the display is SP 4 wire and that is what I am writing the driver for. Writing the actual code to send/receive data from the LCD isn't the real problem at this point. My problem is more of structuring the code in a flexible way so that other users can take full advantage of the code and be able to add/modify as needed for if they wanted another interface style.

    In the past when I wrote LCD display code I set it up to initialize the display and then drop into a forever repeating loop of sending data to the display. I want to structure this code a bit different in that it only updates the display when told to. The LCD display isn't like a VGA or TV driver where it always needs to run and be updated. The LCD display can take an update and every now and again get a new update. It doesn't have to be continuous.

    So, the rest of today I am going to investigate the foundation I have so far to see if I can find what is wrong. Then I can start adding meat to the structure for the actual clocking of data and bytes.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto for SunSPOT, BitScope
    www.tdswieter.com
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-16 05:59
    Erik -

    I just glanced through your code. Wow! You have a lot of stuff in there. Be sure to post this in the object exchange if you haven't already. I hope others can find use in this code too.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto for SunSPOT, BitScope
    www.tdswieter.com
  • kwinnkwinn Posts: 8,697
    edited 2008-11-16 07:00
    Timothy, I hope this helps.

    It appears that this cog is dedicated to running the commands produced by other cogs and does the following.

    CmdWait:
    rdlong t0 par wz ' Reads the long at location "par" in main memory and store it in t0

    if_z jmp #CmdWait 'If "par" is zero (no command) jump to "CmdWait" and read it again

    mov t1 t0 'Move the command + address of the parameters to t1 ( the data in "par" would be the command and address of the first parameter in the list)

    rdlong paramA t1 'Read the long t1 points to and put it in "paramA"

    add t1 #4 'Add 4 to t1 to point to the next parameter in main memory

    'Repeat the above 2 instructions to get parameters B, C, and D

    shr t0 #16 'Shift t0 right 16 bits to remove the address portion of "par" and leave the command

    cmp t0 #(_backLight>>16)+1 wc 'Compare the command (which is the offset into the "CmdTable") to make sure it is a valid command
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-16 07:16
    Thank you kwinn for filling in some blanks. I was going through the Propeller Manual and was piecing some of this together. I think I understand the shifting the command to the upper word of a long. Only the lower word is needed for the address. Actually only 9-bits are needed for the address.

    It looks like the initial stuff is working based on what I see and understand. By initial I mean that the command and parameters are coming over OK into the assembly portion.

    For the part following the command check, does the following make sense:

                  shl       t0,     #1              'Shift left, multiply by two, to get to word instead of byte? or long instead of word?
                  add       t0,     #:CmdTable-2    'add in the "call" address".  Why "-2"?
                  jmp       t0                      'Jump to the command in the table
    
    



    I did more testing with the code I attached in the top post. As I said, with the "helper" routines commented out (the helper routines are after the "command" routine) the code appears to execute OK. With the "helper" routines uncommented I get strange results as if they are being executed or something and they shouldn't. My test it to issue one command, the bl command to turn on one I/O pin. Next I moved the "helper" routines above the "command" routines an left them uncommented. The code appears to work with this arrangement. Is there something in the way that the code is being structured or the jmp/call addresses are being calculated that "helper" routines or any other routines cannot follow the "command" routines?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto for SunSPOT, BitScope
    www.tdswieter.com
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-16 07:35
    This just in...... the code seems to not be returning from a called command routine.

    Up in the call table there is this:
    :CmdTable     call      #rst                    'Reset the LCD, but doesn't initialize
                  jmp       #CmdExit
                  call      #iLCD                   'Initializes the LCD
                  jmp       #CmdExit
                  call      #su                     'Screen update with new data
                  jmp       #CmdExit
                  call      #bl                     'Backlight on/off/intensity
                  or        outa,   blMask   
                  jmp       #CmdExit
    :CmdTableEnd  
    
                  'End of processing a command
    CmdExit       wrlong    zero,   par             'Clear the command status
                  jmp       #CmdWait                'Go back to waiting for a new command
    
    



    Then there is a the commands:
    bl
                  andn      outa,   blMask
    bl_ret
    
    



    I am seeing the LED turn on or off depending on what I place in the bl routine. But, I don't see the LED immediately change state with the line of code I added just after the call. This may makes sense why the "helper routine" may have been executing. It is as if the "bl_ret" isn't returning there the next instruction after it's call. maybe I am defining lables wrong

    ...........................DOH!!!!!!!!!!...............................................

    I don't have a "ret" in the command routine.


    ...........................DOH!!!!!!!!!!...............................................

    Boy I feel sheepish now. So obvious!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto for SunSPOT, BitScope
    www.tdswieter.com
  • dpescheldpeschel Posts: 16
    edited 2008-11-16 08:33
    Timothy,

    First make sure all the ..._ret labels have ret instructions after them. When it does a call, the Propeller changes the address part of the return instruction. The opcode part had better be a jump. (ret counts as a jump.) You are missing some and the Propeller will change the address part of whatever instructions you have at the labels instead. So your subroutines will just continue to the next subroutine and you will change something you don't want to. For example, the first word of sendCMD is something you definitely don't want to change. Changing it would make some other pins into output pins.

    Other things I also noticed:

    Your start method doesn't initialize command. If you know it's always set to something meaningful, you know your Spin code avoids a big possible error.

    How are you calling the driver? From another Spin file? What order do driver methods get called in? Do you know for certain what the order is?

    I think you have the right syntax for cognew but I had to convince myself of it. The procedure being called always needs an @. The variable (which goes into the PAR register for the assembly code to get) can be a 14-bit number, but in your case it must be an address, thus the other @. (An address because the assembly code needs to read memory around command's location. A number wouldn't tell the assembly code where command was, so it wouldn't know where the chip select and things were.) Hopefully you're at least as confident than I am about the syntax.

    Can you have the assembly code blink LEDs or set a variable that Spin will continuously read? If you're really confused about it, you should probably prove to yourself, in small chunks, that it's doing what it should. For example, that it gets the right command, calls the right command handler, etc.

    Post Edited (dpeschel) : 11/16/2008 9:19:57 AM GMT
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-16 08:56
    The lack of "ret" was the hickup in the code. As I said, I feel sheepish for overlooking that after having been writting in assembly for some time. Just goes to show how many, many hours of work can cause fatigue.

    Thank you for your look into this dpeschel. I have been watching data on both a serial terminal, LEDs, volt meter and logic analyzer. I should have recognized the lack of "ret" as soon as it happened but I thought I was missing something else and not understanding the code direction. I blame the "new stuff" because it was late and not all of it was adding up in my head.

    Other comments:

    I understand the point about not initializing the command variable to a value, but all variables are initialized to zero therefore I didn't write it out. Writing it out would make it clearer though.

    I know the spin and cognew are working just fine. This is "plain vanilla" code there with no surprises.

    The routine above is a snippet of much larger code that I am not able to post, at least not yet. In time I hope to be able to post the whole project, but we will see how it turns out.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto for SunSPOT, BitScope
    www.tdswieter.com
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-16 08:58
    Oh, I should add, go ahead and get yourself a Propeller. At least a Protoboard or a demo board would be a joy to work with.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto for SunSPOT, BitScope
    www.tdswieter.com
  • Erik FriesenErik Friesen Posts: 1,071
    edited 2008-11-16 14:15
    One thing that would be nice is if you could make some good way to initialize this for any style of interface and any pin arrangement. This will require some ingenuity on your part. The
    way I did it is not very transferable between projects.

    Do you need to conserve power or memory? If not is seems easier to allow a continuous loop.
  • kwinnkwinn Posts: 8,697
    edited 2008-11-16 15:59
    From what I can see in this code snippet the commands are numbered sequentially starting with 1. Command 1 would be reset, 2 would be initLCD, etc.
    This is a fairly standard way to do things. A lot of early microcomputer monitors were done this way. The command number has to be multiplied by 2 to
    convert it into an offset into the command table (each call & each jmp takes 1 long) so the "shl t0 1" does that. This converts command 1 to an
    address of 2, 2 to 4, etc. but the address offset is pointing one position too far into the table. The "add t0 #CmdTable-2" converts the offset into the
    actual address where the call instruction for each command is located. The "jmp t0" now ends up at the correct place in the table.

    The "cmp t0 #(_backlight>>16)+1 wc" just before the second "if" statement calculates the offset of the last command in the table and compares that to
    the command number to be sure the command number is not larger than the offset of the last command in the table (an invalid command).

    This code snippet could be modified slightly to become the skeleton of a good general purpose command jump routine.

    Kurt
  • dpescheldpeschel Posts: 16
    edited 2008-11-16 18:57
    Glad your code works! You said you were confused about parts of the code, so I wasn't sure how much general experience you had. I wanted to emphasize but not lecture. Are you still confused about parts of the code?

    A Prop would definitely be fun. I need a PC or development tools though, and for my interests the Prop really needs more memory. But I'm watching people make bdtter and better use of the memory that is there (to write mini-OSs and so on) and I'm also eager to find out more about the Prop II.
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-16 23:14
    The intent with my LCD driver is to make it general purpose and to make it well structured for anyone you will want to use it. I hope to get stock this week of the display to sell on my web site. The display is 128x96 graphics, monochrome, 4 gray levels in a small package with white LED back light. The purpose to do the code in the command style is so that commands can still be sent to the display for turning it on/off or power save or inverse display, etc. If I was to simply drop into a forever repeating loop on display ram then I would not be able to stop and send commands without a flag of some sort.

    The method I am pursuing really appears to be the best because there is no need to update the display continuously because it is LCD. Furthermore, the user can decided on double buffer video memory versus single buffer video memory. If the user wants the display to be updated continually I may include a mode where this can be done or it can be done by continually calling one of the commands I am setting up. Based on my experience on writing past LCD drivers for monochrome displays and the uOLED display I think this way of structuring the driver is the best so we will see how it goes once I release it for use.

    Erik - thank you for the recommendation on providing for multiple interfaces, I hadn't considered that yet. By default the display is configured in 4-wire SPI so naturally I am focused on that driver. This also worked for my project because I wanted to get the pin count low. I will get this code working and release it to get any feedback or recommendations first. With the way the driver is structured I can see that once the core parts are working and proven that it is a matter of changing the initialization routine and the data clocking sub-routines to get the other interfaces working. Maybe a little work in the SPIN code too. Therefore I think I can provide the other interfaces (3-wire SPI, 6800, 8080) in time. This would really make the driver general purpose because I am sure others could take my code and morph it as needed for their LCDs. The code may be a different driver for every interface though or in the same code, we will see. I think I will add the other as time allows. Again, thank you for the recommendation.

    kwinn, dpeschel - thank you for the details, code explanation and looking into the code and writing it out in words. My mind over the weekend just wasn't getting over a hump, but you have helped me to see more clearly now. I know I should have been able to see this.

    My code is cranking along as expected now. Last night I got the initialization routine of the LCD screen written and tested. This week when time allows in the evenings I will get the screen update routines working too. I will post progress here so others can see how it works.

    Oh, by the way, the LCD driver that I am working on will be compatible with graphics.spin. Erik I see in your code you included the draw routines. With my code and past code I wrote a user would setup display memory, start graphics.spin, start my LCD driver and then use graphics.spin to draw in the video memory. From there the LCD driver would take that memory and write it out to the display. I have done this before on a couple other drivers I have done and it works really well. First it means the LCD driver is just the LCD driver. Next it means that the LCD driver may be compatible with code already written with graphics.spin or code object built on top of graphics.spin.

    I am still shaking my head, the lack of "ret" was the component that kept be debugging for so long. I remember setting up a test early in my debugging to see if it was falling through the routines, but at that time I was only blinking an LED with no logic analyzer setup and so I wouldn't have seen the LED blink because the code is too fast. It wasn't until I discovered the code wasn't returning from executing a command that I realized the code was walking off the end of the program. Silly me!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto for SunSPOT, BitScope
    www.tdswieter.com
  • Erik FriesenErik Friesen Posts: 1,071
    edited 2008-11-17 02:21
    Actually there are two draw routines. There are high level draw routines and a low level routine that can read from the graphics.spin video bitmap. It is updated when you call writegraphics. I didn't realize that your display is a 2bit grayscale. That calculates to 768 longs per bitmap by my calculation which does in fact start becoming a factor. I'd be curious how this all works for you. One thing I have realized in working with the pic24 graphics is how nice a pixel by pixel working scheme can be. They use the ram on the display to change the display by pixel, byte by byte. The drawback with spin is that by the time you have done all the necessary calculations it has become too slow to do it that way.
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-17 22:49
    Erik -

    I have not experienced the slowness that you are talking about. I use Graphics.spin which takes commands and then does assembly to adjust byte by byte and bit by bit the video memory. The LCD driver grabs that memory and clocks it out appropriately for the LCD. The graphics.spin way of setting up memory has always include two bits per pixel so that color palettes and such could be done. So beauty of it is that I don't need to design the graphics engine, just the display driving engine.

    Have you looked into graphics.spin? There are a couple other graphics routines out there as well but I am not sure if they are posted or not. The Hydra book is an excellent reference on this topic.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto for SunSPOT, BitScope
    www.tdswieter.com
  • Erik FriesenErik Friesen Posts: 1,071
    edited 2008-11-18 01:25
    Graphics.spin is not slow because all the pixel changing is done in assembly. The high level routines in my demo are slow because they are in spin.

    If you look at the way other platforms convert fonts and bitmaps to the screen, they typically use a pixel by pixel format. The problem with many of the lcds is that they are written to in a vertical format by page, which is difficult with anything that is not a 8 pixel high font. (this may only apply to single color lcds)

    Like you say though, the graphics bitmap is two bits per pixel so that makes your job easier.

    Sorry for being off the original subject.
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-18 01:32
    I see what you mean now Erik. My first grpahics engine for the uOLED was in SPIN in order to prove out the routines and such. No worries about getting off topic. We are still talking about LCD driver and LCD driver construction and speed.

    For me, I don't worry over the fonts size and pixel arrangements and such on the LCD or the particular micro. If the drivers for both the LCD and the graphics engine are good, then all we deal with is video memory. The driver routines take the processing of scaling a font or making sure the data is clocked out properly. Now, if we were using a graphics LCD but treating it like a character display and using a set font and tile graphic memory then we may have a problem. Since both the graphics and LCD driver using straight video memory we are OK because we can manipulate the video memory with routines, add fonts of different sizes, scale, etc. Of course, with the Propeller we only have so much memory so this doesn't extend well to color and larger displays.

    I have only written LCD drivers using the Propeller and a handful of LCDs and OLEDs. So maybe I have the luxury of speed here since I haven't tried to do the work on other micros. What is your experience? Are you use to other micros and coming to the Propeller and seeing advantages and disadvantages with graphics and LCD Drivers?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto for SunSPOT, BitScope
    www.tdswieter.com
  • Erik FriesenErik Friesen Posts: 1,071
    edited 2008-11-18 03:26
    My experience is somewhat limited The propeller is really my first real micro. I wrote a parallel lcd driver for a ks0108. In the process I came to realize the difficulty of getting a nice looking font in a 128x64 size screen. I ended up writing/copying my own font tables along with using the built in font. A project later I started using a ks0713 and rewrote my driver for that. Sad to say, I have moved my project to a pic24. In the process of starting to use their system, I realized how nice it is to have all these fonts and tools at my disposal. You can take a pixel font and convert it to a byte format which is then stored in a hex file which can then be used. However, the memory that this uses is significant when you only have 32K. Also this is being done in C which has its advantages and disadvantages. The Pic library allows semi-direct use of bmp I believe.

    However, I still prefer the propeller programming and IDE.

    I spent days connecting my first lcd and getting it to work. I thought maybe the lcd was defective.

    I think a baseline lcd driver would be in order. Something that has been forming in my mind is a general purpose parallel/serial lcd driver that could be configured in many ways and for multi sizes. I don't know how it would work for 2 bit devices though.
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-18 06:44
    Thank you for the details Erik! I have a few questions for you.

    1. What do you mean by a "nice looking font"?
    2. Why would a 128x64 screen limit you on a nice looking font?
    3. What do you mean by pixel font?
    4. What do you mean by byte font?
    5. Where there other reasons for switching to a PIC? I am hoping it was not just because of fonts because that is software based.

    The graphics engine is the thing to determine the look and the feel of the screen displayed while the LCD driver takes the video memory and serves it out to the LCD. Yes the Propeller has a built in ROM font, but there are graphics engines that don't use this. In fact, I think graphics.spin uses a vector font. My point is that any microcontroller can do any font assuming there is enough memory and the right software written. If the font tools you are using can create hex files or other outputs maybe you can grab that output, format it and place it in the DAT section of the Propeller code.

    Remember, the font is in the memory, ROM, RAM or other no matter which microcontroller you use. Fonts that describe each pixel (each bit) do take space. The font just describes the character look while the graphics engine takes that data and places it in video memory with the appropriate bits/bytes for the appropriate color depth.

    I like the idea of creating a generalized LCD driver but that is a difficult if not impossible task. However, creating a detailed application note could be possible. You see, there are many different LCD controller ICs out there. A generalized driver would difficult with all the options for commands, shifting data, initlization, color depth, etc. Therefore, an app note that describes a method or structure for creating a driver would work. The app note would provide examples and details from perhaps a couple different controller ICs, but those would be examples so the user could build on it from there. I like this idea and will add it to my heap of things to do. Don't look for anything too soon other than my code for the driver I am writing, which I hope is a good example of driver code with good comments and good structure such that plugging in new data for a different controller IC would work.

    I am happy to hear that you started with the Propeller. It is great that you are contributing to the community and helping me here in this thread. Thank you again for sharing your details like that. I am looking forward to hearing your responses to my questions.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto for SunSPOT, BitScope
    www.tdswieter.com
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-18 06:47
    I almost forgot. Attached is a picture of a 128x64 monochrome LCD screen I used in a product design. The display is being driven by the Propeller and it is using graphics.spin without any modification. Therefore the font displayed is the vector font I believe. The font and graphics engine works well for what we needed to display.

    Note that this picture is a close up, so the user wouldn't be that close.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto for SunSPOT, BitScope
    www.tdswieter.com
    1024 x 768 - 52K
  • Erik FriesenErik Friesen Posts: 1,071
    edited 2008-11-18 12:49
    By a nice looking font I mean for example the parallax font. Another example is the 5x8 font typically found in character displays. A couple of examples are included here. The tripdisplay uses the 5x8 font and a squeezed version of the parallax font from memory. The counter uses a 8x11 font. It may be I am too particular too on this issue.

    The reason why a 128x64 limits your font options is that it is nice to have a font that can be displayed evenly for example, a font that is 13 high would be 65 pixels total. Also the width is an issue. But I guess that wouldn't limit you to a nice looking font.

    What I mean by a pixel font is a font that is created from a specific set of pixels. Your typical font editor does not allow direct pixel editing.(This reference would be from a pc angle)

    By byte font, I mean another obscure reference to the pic way. If each line of the font is 5 wide with a 5x8 font example, it occupies 8 bytes. The font table says how wide each character is, and the micro prints each line from memory up to the width specified in bits.

    My reasons for the switch are:
    While the chip can do usb, it is not native and takes two cogs.(The picture attached is a prop driven product)
    Power usage. My current usage is around 125ma. This includes a quantum touch chip and another pic product.
    Cost. I can remove close to $10 in parts by using the pic part, partly by removing battery charging circuitry.



    I know that a person can't write a totally general purpose driver but what I had in mind is more something that could be configured for a number of screens. It is fairly obvious to me that the person using the code will have to have an understanding of how to use his particular lcd, which will include studying the data sheet.


    What is a vector font, by the way?
    1200 x 800 - 91K
    722 x 1116 - 312K
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-19 12:08
    Yahoo!!! The first images of my new LCD driver is coming to life. Nothing fancy here yet, just a bunch of code that is working but needs to be better organized, commented, and documented. Not to mention to add the various features and function I would like to add. I am still a few days away from posting any code, but here is a screen shot.

    The LCD driver I am creating works with graphics.spin. So, the image shown on the screen was first drawn in the "video memory" using graphics.spin, then the video memory was processed and sent out to the display.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto for SunSPOT, BitScope
    www.tdswieter.com
    1024 x 768 - 65K
  • Erik FriesenErik Friesen Posts: 1,071
    edited 2008-11-19 12:25
    Looks good. Plus your workbench looks a lot cleaner than mine.
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-11-19 12:47
    Erik Friesen said...
    Plus your workbench looks a lot cleaner than mine.

    That is why it is a close up! smilewinkgrin.gif

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter, E.I.
    www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, uOLED-IOC, eProto for SunSPOT, BitScope
    www.tdswieter.com
Sign In or Register to comment.