• We recently switched our forum platform. If you experience any issues please email support@crystalfontz.com

CFAG160160B Initialization help

BrentK

New member
Hey guys, I'm having some problems getting my lcd (CFAG160160B) to initialize (Right now its constantly display a black line that goes across the screen).

I know you guys have the some code in C but I am not familiar with it at all. I'm trying to code using assembly using the 9s12 as the micro processor.

Here is how I have it set up, just need another set of eyes to see if I've done something wrong or not

Code:
;Testing
;Trying to output characters to my GLCD
;Port K will be the control of the GLCD
;Port B will be the data input

#include        D_variant_registers.inc


DATA            equ $1000
PROG            equ $2000
STACK           equ $2000
REGBLK:         equ $0000


lcd_CTRL        equ PORTK
lcd_DAT         equ PORTB
lcd_dir         equ DDRK

lcd_E   equ $02
lcd_RS  equ $08
lcd_CS  equ $04
lcd_RW  equ $01
lcd_RST equ $10


; LCD INSTRUCTIONS
;lcd_mode                  equ $00
;lcd_setCharPitch          equ $01
;lcd_setNumOfChar          equ $02
;lcd_setTimeDivNum         equ $03
;lcd_setCursorPos          equ $04
;lcd_setDispStartLower     equ $08
;lcd_setDispStartUpper     equ $09
;lcd_setCursorLowerAddress equ $0A
;lcd_setCursorUpperAddress equ $0B


        org        #DATA
counter:  rmb 1

;Program start

start:
        org         #PROG                          ;
        lds         #STACK

        ;INITIALIZATION
        movb    #$ff,DDRB          ; port b = output
        movb    #$ff,lcd_DIR          ; port k = output
        clr     LCD_CTRL    ; Initialize everything in portk K to 0
        clr     LCD_DAT
        
        bset    LCD_CTRL, lcd_RST ; set reset to be high
        jsr     open_lcd
        
        ;trying to output a single character
        bset         LCD_CTRL, lcd_RS
        bset         LCD_CTRL, lcd_E
        ldaa         #$0C
        staa    LCD_DAT
        jsr         delayby1ms
        bclr    LCD_CTRL, lcd_E + lcd_RS
        jsr         delayby1ms
        bset         LCD_CTRL, LCD_E
        ldaa    #%00100000
        staa         LCD_DAT
        jsr         delayby1ms
        bclr         LCD_CTRL, lcd_E
        
        end

open_lcd:
        bclr        lcd_CTRL,lcd_RS
        bclr        lcd_CTRL, lcd_E

        ldaa    #$00                 ;data command  to set lcd mode
        ldab    #$2C                 ;
        jsr     cmd2lcd

        ldaa    #$01                 ;data command to set lcd CharPitch
        ldab    #%10000111            ; 8horz, 8vert dots
        jsr     cmd2lcd

        ldaa    #$02 ;data command to set lcd NumOfChar/line
        ldab    #$04            ; num of chars on 1 line
        jsr     cmd2lcd

        ldaa    #$03 ;data command to set lcd TimeDivNum
        ldab    #$9F
        jsr     cmd2lcd

        ldaa    #$04 ;data command to set lcd Cursor Position
        ldab    #%00000111
        jsr     cmd2lcd

        ldaa    #$08 ;data command to set lcd Display Start (Lower)
        ldab    #$00
        jsr     cmd2lcd

        ldaa    #$09 ;data command to set lcd Dispplay Start (Upper)
        ldab    #$00
        jsr     cmd2lcd

        ldaa    #$0A ;data command to set lcd Cursor (Lower) Address
        ldab    #$00
        jsr     cmd2lcd

        ldaa    #$0B  ;data command to set lcd Cursor (Upper) Address
        ldab    #$00
        jsr     cmd2lcd


cmd2lcd:

        bclr    lcd_CTRL, lcd_RW
        bset    lcd_CTRL, lcd_RS
        bset    lcd_CTRL, lcd_E


        staa    lcd_DAT

        bclr    lcd_CTRL, lcd_E
        jsr     delayby1ms
        bclr    lcd_CTRL, lcd_RS


        bset    lcd_CTRL, lcd_E
        stab    lcd_DAT
        jsr     delayby1ms
        bclr    lcd_CTRL, lcd_E

        rts





delayby1ms:
        psha
        ldaa #10               ; delay 1 ms
        staa counter

d1:     ldy #6000            ; 6000 x 4 = 24,000 cycles = 1ms
d:      dey                  ; this instruction  takes 1 cycle
        bne d                ; this instruction  takes 3 cycles
        dec counter
        bne d1               ; not 5ms yet, delay again
Notes: the delayby1ms is actually a 10ms delay
Looking for additional LCD resources? Check out our LCD blog for the latest developments in LCD technology.
 
Last edited:
I made some changes that you can try. Also, I'm not sure if your init data might have problems, but try this change first to see whether it helps.
Code:
cmd2lcd:
        psha
[COLOR="DarkOrange"][B]        bclr    lcd_CTRL, lcd_RW[/B][/COLOR]
        bset    lcd_CTRL, lcd_RS   ;RS = 1 for command
        bset    lcd_CTRL, lcd_E
[COLOR="RoyalBlue"];****************************
; I dont understand this part, you should remove it
;       oraa    lcd_CTRL
;       jsr     delayby1ms
;       staa    lcd_CTRL
;****************************[/COLOR]
        pula
        staa    lcd_DAT
[COLOR="DarkOrange"][B]        jsr     delayby1ms[/B][/COLOR]
        
        bclr    lcd_CTRL, lcd_E
        jsr	delayby1ms
        bclr    lcd_CTRL, lcd_RS   ;RS = 0 for data

        bset    lcd_CTRL, lcd_E
        stab    lcd_DAT
        jsr delayby1ms
        bclr    lcd_CTRL, lcd_E
        rts
What is the clock speed of your cpu?
 

BrentK

New member
thanks for the quick response.

The change did not fix my problem however. I had my hopes up but realized soon after that my RW was already set to 0 when I cleared my port and it should never have changed.


As for the clock speed, trying to find it. I want to say that its 24MHz but I'm not to sure. Why do you ask?
 

BrentK

New member
well apparently I'm having some issues with something else. I'll post more info later

edit: turns out I made some big mistakes in my software.

Actually have my lcd kinda-sorta initialized
 
Last edited:
As for the clock speed, trying to find it. I want to say that its 24MHz but I'm not to sure. Why do you ask?
Just trying to get an idea of how fast your port writes would be if you didn't use delays. Since the minimum setup time is only 220 nS, you could probably just use a few NOP instructions instead of a counting loop for delays.

If you are still not getting results, you might try my init values. They DO work. This is an excerpt from my C code, so ignore the mixed syntax.
Code:
#define GR_MODE		0	; mode register
#define GR_PITCH	1	; character H & V pitch register
#define GR_HORIZ	2	; horiz chars or bytes register
#define GR_DUTY		3	; duty cycle register
#define GR_CURP		4	; cursor posn register
#define GR_STRTL	8	; display start addr L register
#define GR_STRTH	9	; display start addr H register
#define GR_CURAL	0xA	; cursor addr L register
#define GR_CURAH	0xB	; cursor addr H register
#define GR_WRITE	0xC	; write instruction

init_table:
		GR_MODE, 0x10,
		GR_PITCH, 0x77,
		GR_HORIZ, 19,
		GR_DUTY, 159,
		GR_CURP, 0,
		GR_STRTL, 0,
		GR_STRTH, 0,
		GR_CURAL, 0,
		GR_CURAH, 0,
		GR_MODE, 0x32	   ; graphic mode normally

;		GR_MODE, 0x30,	;character mode test
;		GR_WRITE, 0x44,      ; write two characters
;		GR_WRITE, 0x55;
 

BrentK

New member
My code is, in fact, doing something (See updated code in original post). However, each time I run it I get a different result on the screen.

some times it just goes all black, some times 3 lines will show up and other times it will show up with a bunch of characters and a cursor blinking (sometimes the characters will flash then disappear), etc.

I would love to try your code out, unfortunately I have no idea how to get a C program into my processor. Doing this in school and they're only teaching assembly
 
You don't have to put a C program into your processor. Just read the C code and extract the init values and put them into your assembly program. It should be plain what the init values are. You know that "0x" prefix is the same as "$" prefix, right?

In your startup code, you should stretch out the reset time:
Code:
        clr LCD_CTRL    ; Initialize everything in portk K to 0
        clr LCD_DAT
        [COLOR="Red"][B]jsr delay10ms     ; make reset pulse 10 mS long[/B][/COLOR]
        bset LCD_CTRL, lcd_RST ; set reset to be high
If your results are inconsistant, I suspect a timing problem, or noise on the E signal. Do you have the use of a scope to check your signal quality and timing? How long are the wires from the HC12 to the display?

As I look back to your first post, at the changes you added, I see some problems:
Code:
        ;trying to output a single character
        bset LCD_CTRL, lcd_RS
        [COLOR="Red"][B]jsr delayby1ms[/B][/COLOR]
        bset LCD_CTRL, lcd_E
        ldaa #$0C     ; the "write" command
        staa LCD_DAT
        jsr delayby1ms
[COLOR="Blue"]; when you clear both of these together, you are violating the 
; address hold time: 10 nS. Do E first, then do RS
        [B]bclr LCD_CTRL, lcd_E + lcd_RS[/B][/COLOR]
        jsr delayby1ms
        bset  LCD_CTRL, LCD_E
       [COLOR="Red"] ldaa  #%00100000    [B]; a space character, which is invisible[/B][/COLOR]
        staa  LCD_DAT
        jsr     delayby1ms
        bclr   LCD_CTRL, lcd_E
I also just noticed, since I mentioned timing problems, that you are probably violating the address setup time: 90 nS. So, you should have a 100 nS delay from whenever you change RS or RW to when you set E high.

If you feel like attaching your whole source file (not put in a code box), I can point out the places that need delays, and how long a delay.
 

BrentK

New member
If your results are inconsistant, I suspect a timing problem, or noise on the E signal. Do you have the use of a scope to check your signal quality and timing? How long are the wires from the HC12 to the display?
I did in fact have an oscilloscope to work with. The noise around E was very minimal, if even noticeable. The wires to to the display are anywhere from 6"-12".

I was also assuming that the problem lies within the timing somewhere as a triple checked all the connections and using the oscilloscope i did a little debugging to make sure it was sending the right signals.

Attached is my code with some of the changes you already suggested.

Thanks for pointing out that one violation btw and your help is very much appreciated.
 

Attachments

BrentK

New member
yay! I got it to initialize.

now for some questions. It seems that after all the setup is done, the display initially shoots out a bunch of garbage characters. Is that normal? I've been tinkering around with how to clear it and set the cursor position back to the original spot to no avail. I was able to clear it (just loop white space characters x amount of times) but not able to get it to return back to the position I want.

Any suggestions?

EDIT: Okay. I was thinking on the way home that maybe doing a RST wouldn't be a bad idea? But that all depends on how it actually works. When I reset it does it reset all the data as well? I did try this but had some problems with my code (surprise 'end' doesn't actually end the program).
 
Last edited:
... the display initially shoots out a bunch of garbage characters. Is that normal?
Yes, if you haven't cleared the display RAM.
... set the cursor position back to the original spot to no avail..
Code:
        ldaa    #$0A ;data command to set lcd Cursor (Lower) Address
        ldab    #$00
        jsr     cmd2lcd

        ldaa    #$0B  ;data command to set lcd Cursor (Upper) Address
        ldab    #$00
        jsr     cmd2lcd
You must do both commands to set cursor, even if one of the bytes has not changed.
I was thinking on the way home that maybe doing a RST wouldn't be a bad idea? But that all depends on how it actually works.
The data sheet explains what settings are made by the RST action. I don't think it clears the data RAM. But then you would have to reinitialize. Or maybe I don't understand what you mean... do a RST when?
surprise 'end' doesn't actually end the program
It should end the assembly process, leaving out everything after in the source file. At the end of your "main", just put a "jmp $" to make an infinite loop.
 

BrentK

New member
Well splendid! It actually works.

Sorry for not posting in awhile, but I was playing around with it and so forth.

I have a follow up question!

In the graphics mode, I'm trying to do some stuff, I can make it output pixels and so forth but I'm trying to figure out the 'Setting the cursor (lower/upper) address instructions/data'. I understand that it is meant to be a 16bit data input but I'm not entirely sure how it works. For example, i know that when i load it with all zeroes, it starts at the top left corner pixel. But when I try and change it (let's say to all 1's) what is supposed to happen? Is the cursor supposed to go to the bottom right corner pixel? An example of how it would theoretically work would be awesome.

The reason I'm asking is because I'm trying to accomplish an etch-a-sketch (ish) game where I want to output a single pixel (not a a string of 5 pixels[what it does for me now based on the data I pass in]). The idea is to display a single pixel, then based on some input, move to the next pixel beside/below/above that last pixel.

I did some playing around with the cursor setting and so forth and the best that I could achieve was something like this (where dots would be pixels, and the vertical gap is there)
.....
.....

I guess an alternative question would be is there a way to make the data output a single pixel at a time?
So one input would give "." and the next input would give ".." and so forth.
 
This display writes bytes horizontally, as you know. There are 20 bytes in each row (160/8). So your cursor address will be 0~19 for the top row, 20~39 for the 2nd row, 40~59 for the 3rd row, yada, yada. The addresses for the bottom row are 3180~3199.

There are three ways to write single pixels.

1. Maintain a 3200 byte buffer in your cpu memory that is a virtual image of the screen. Do your bit setting/clearing in this buffer, and then write the whole buffer to the screen. Assuming a 1 uS per byte write rate, the update would take 3.2 mS approx. Or, you could get sophisticated, and only update the bytes that have changed. I'm not sure if flicker on rapid updates would be a problem.

2. Address the byte to be modified on the screen, and then read the screen RAM into your cpu. Modify the byte to set/clear the bit to be changed. Re-address the byte on the screen (as the read action will auto-increment the cursor addr), and write the byte back to the screen. This method allows changing up to 8 pixels at once, and preserves the original content (the reason to do the read).

3. Address the byte to be modified on the screen, then use the bit set ($0F) or bit clear ($0E) instructions to modify the bit in question. Note that the cursor addr will auto-increment, so to do another bit in the same byte, you will need to set the cursor addr again. This method only changes one bit at a time.

Note that this display has a slow LCD response time of 200 mS, so updating rapidly would tend to blur the image, I think.

Too bad you are not willing to at least learn to read "C" language programs, as I have posted a small library of text (bitmap fonts) and graph routines for the CFAG160160 in the 3rd party software forum on this site. The routines include "plot a point" and "draw a line". If you knew how to read "C", you could just translate them into assembly language (compile by brain).
 

BrentK

New member
So I took your advice and went through some of the sample C code that is posted. Helped a little bit and gave me some ideas on what I wanted to do and how to accomplish it.

So here I am, I have my program that, based on some input (00, 01, 10, 11 [binary, call it A]) it should draw a pixel directly below the current pixel on the screen. So I made a loop that will draw the pixel at the desired location if the input A changes a value.

The program does work as intended, however I'm having some display problems. I know it draws a line but I can only get 1-6 pixels to show up on the screen before they disappear off the display. I can keep going through the loop to display pixels, but it doesn't come up on the display. But just wait, when I reset my program (completes a clear screen) the line that I drew shows up and gets erased (of course).

I'm not entirely sure where the problem lies. I'm thinking it might have something to do with my timing. Have you heard/encountered this problem before? Just wondering what your opinion is on the situation. I can post/attach my code if you would like to see it as it differs significantly from before.
 
I'm not clear on exactly what your symptoms are.
... I'm having some display problems. I know it draws a line but I can only get 1-6 pixels to show up on the screen before they disappear off the display.
When "they" disappear, are you referring to all the pixels or just the ones after the 1-6 that show up?
I'm thinking it might have something to do with my timing. Have you encountered this problem before?
I've never seen this problem before. Only one idea comes to mind: you are somehow sending a command to turn off the display (which is why I asked the question above).

If you attach your code, I will take a look at it.
 

BrentK

New member
I'm not clear on exactly what your symptoms are.When "they" disappear, are you referring to all the pixels or just the ones after the 1-6 that show up?I've never seen this problem before. Only one idea comes to mind: you are somehow sending a command to turn off the display (which is why I asked the question above).

If you attach your code, I will take a look at it.
The situation (re-worded - kinda for my reference. I'll probably be referring to this thread when I right up my project report): I start up my program, it clears the screen. Then it waits for the input to change. When the input changes it draws a pixel. When the input changes again, it draws another pixel. However, the screen will randomly just go blank after I change the input(everything disappears). When I re-run the program. It starts the clear algorithm, and I can see that my line is there before it gets erased

What your saying makes sense (the display turns off) but I'm not sure why it would turn off some times and not others. But i'll have a look through my code tomorrow to see if I can find the problem.
 
I'm assuming that you've positively ruled out any wiring errors. The next cause, especially for non-repeatable problems, is likely to be write timing. Since you didn't attach your code file, I can't comment further.
 

CF Tech

Administrator
Awesome! Please post some pics :)

OK, this is why cosmicvoid has superhero status in my book.

Glad you got it working.

Please feel free to post the code over in 3rd Party Software forum to help out the next fellow.
 

BrentK

New member
Something isn't working properly with my display.

The situation: i have it set to display 20bytes on a line (pass in #19 [n-1]).

When I use the following it should output something like "........"
Code:
output8pixels:

        bset         LCD_CTRL, lcd_RS        ; RS = 1 for cmd
        bset         LCD_CTRL, lcd_E
        ldaa         #$0C                        ;"write data" command
        staa         LCD_DAT
        jsr          delayby1ms                ; >220 nS (tDSW)
        bclr         LCD_CTRL, lcd_E
        ; >10 ns from E low to RS change (tAH)
        bclr         LCD_CTRL, lcd_RS        ; RS = 0 for data

        ; >90 nS from RS change to E high (tAS)
        nop

        ; allow data to come in
        bset         LCD_CTRL, LCD_E
        ldab         #$FF        ;should make every pixel high (on)
        stab         LCD_DAT
        ; delay>220 nS (tDSW)
        nop
        nop
        nop

        ;no more data
        bclr          LCD_CTRL, lcd_E
        jsr        delayby1ms
        rts
that doesn't actually happen. It outputs "......" (6pixels)

Am I assuming something wrong? I'm trying to figure out what i'm doing wrong. It seems that my Hp isn't set properly for some reason?
 
Top