AtMega 328PU and 20x4 LCD pfleury libraries

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

Hello guys...

 

It has been a while since my last time here!

 

Now, most of things have been forgotten but I pretend to get them back.

 

I'm trying to connect an HD44780 based 20x4 LCD to my AtMega328PU ucontroller and I'm using Peter Fleury's libraries and I can't remember how some of the lcd.h parameters are configured to my LCD module!

 

I'm talking particularly about this piece of code:

 

#ifndef LCD_LINES
#define LCD_LINES           2     /**< number of visible lines of the display */
#endif
#ifndef LCD_DISP_LENGTH
#define LCD_DISP_LENGTH    16     /**< visibles characters per line of the display */
#endif
#ifndef LCD_LINE_LENGTH
#define LCD_LINE_LENGTH  0x40     /**< internal line length of the display    */
#endif
#ifndef LCD_START_LINE1
#define LCD_START_LINE1  0x00     /**< DDRAM address of first char of line 1 */
#endif
#ifndef LCD_START_LINE2
#define LCD_START_LINE2  0x40     /**< DDRAM address of first char of line 2 */
#endif
#ifndef LCD_START_LINE3
#define LCD_START_LINE3  0x14     /**< DDRAM address of first char of line 3 */
#endif
#ifndef LCD_START_LINE4
#define LCD_START_LINE4  0x54     /**< DDRAM address of first char of line 4 */
#endif
#ifndef LCD_WRAP_LINES
#define LCD_WRAP_LINES      0     /**< 0: no wrap, 1: wrap at end of visibile line */
#endif

I'm not sure how to configure those lines for a 20x4 LCD.

I already tried to look for the addresses in the HD44780 datasheet but I can only find reference to 16x2 LCD addresses as it's stated in this document at page 12.

 

I hope I provided all information needed!

 

 

Edited;

Is it like this:

#ifndef LCD_LINES
#define LCD_LINES           4     /**< number of visible lines of the display */
#endif
#ifndef LCD_DISP_LENGTH
#define LCD_DISP_LENGTH    20     /**< visibles characters per line of the display */
#endif
#ifndef LCD_LINE_LENGTH
#define LCD_LINE_LENGTH  0x40     /**< internal line length of the display    */
#endif
#ifndef LCD_START_LINE1
#define LCD_START_LINE1  0x00     /**< DDRAM address of first char of line 1 */
#endif
#ifndef LCD_START_LINE2
#define LCD_START_LINE2  0x28     /**< DDRAM address of first char of line 2 */
#endif
#ifndef LCD_START_LINE3
#define LCD_START_LINE3  0x14     /**< DDRAM address of first char of line 3 */
#endif
#ifndef LCD_START_LINE4
#define LCD_START_LINE4  0x3C     /**< DDRAM address of first char of line 4 */
#endif
#ifndef LCD_WRAP_LINES
#define LCD_WRAP_LINES      0     /**< 0: no wrap, 1: wrap at end of visibile line */
#endif

 

Edit 2;

This topic has a solution.
Last Edited: Fri. Jul 21, 2017 - 09:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A pretty easy way to debug ram locations is to write a big continuous string of data to the display.

A letter followed by 3 digits is easily recognisable and debuggable.

A000A001A002A003A004...

You will overflow the whole data buffer and it will wrap around so when you do not write too fast (10Hz or so) you can even determine approximate addresses from the order in which you see your display filled with data.

 

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

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

For a standard 4x20 LCD in the .h file modify these two lines:


/**
 *  @name  Definitions for Display Size
 *  Change these definitions to adapt setting to your display
 */
#define LCD_LINES           2     /**< number of visible lines of the display */
#define LCD_DISP_LENGTH    16     /**< visibles characters per line of the display */

 

To this:

 


/**
 *  @name  Definitions for Display Size
 *  Change these definitions to adapt setting to your display
 */
#define LCD_LINES           4     /**< number of visible lines of the display */
#define LCD_DISP_LENGTH    20     /**< visibles characters per line of the display */

 

 

And also in the .h  file these lines here:

#define LCD_PORT         PORTA        /**< port for the LCD lines   */
#define LCD_DATA0_PORT   LCD_PORT     /**< port for 4bit data bit 0 */
#define LCD_DATA1_PORT   LCD_PORT     /**< port for 4bit data bit 1 */
#define LCD_DATA2_PORT   LCD_PORT     /**< port for 4bit data bit 2 */
#define LCD_DATA3_PORT   LCD_PORT     /**< port for 4bit data bit 3 */
#define LCD_DATA0_PIN    0            /**< pin for 4bit data bit 0  */
#define LCD_DATA1_PIN    1            /**< pin for 4bit data bit 1  */
#define LCD_DATA2_PIN    2            /**< pin for 4bit data bit 2  */
#define LCD_DATA3_PIN    3            /**< pin for 4bit data bit 3  */
#define LCD_RS_PORT      LCD_PORT     /**< port for RS line         */
#define LCD_RS_PIN       4            /**< pin  for RS line         */
#define LCD_RW_PORT      LCD_PORT     /**< port for RW line         */
#define LCD_RW_PIN       5            /**< pin  for RW line         */
#define LCD_E_PORT       LCD_PORT     /**< port for Enable line     */
#define LCD_E_PIN        6            /**< pin  for Enable line     */

is where you set the port you will connect the LCD to, and what port pins are to do what.

 

All the other addressing and such you do not need to do.  as long as you haven't touched anything the library does it for you.

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

Last Edited: Fri. Jul 21, 2017 - 12:08 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, I recall now somethings.

 

But I find it weird that the default lcd.h has a PORTA defined to LCD_PORT and AtMega328PU does not have a PORTA. I'll assume that lcd.h file was made for some other ucontroller that possibly had a PORTA. I'll change it to one of B, C, or D ports!

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

I'm confused right now! I need to connect 7 wires from LCD. PORTB has pin PB6 and PB7 reserved to XTAL and this port goes from PB0 to PB7. PORTC has PB6 reserved to reset needed to load firmware onto the ucontroller and this port goes fromPC0 to PC6. PORTD has PD0 and PD1 reserved to Rx and Tx and this port goes from PD0 to PD7. So where am I going to connect 7 wires from the LCD?

 

 

Edited;

I got it... Ignore this!

Last Edited: Fri. Jul 21, 2017 - 06:57 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
But I find it weird that the default lcd.h has a PORTA defined to LCD_PORT and AtMega328PU does not have a PORTA.

 

So YOU CHANGE the port to whatever you want.  THe library does not care.

 

PsySc0rpi0n wrote:
So where am I going to connect 7 wires from the LCD?

Easy.  Break it up between two ports.

 

Look:

#define LCD_PORT         PORTA        /**< port for the LCD lines   */
#define LCD_DATA0_PORT   LCD_PORT     /**< port for 4bit data bit 0 */
#define LCD_DATA1_PORT   LCD_PORT     /**< port for 4bit data bit 1 */
#define LCD_DATA2_PORT   LCD_PORT     /**< port for 4bit data bit 2 */
#define LCD_DATA3_PORT   LCD_PORT     /**< port for 4bit data bit 3 */

and:

#define LCD_DATA0_PIN    0            /**< pin for 4bit data bit 0  */
#define LCD_DATA1_PIN    1            /**< pin for 4bit data bit 1  */
#define LCD_DATA2_PIN    2            /**< pin for 4bit data bit 2  */
#define LCD_DATA3_PIN    3            /**< pin for 4bit data bit 3  */
#define LCD_RS_PORT      LCD_PORT     /**< port for RS line         */
#define LCD_RS_PIN       4            /**< pin  for RS line         */
#define LCD_RW_PORT      LCD_PORT     /**< port for RW line         */
#define LCD_RW_PIN       5            /**< pin  for RW line         */
#define LCD_E_PORT       LCD_PORT     /**< port for Enable line     */
#define LCD_E_PIN        6            /**< pin  for Enable line     */

 

If you simply change the first part:

#define LCD_PORT         PORTB        /**< port for the LCD lines   */
#define LCD_DATA0_PORT   PORTC    /**< port for 4bit data bit 0 */
#define LCD_DATA1_PORT   PORTC     /**< port for 4bit data bit 1 */
#define LCD_DATA2_PORT   PORTC    /**< port for 4bit data bit 2 */
#define LCD_DATA3_PORT   PORTC     /**< port for 4bit data bit 3 */

 

And this to the second part:

#define LCD_DATA0_PIN    0            /**< pin for 4bit data bit 0  */
#define LCD_DATA1_PIN    1            /**< pin for 4bit data bit 1  */
#define LCD_DATA2_PIN    2            /**< pin for 4bit data bit 2  */
#define LCD_DATA3_PIN    3            /**< pin for 4bit data bit 3  */
#define LCD_RS_PORT      LCD_PORT     /**< port for RS line         */
#define LCD_RS_PIN       0            /**< pin  for RS line         */
#define LCD_RW_PORT      LCD_PORT     /**< port for RW line         */
#define LCD_RW_PIN       1            /**< pin  for RW line         */
#define LCD_E_PORT       LCD_PORT     /**< port for Enable line     */
#define LCD_E_PIN        2            /**< pin  for Enable line     */

 

Now the LCD CONTROL lines are on PORTB pins 0, 1, and 2.

 

The LCD DATA lines are on PORTC Pins 0, 1, 2, and 3.

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

@jgmdesign, done! Now I just need to recall the 3 commands to compile, convert to intel hex and upload the code to the ucontroller! Anyone has those commands? I deleted a file accidentally where I kept the commands!

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

PsySc0rpi0n wrote:
Anyone has those commands?

Not unless you tell us

- What toolchain (i.e compiler etc) you are using, and

- What operating system you are using, and

- What programmer you have, and

- What programming software you used the last time (if possible to recall)

 

Without any of that information there will be hundreds of combinations of the above things. We can't list them all..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

PsySc0rpi0n wrote:

@jgmdesign, done! Now I just need to recall the 3 commands to compile, convert to intel hex and upload the code to the ucontroller! Anyone has those commands? I deleted a file accidentally where I kept the commands!

 

In the beginning,  God invented AVR Studio 4 (AS4) and it was good.

We now have Atmel Studio 7.0 (AS7) and it works too.

 

If you are on Linux,  there is probably a program called MFile that will create an appropriate Makefile for your project.

 

Hand-crafting commands is unwise.    Let the IDE or MFile do this for you.

 

David.

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

In the beginning,  God invented AVR Studio 4 (AS4) and it was good.

You young kids!! I started with AS3 which was just out and I still have AS2.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

@JohanEkdahl, I'm sorry I missed that information!

 

I'm using Debian 9, 64bit and AVR Tool Chain, avr-gcc-4.9.2, avrdude 6.3! I don't remember very well what "programmer" was since I make a mess with those names in my mind because I also have used Arduino in the past. I already have to use Arduino to burn, I think, a bootloader to my AtMega328's and I remember I used something called a programmer like ISP or so! But I also remember to see something like stk500 when loading firmware into AtMega328P, so I'm a little confused!

 

Edited;

Ok, I break the first step... Get along with avr-gcc-4.9.2 first option.

I was using:

 

avr-gcc-4.9.2 -mmcpu=atmega328p lcd.c -o lcd.o

when I should use

avr-gcc-4.9.2 -mmcu=atmega328p lcd.c -o lcd.o

 

but now I get the following errors that I need help with:

 

~/avr_projects/Peter_Fleury_LCD$ avr-gcc-4.9.2 -mmcu=atmega328p lcd.c -o lcd.o
In file included from lcd.c:15:0:
/usr/lib/avr/include/util/delay.h:95:3: warning: #warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed" [-Wcpp]
 # warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"
   ^
/tmp/ccd1kNY1.o: In function `main':
lcd.c:(.text+0x18c): undefined reference to `lcd_init'
lcd.c:(.text+0x190): undefined reference to `lcd_clrscr'
lcd.c:(.text+0x198): undefined reference to `lcd_puts'
lcd.c:(.text+0x1a0): undefined reference to `lcd_puts'
lcd.c:(.text+0x1a8): undefined reference to `lcd_gotoxy'
lcd.c:(.text+0x1ae): undefined reference to `lcd_putc'
lcd.c:(.text+0x1b8): undefined reference to `lcd_command'
lcd.c:(.text+0x1c0): undefined reference to `lcd_puts'
lcd.c:(.text+0x1c8): undefined reference to `lcd_clrscr'
lcd.c:(.text+0x1d0): undefined reference to `lcd_puts_p'
lcd.c:(.text+0x1d8): undefined reference to `lcd_puts_p'
lcd.c:(.text+0x1de): undefined reference to `lcd_command'
lcd.c:(.text+0x1e8): undefined reference to `lcd_command'
lcd.c:(.text+0x1ec): undefined reference to `lcd_clrscr'
lcd.c:(.text+0x208): undefined reference to `lcd_puts'
lcd.c:(.text+0x210): undefined reference to `lcd_clrscr'
lcd.c:(.text+0x218): undefined reference to `lcd_puts'
lcd.c:(.text+0x21e): undefined reference to `lcd_command'
lcd.c:(.text+0x240): undefined reference to `lcd_data'
lcd.c:(.text+0x254): undefined reference to `lcd_gotoxy'
lcd.c:(.text+0x25a): undefined reference to `lcd_putc'
lcd.c:(.text+0x260): undefined reference to `lcd_putc'
collect2: error: ld returned 1 exit status

The only change I made to lcd.c Peter Fleury file was to add

#define F_CPU 16000000UL

before line

#include <util/delay.h>

like this:

/*************************************************************************
Title:         Testing output to a HD44780 based LCD display.
Author:        Peter Fleury  <pfleury@gmx.ch>  http://tinyurl.com/peterfleury
Modded Author: PsySc0rpi0n <psysc0rpi0n@gmail.com>
File:          $Id: test_lcd.c,v 1.8 2015/01/31 18:04:08 peter Exp $
Software:      AVR-GCC 4.x
Hardware:      HD44780 compatible LCD text display
               AVR with external SRAM interface if memory-mapped LCD interface is used
               any AVR with 7 free I/O pins if 4-bit IO port mode is used
**************************************************************************/
#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#include "lcd.h"

 

Last Edited: Fri. Jul 21, 2017 - 10:48 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I got it again... I was missing lcd.c content and pasting test_lcd.c content into lcd.c...

 

Edited;

 

Well the errors still there! :(

Last Edited: Sat. Jul 22, 2017 - 08:39 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You need to read up on the compiler command line, and how to compile multiple file projects.

 

In order to get the warning about optimization out of the way, specify an optimization level like -O3 or (preferrably?) -Os.

 

For the long list of "undefined reference", there is a "usual suspect" but I can not confirm this. It seems you have not posted the command you use to compile main.c. Show the command you use to compile main.c!

 

(I am also missing a "undefined reference to main" error that is to be expected using the compile command for lcd.c that you have. If in doubt, rather post a little to much of build output than risk cutting away important info!)

 


 

There are a lot more required or recommended options to give at the gcc command line. I suggest you avoid doing this all by hand  and instead use GNU Make and a makefile to get your build done. Now, makefiles are not so easy to write for a beginner, but luckily there is a utility called Mfile that will help you with this. Get it here: http://www.sax.de/~joerg/mfile/

 

Whaqt you do, is you start this utility and then use some menu options to tell what source files you have, what optimization level you what etc and then save the resulting makefile to the same directory where you have your source files. Then, on a command line, in that directory, you simply type "make" and the build will happen. If your code is not correct then you will still get build errors, but not due to a faulty build process. AND that makefile will create the hex file for you too! 

 

I have attached a makefile for a project with two source files named main.c and lcd.c, for an ATmega328, optimization level -Os. You might be able to use that..

Attachment(s): 

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Sat. Jul 22, 2017 - 08:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
I got it again... I was missing lcd.c content and pasting test_lcd.c content into lcd.c...   Edited;   Well the errors still there! :(

You're very confusing now.

 

Do this:

1. Clear/reset your terminal window.

2. Issue the commands you use to compile your files.

3. Copy the commands and their output, the complet ecommands and the entire output, and pate it in a post here.

 


 

The normal way of building a project with multiple source files is to compile each source file separately, and only compile it (you need to be specific about that, or else the cimpiler will try to compile and link in one go). After that you issue a final command to link together the results of the earlier compilations. Something like this:

 

# Compiling...

avr-gcc -c lcd.c -o lcd.o
avr-gcc -c main.c -o main.o

# Linking...
avr-gcc main.o lcd.o -o theProgram.elf

Note that the above is not complete, missing a lot of options (e.g. optimization) etc. It is only an illustration of the "flow of the process". After the above you need to make a .hex file based on he .elf file. For this you use the objcopy command, something like this (again an example, not complete)

 

objcopy -o ihex -R theProgram.elf theProgram.hex

So you see this is not a trivial thing, with just a few short'n'simple commands involved.

 

really recommend the MFile utility to get you started. It will let you focus on the code rather than fighting with poor build processes.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Ok, I know I can get lost very easily. Anyway, I used the avr-libc default Makefile from here and looks like it's working!

 

So, now I just need to recall/find/google the correct avrdude command to send the firmware to the AtMega328PU ucontroller and check if the code is working!

 

The Makefile I used was this:

 

PRG            = test_lcd
OBJ            = test_lcd.o lcd.c
#MCU_TARGET     = at90s2313
#MCU_TARGET     = at90s2333
#MCU_TARGET     = at90s4414
#MCU_TARGET     = at90s4433
#MCU_TARGET     = at90s4434
#MCU_TARGET     = at90s8515
#MCU_TARGET     = at90s8535
#MCU_TARGET     = atmega128
#MCU_TARGET     = atmega1280
#MCU_TARGET     = atmega1281
#MCU_TARGET     = atmega1284p
#MCU_TARGET     = atmega16
#MCU_TARGET     = atmega163
#MCU_TARGET     = atmega164p
#MCU_TARGET     = atmega165
#MCU_TARGET     = atmega165p
#MCU_TARGET     = atmega168
#MCU_TARGET     = atmega169
#MCU_TARGET     = atmega169p
#MCU_TARGET     = atmega2560
#MCU_TARGET     = atmega2561
#MCU_TARGET     = atmega32
#MCU_TARGET     = atmega324p
#MCU_TARGET     = atmega325
#MCU_TARGET     = atmega3250
#MCU_TARGET     = atmega329
#MCU_TARGET     = atmega3290
#MCU_TARGET     = atmega32u4
#MCU_TARGET     = atmega48
#MCU_TARGET     = atmega64
#MCU_TARGET     = atmega640
#MCU_TARGET     = atmega644
#MCU_TARGET     = atmega644p
#MCU_TARGET     = atmega645
#MCU_TARGET     = atmega6450
#MCU_TARGET     = atmega649
#MCU_TARGET     = atmega6490
#MCU_TARGET     = atmega8
#MCU_TARGET     = atmega8515
#MCU_TARGET     = atmega8535
#MCU_TARGET     = atmega88
#MCU_TARGET     = attiny2313
#MCU_TARGET     = attiny24
#MCU_TARGET     = attiny25
#MCU_TARGET     = attiny26
#MCU_TARGET     = attiny261
#MCU_TARGET     = attiny44
#MCU_TARGET     = attiny45
#MCU_TARGET     = attiny461
#MCU_TARGET     = attiny84
#MCU_TARGET     = attiny85
#MCU_TARGET     = attiny861
MCU_TARGET		= atmega328p

OPTIMIZE       = -O2
DEFS           =
LIBS           =
# You should not have to change anything below here.
CC             = avr-gcc
# Override is only needed by avr-lib build system.
override CFLAGS        = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) -DF_CPU=16000000UL
override LDFLAGS       = -Wl,-Map,$(PRG).map
OBJCOPY        = avr-objcopy
OBJDUMP        = avr-objdump
all: $(PRG).elf lst text eeprom
$(PRG).elf: $(OBJ)
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
# dependency:
lcd.o: lcd.c lcd.h
test_lcd.o: test_lcd.c lcd.h
clean:
	rm -rf *.o $(PRG).elf *.eps *.png *.pdf *.bak
	rm -rf *.lst *.map $(EXTRA_CLEAN_FILES)
lst:  $(PRG).lst
%.lst: %.elf
	$(OBJDUMP) -h -S $< > $@
# Rules for building the .text rom images
text: hex bin srec
hex:  $(PRG).hex
bin:  $(PRG).bin
srec: $(PRG).srec
%.hex: %.elf
	$(OBJCOPY) -j .text -j .data -O ihex $< $@
%.srec: %.elf
	$(OBJCOPY) -j .text -j .data -O srec $< $@
%.bin: %.elf
	$(OBJCOPY) -j .text -j .data -O binary $< $@
# Rules for building the .eeprom rom images
eeprom: ehex ebin esrec
ehex:  $(PRG)_eeprom.hex
ebin:  $(PRG)_eeprom.bin
esrec: $(PRG)_eeprom.srec
%_eeprom.hex: %.elf
	$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ \
	|| { echo empty $@ not generated; exit 0; }
%_eeprom.srec: %.elf
	$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O srec $< $@ \
	|| { echo empty $@ not generated; exit 0; }
%_eeprom.bin: %.elf
	$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O binary $< $@ \
	|| { echo empty $@ not generated; exit 0; }
# Every thing below here is used by avr-libc's build system and can be ignored
# by the casual user.
FIG2DEV                 = fig2dev
EXTRA_CLEAN_FILES       = *.hex *.bin *.srec
dox: eps png pdf
eps: $(PRG).eps
png: $(PRG).png
pdf: $(PRG).pdf
%.eps: %.fig
	$(FIG2DEV) -L eps $< $@
%.pdf: %.fig
	$(FIG2DEV) -L pdf $< $@
%.png: %.fig
	$(FIG2DEV) -L png $< $@

 

Now, I'll try to figure out the avrdude command!

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

I'm using the following command:

avrdude -c stk500v2 -p m328p -P /dev/ttyUSB0 -U flash:w:test_lcd.hex:i -vvvv

but it can't contact the uController!

 

I get this:

 

avrdude: Version 6.3, compiled on Oct  2 2016 at 23:15:04
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "/usr/local/etc/avrdude.conf"
         User configuration file is "/home/narayan/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/ttyUSB0
         Using Programmer              : stk500v2
avrdude: Send: . [1b] . [01] . [00] . [01] . [0e] . [01] . [14]
avrdude: ser_recv(): programmer is not responding
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: Send: . [1b] . [01] . [00] . [01] . [0e] . [01] . [14]
avrdude: ser_recv(): programmer is not responding
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: Send: . [1b] . [01] . [00] . [01] . [0e] . [01] . [14]
avrdude: ser_recv(): programmer is not responding
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: Send: . [1b] . [01] . [00] . [01] . [0e] . [01] . [14]
avrdude: ser_recv(): programmer is not responding
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: Send: . [1b] . [01] . [00] . [01] . [0e] . [01] . [14]
avrdude: ser_recv(): programmer is not responding
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: Send: . [1b] . [01] . [00] . [01] . [0e] . [01] . [14]
avrdude: ser_recv(): programmer is not responding
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_getsync(): timeout communicating with programmer
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : STK500V2
         Description     : Atmel STK500 Version 2.x firmware
         Programmer Model: Unknown
avrdude: Send: . [1b] . [01] . [00] . [02] . [0e] . [03] . [90] . [85]
avrdude: ser_recv(): programmer is not responding
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: Send: . [1b] . [01] . [00] . [01] . [0e] . [01] . [14]
avrdude: ser_recv(): programmer is not responding
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: Send: . [1b] . [01] . [00] . [01] . [0e] . [01] . [14]
^C

 

Wasn't there an option that would show us the voltage that the uController was at? My scope measures 4.80V from rail-to-rail of my breadboard.

 

 

 

 

 

And this is E pin activity on a reset button push

Last Edited: Sat. Jul 22, 2017 - 07:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
OBJ = test_lcd.o lcd.c

Are you sure?

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

Ok, everything is working now!

It was a bad reset circuit wiring! :(

 

Anyway, I'm now going to try to recall how to use Peter Fleury's libraries! Any questions I have, I'll post them here!

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

Ok, I've sorted everything out electronically speaking!

 

Now I'm just trying to understand how to use Peter's libraries and I'm trying to make a simple raster in the LCD using asteriscs. I'm not sure if "raster" is the best wording choice but I'll explain what I want to do.

 

I'm just trying to print '*'s one by one in each position of the LCD until the LCD is filled with them. Then I clear the screen, and start all over again!

 

But this is what is happening:

Video link

 

Code:

#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "lcd.h"

int main(void){
   uint8_t xx = 0, yy = 0;

   lcd_init(LCD_DISP_ON_CURSOR);
   lcd_clrscr();

   for(;;){
      if(xx == 20 && yy == 4){
         lcd_clrscr();
         xx = 0, yy = 0;
      }
      if(xx == 20){
         yy++, xx = 0;
      }
      lcd_gotoxy(xx++, yy);
      lcd_putc('*');
      _delay_ms(125);
   }
}

 

Settings in lcd.h to a 20x4 LCD

#ifndef LCD_LINES
#define LCD_LINES           4     /**< number of visible lines of the display */
#endif
#ifndef LCD_DISP_LENGTH
#define LCD_DISP_LENGTH    20     /**< visibles characters per line of the display */
#endif
#ifndef LCD_LINE_LENGTH
#define LCD_LINE_LENGTH  0x40     /**< internal line length of the display    */
#endif
#ifndef LCD_START_LINE1
#define LCD_START_LINE1  0x00     /**< DDRAM address of first char of line 1 */
#endif
#ifndef LCD_START_LINE2
#define LCD_START_LINE2  0x40     /**< DDRAM address of first char of line 2 */
#endif
#ifndef LCD_START_LINE3
#define LCD_START_LINE3  0x14     /**< DDRAM address of first char of line 3 */
#endif
#ifndef LCD_START_LINE4
#define LCD_START_LINE4  0x54     /**< DDRAM address of first char of line 4 */
#endif
#ifndef LCD_WRAP_LINES
#define LCD_WRAP_LINES      0     /**< 0: no wrap, 1: wrap at end of visibile line */
#endif

 

So, just need help to fix those minor bugs in the video!

Thanks

Last Edited: Tue. Jul 25, 2017 - 09:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is pretty close, isn't it?

 

I'd leave the cursor off in the final animation, but suit yourself.

 

Examine your yy logic.  Don't you want your test when yy == 3 ?

 

Next you can try a simple loop outputting 80 asterisks after a clear screen.  The driver should do the line wrapping for you.

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

theusch wrote:

It is pretty close, isn't it?

 

I'd leave the cursor off in the final animation, but suit yourself.

 

Examine your yy logic.  Don't you want your test when yy == 3 ?

 

Next you can try a simple loop outputting 80 asterisks after a clear screen.  The driver should do the line wrapping for you.

 

 

 

Oh yes... I changed xx == 21 to xx == 20 and forgot to do the same to yy... About the cursor, maybe you're correct too! heheh

Thanks

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

I'm watching that video standing on my head. It hurts.. ;-)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

JohanEkdahl wrote:

I'm watching that video standing on my head. It hurts.. ;-)

 

I posted the link but it is gone!... Trying again:

 

Video

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

Ok, I'll byte, what are you having issues with understanding Mr. Fleury's code?  It is very well commented right out of the box.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

jgmdesign wrote:

Ok, I'll byte, what are you having issues with understanding Mr. Fleury's code?  It is very well commented right out of the box.

 

JIm

 

I'm still exploring!

 

I have tried to make a raster and it's done!

Now I'm trying to create and use CGRAM Custom chars! I think in Peter's page there is no example on how to use functions or print those custom chars! This is my next task!

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

Just to say that "rasterization" is probably the wrong term when a character LCD rather than a GLCD is being used.

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

PsySc0rpi0n wrote:
I think in Peter's page there is no example on how to use [...]

When you downloaded the "library" from Peters site, it came with an example. Look in test_lcd.c. It defines custom characters and prints.

 

BTW, that test_lcd.c should have been the first program you tried..

 

PsySc0rpi0n wrote:
I think in Peter's page there is no example on how to [...] print those custom chars!

Just print any characer 0 .. 7. E.g.:

lcd_putc(4);  // Prints the fifth character defined in CGRAM

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Thu. Jul 27, 2017 - 10:09 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Every time I read a thread about HD44780 and custom characters my first thought is "did they make a mistake by not selecting a GLCD?" cheeky

 

(that "only 8 definable" is often going to bite one in the posterior!)

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

clawson wrote:

Just to say that "rasterization" is probably the wrong term when a character LCD rather than a GLCD is being used.

 

I just used that word because it is a simple '*' filling the LCD one at a time... Anyway, I got your point!

 

JohanEkdahl wrote:

PsySc0rpi0n wrote:

I think in Peter's page there is no example on how to use [...]

 

When you downloaded the "library" from Peters site, it came with an example. Look in test_lcd.c. It defines custom characters and prints.

 

BTW, that test_lcd.c should have been the first program you tried..

 

 

PsySc0rpi0n wrote:

I think in Peter's page there is no example on how to [...] print those custom chars!

 

Just print any characer 0 .. 7. E.g.:

lcd_putc(4);  // Prints the fifth character defined in CGRAM

 

There is something I'm not familiar with in Peter's code

 

How do we store the custom chars in CGRAM?

I know it's done by these lines, but don't know how!

 

lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */
      for(i=0; i<16; i++){
         lcd_data(pgm_read_byte_near(&copyRightChar[i]));
      }

 

I don't know exactly what that pgm_.... function is doing and how it stores the chars in CGRAM.

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

There is something I'm not familiar with in Peter's code

 

How do we store the custom chars in CGRAM?

I know it's done by these lines, but don't know how!

 

lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */
      for(i=0; i<16; i++){
         lcd_data(pgm_read_byte_near(&copyRightChar[i]));
      }

 

I don't know exactly what that pgm_.... function is doing and how it stores the chars in CGRAM.

 

You need to take this on in a structured way. What are the unknowns? Well, probably..

 

First:  The pgm_read_byte_near( ...) function. Do an internet search for that and you will soon find that it is a function to read data out of flash (rather than RAM) of the AVR. You will fins that it is a part of the avrlibc library - the support library for your compiler. You can the go to the avrlibc documentation, and you will find more info on it here: http://www.nongnu.org/avr-libc/u...

 

Second: A parameter to pgm_read_byte_near() is 

&copyRightChar[i]

so look in the source code for where copyRightChar is defined. It looks like this:

 

static const PROGMEM unsigned char copyRightChar[] =
{
	0x07, 0x08, 0x13, 0x14, 0x14, 0x13, 0x08, 0x07,
	0x00, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x00
};

Once again, PROGMEM is something that helps to store data in flash rather than RAM, so again look in the avrlibc documentation linked to above.

 

Now for the data. Let's translate those values in there to binary. 0x07 is binary 00000111, 0x08 is 00001000 and so on. Taking the whole first line (forming one user defined character) and placing each binary byte on its own line, we have

00000111
00001000
00010011
00010100
00010100
00010011
00001000
00000111

Doesn't make much sense yet. Let's continue! Well place the bytes of the second line to the right of the bytes of the first line:

 

00000111 00000000
00001000 00001010
00010011 00001000
00010100 00001000
00010100 00001000
00010011 00001000
00001000 00001010
00000111 00000000

A little hard to read. Let's reform that, substituting  * where we have a 1 and a blank where we have a 0.

     ***         
    *       *  
   *  **     *   
   * *       *   
   * *       *   
   *  **     *   
    *       *    
     ***         

Do you see a, somewhat ill formed, copyright sign ( © )? The space column between th left and right part is somewhat disturbing. Peter has chosen to use two character cells for a copyright sign and there will always be a blank column between two character cells on an 44780-base LCD display. He could have opted for a copyright sign taking up only one character cell, e.g. 

 

  ****
 *    *
*  **  *
* *    *
* *    *
*  **  *
 *    *
  ****

but that is not what he is doing, so to stay with his example let's leave that one-character-cell-copyright-sign for now.

 

So, the big picture is: To define a custom character you set up a "bitmap" defining which pixels in the charater cell should be set and which should be clear.

 

Peter has opted to store this in flash, which complicates his example a bit, but do understand that this has nothing do do with the defining of a custom character as such. He's just preserving precious RAM, sacrificing less precious flash memory.

 

So the loop  you pointed out reads the bitmap, byte by byte, out of flash and calls lcd_data() with the byte ass parameter. The lcd_data() function is a function in Peters librry so you can go analyze it on your own.

 

Also note that the call to 

lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */

says that what follows is the first spacial character of the eight that the 44780 can handle. Remember that each character is defined by 8 bytes. This means that the second special character is defined in the eight bytes starting at _BV(LCD_CGRAM) + 8. In general, to define special character n  you need to 

lcd_command(_BV(LCD_CGRAM) + n * 8);  /* set CG RAM to define spacial character n */

 

You'll have enough to investigate now with this help, I believe. Remember to try to sort out any detail you don't know about by searching, reading documentation  etc. Then try to put it together to see the bigger picture.

 

This document is invaluable for understanding the controller chip on your display: https://www.sparkfun.com/datashe... . Download it and keep it close to you when working with the 44780. It is technically "dense" but holds information about how defining a special character works, from the perspective of the 44780 LCD controller.

 

If you want to get rid of the complication of PROGMEM and pgm_read_byte... to begin with, change Peters example so that you have

 

static const unsigned char copyRightChar[] = // "PROGMEM" removed
{
	0x07, 0x08, 0x13, 0x14, 0x14, 0x13, 0x08, 0x07,
	0x00, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x00
};



    .
    .
    .
    
       lcd_command(_BV(LCD_CGRAM));
       for(i=0; i<16; i++)
       {
           lcd_data(&copyRightChar[i]);   // pgm_read_byte_near( ... ) removed
       }

 

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Thank you a lot for the thorough explanation.

 

I know about the custom chars generation. My questions were about how to store each custom char in CGRAM and then how to print them on the LCD! Which commands do we need to use to accomplish these two tasks!

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

His manual:

 

http://homepage.hispeed.ch/peter...

 

says you send commands to the LCD with lcd_command() and that there is LCD_CGRAM defined to set the address for writing to CG locations. In fact that is exactly what Johan showed above:

lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */
      for(i=0; i<16; i++){
         lcd_data(pgm_read_byte_near(&copyRightChar[i]));
      }

So you start by issuing the LCD_CGRAM command (with optional offset if you aren't going to set all characters from address 0) then you keep calling lcd_data() to send the bytes that define the characters.

 

The characters you define are 0 .. 7. So just as you might use lcd_putc(0x41) or lcd_putc('A') to print an 'A' you use lcd_putc(3) to print the 4th user defined character.

 

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

PsySc0rpi0n wrote:
My questions were about how to store each custom char in CGRAM and then how to print them on the LCD! Which commands do we need to use to accomplish these two tasks!

Should I give up? Re storing in CGRAM, this is exactly what I pointed to in Peters test program. It does exactly that.

 

To be explicit, this: 

lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */
      for(i=0; i<16; i++){
         lcd_data(pgm_read_byte_near(&copyRightChar[i]));
      }

Re how to then print them this is also done in Peters test program:

 

       /* display user defined (c), built using two user defined chars */
       lcd_putc(0);
       lcd_putc(1);

I can't help to think that the comment sort of reveals that this  is the place where the characters are printed out..

 

Suggest you read through the whole example program. It's not more than 167 lines. Then read it again..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Ok guys... I read it and tried it and it's not working!

 

This is what I have!

#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "lcd.h"

int main(void){
   const unsigned char customChar[8] = {
      0x0F,
	   0x10,
	   0x0A,
	   0x0F,
	   0x0A,
	   0x08,
	   0x10,
	   0x0F
   };

   lcd_init(LCD_DISP_ON);
   lcd_clrscr();

   lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */
   for(int i = 0; i < 8; i++){
      lcd_data(pgm_read_byte_near(&customChar[i]));
   }

   for(;;){
      lcd_gotoxy(0, 9);
      lcd_putc(0);
      _delay_ms(500);
   }
}

I used Peter's functions and only changed the first for loop exit condition from "i < 16" to "i < 8".

 

Then used the second loop just in the same way. Tried to set the position where I wanted to print the char and then I tried to print customChar at position 0 of CGRAM... It just printed a filled char in first position of last line of LCD, like in (0, 3) or column 0, line 3. So, the code is not working and I tried to the just like what is in Peter example!

 

 

Edited;

 

I spotted an error that is the coordinate order! It should be 9, 0 instead! But I didn't want to use that PROGMEM and that weird function and it only works if I use the static const PROGMEM and that weird function!

 

Isn't there any other way?

Last Edited: Fri. Jul 28, 2017 - 07:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not a GCC guru, but what makes you think "const" will put customChar into flash?

 

That was gone into in #30.  Your code managed to combine two approaches.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

As Lee says, your bitmap for the character is not in flash. You removed the PROGMEM as I suggested.

But then you should not try to read the bitmap out of flash!

 

Change

      lcd_data(pgm_read_byte_near(&customChar[i]));

to 

      lcd_data(&customChar[i]);

as I said in #30.

 

Those two changes go together.

EITHER have bitmap in flash (PROGMEM) and read out of flash (pgm_read_byte...),

 OR have bitmap in RAM (no PROGMEM) and read out of RAM (no pgm_read_byte...).

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Fri. Jul 28, 2017 - 07:53 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One & too many ;-)

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

theusch wrote:

I'm not a GCC guru, but what makes you think "const" will put customChar into flash?

 

That was gone into in #30.  Your code managed to combine two approaches.

 

It doesn't ... It's just in Peter's code!

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

JohanEkdahl wrote:

As Lee says, your bitmap for the character is not in flash. You removed the PROGMEM as I suggested.

But then you should not try to read the bitmap out of flash!

 

Change

      lcd_data(pgm_read_byte_near(&customChar[i]));

to 

      lcd_data(&customChar[i]);

as I said in #30.

 

Those two changes go together.

EITHER have bitmap in flash (PROGMEM) and read out of flash (pgm_read_byte...),

 OR have bitmap in RAM (no PROGMEM) and read out of RAM (no pgm_read_byte...).

 

Ok, going to try! Thanks

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

PsySc0rpi0n wrote:
It doesn't ... It's just in Peter's code!

No, it is not.  And it was completely explained in #30, as well as #36.

 

From "Peter's code":

/*
** constant definitions
*/
static const PROGMEM unsigned char copyRightChar[] =
{
	0x07, 0x08, 0x13, 0x14, 0x14, 0x13, 0x08, 0x07,
	0x00, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x00
};
...
       /*
        * load two userdefined characters from program memory
        * into LCD controller CG RAM location 0 and 1
        */
       lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */
       for(i=0; i<16; i++)
       {
           lcd_data(pgm_read_byte_near(&copyRightChar[i]));
       }

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Ok, I think I have one more question.

 

in lcd.h the following is set:

 

#define LCD_CGRAM             6      /* DB6: set CG RAM address             */

 

I don't understand how this "says" that the custoChar is going to be stored in 1st position of the 8 available in CGRAM.

 

Let's say I want to store 3 customChars. They will be "magically stored in CGRAM. How do I access to one of the 3 customChars? How do I know which customChar is at which position in CGRAM?

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

You will have to stress a bit more and try to understand my ASM code wink this is from an old project for the music store HMV (RIP)

 

These are the 8 special graphics, at this stage they are just flash data

 

cg_codes:
;0x00 or 0x08
.db	0,0,0,7,5,6,5,0		;"Repeat" graphic

;0x01 or 0x09
.db	16,24,28,30,28,24,16,0	;"Play" graphic

;0x02 or 0x0a
.db	28,16,28,7,29,6,5,0	;"Shuffle" + "Repeat" graphic

;0x03 or 0x0b
.db	27,27,27,27,27,27,27,0	;"Pause" graphic

;0x04 or 0x0c
.db	28,16,24,23,29,7,1,0	;"Eq" graphic

;0x05 or 0x0d
.db	31,31,31,31,31,31,31,0	;"Stop" graphic

;0x06 or 0x0e
.db	0x01,0x03,0x07,0x0f,0x07,0x03,0x01,0x00	;< Reverse graphic

;07 or 0x0f
.db	0,0,0,7,5,6,5,0		;"Repeat" graphic

during the initialization  that data is copied to the LCD cg ram location using the control write command with a loop of 8 counts.

 

To display the corresponding graphic at run time you call the print routine with the code (say 0x05 for Stop graphic) instead of say A, B etc.

 

Sorry no C code that I can remember, maybe I have one but don't know where.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

Last Edited: Fri. Jul 28, 2017 - 10:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No problem... I got the first part! I understand your ASM code... That's just defining the custom chars to create icons, so to speak...

 

What I didn't understood an dnow I already understand is that I was used to send a command 0x40 to the LCD when I used an 8051 and I was not understanding why with AVR uC and Peter's libraries, a 6 was being used as the "set CGRAM address" command! Now I understand that, after the _BV macro is executed with that 6, it becomes THE 0x40 I was used to, by means of 1 << 6 == 0x40... That was my struggle. I couldn't understand the reason of that 6.

 

Now I tried the following code but it's not working either, but now I think it's a C code problem and not any configuration:

 

I use ideone as it's a little long code due to the customChars I created!

 

http://ideone.com/zXlRs3

 

Edited;

I found the error and fixed it...

It's working now!

Last Edited: Fri. Jul 28, 2017 - 10:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
Let's say I want to store 3 customChars. They will be "magically stored in CGRAM. How do I access to one of the 3 customChars? How do I know which customChar is at which position in CGRAM?

 

OK it is now clear that you aren't reading what we post, or are reading sloppily. In #30 I wrote

 

Also note that the call to 

lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */

says that what follows is the first spacial character of the eight that the 44780 can handle. Remember that each character is defined by 8 bytes. This means that the second special character is defined in the eight bytes starting at _BV(LCD_CGRAM) + 8. In general, to define special character n  you need to 

lcd_command(_BV(LCD_CGRAM) + n * 8);  /* set CG RAM to define spacial character n */

It is not the _BV(LCD_CGRAM) that specifies where in CGRAM the special character ends up. The _BV(LCD_CGRAM) bit tells the LCD that this whole byte is to set the CGRAM address. It is the rest of the byte is the address where the first byte of the bitmap is to end up. And then every write will auto-increment the address into CGRAM with 1. This probably would have been clear if you had opened up the Hitachi PDF that I linked to somewhere above, and read there about CGRAM.

 

To write to the first special character in CGRAM you start at byte 0 in CGRAM. With my general code from above that would be:

lcd_command(_BV(LCD_CGRAM) + 0 * 8);  /* set CG RAM to define spacial character 0 */

and since 0 * 8 == 0, and thus can be left out, Peters code simply says

lcd_command(_BV(LCD_CGRAM));  /* set CG RAM to define spacial character 0 */

 

I believe I have spent at least two hours thinking out and typing posts to you. Typing a lengthy post to try to explain something thoroughly, only to then find it was not read (or read sloppily) is frustrating and feels like a complete waste of time.

 

 I will not spend any more time here until you start reading. (Begin with e.g. browsing the Hitachi document from beginning to end so that you have a hunch about what's in there. Not everything is excellent info, but there are a lot of things are important and useful.)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

JohanEkdahl you may not believe me, but I read every single line of each post that was posted here! I'm not English and sometimes there are technical terms I'm not absolutely comfortable with. And believe it or not, I have like 12 sites open regarding AVR, avr-gcc, Atmel and some other sites, including HD44780 controller datasheet.

 

This is actually my Google Chrome window. You can see the amount of sites I have been reading and exploring!

google chrome

 

I'm sorry if I'm disappointing and not meeting your expectations! I can't make anyone to help me. But as this forum is the best one related to Atmel and AVR, I'm here asking help! I'll be sad and mad with myself if I get to a point where no one is willing to help me. That will force me to seek help somewhere else that probably won't have the quality and expertise I find here!

 

Regarding your post, specifically this:

 

says that what follows is the first spacial character of the eight that the 44780 can handle.

I have no idea of what a "spacial character" is... And if you meant "special" instead of "spacial", I'm really sorry I didn't noticed that earlier! 

 

And about the way you say I need to follow to write custom chars in CGRAM, I did it without the way you explained, I mean the 

lcd_command(_BV(LCD_CGRAM) + 0 * 8);  /* set CG RAM to define spacial character 0 */

way. I did it differently and I got what I was expecting! Probably it's a dumb way of doing things but it was the way I found!

Last Edited: Fri. Jul 28, 2017 - 11:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
I have no idea of what a "spacial character" is...

 

Same thing as a Custom Character.

 

 

Hmmmm, Maybe you need to take a little break from all of this and go outside for a day or so and catch your breath ! smiley

 

 

 

Jim

 

EDIT:

After I read through the posts in this thread I started wondering about the Custom Character RAM and how its used etc.  I put the following into GOOGLE:

 

creating custom characters for HD44780

 

The return hits were quite helpful.  Since I do not know how your returns may show up here are the first few that came back for me:

 

This is a utility for creating the values for your character

https://omerk.github.io/lcdcharg...

 

Another great utility:

https://www.quinapalus.com/hd447...

 

This link gives a basic, yet decent understanding of how it works:

http://www.circuitvalley.com/201...

 

 

If you put the same search term, but add AVR to teh end of it you get several threads and projects from this site as well....and Johan is ion the thick of those threads too!

 

I may put together a little test program of my own just to see what happens using the threads I posted above.

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

Last Edited: Sat. Jul 29, 2017 - 01:42 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
My questions were about how to store each custom char in CGRAM and then how to print them on the LCD! Which commands do we need to use to accomplish these two tasks!

How we do it in the old day

http://www.circuitvalley.com/2012/02/lcd-custom-character-hd44780-16x2.html

 

Sorry for big picture. I don't know how to resize it. Need help!

 

The code

lcdInit();
gotoXy(0,0);
prints("custom font");

//save 7 custom char
lcdCmd(0x40);
lcdData(0xe);
lcdData(0x1b);
lcdData(0x11);
lcdData(0x11);
lcdData(0x11);
lcdData(0x11);
lcdData(0x11);
lcdData(0x1f);

lcdData(0xe);
lcdData(0x1b);
lcdData(0x11);
lcdData(0x11);
lcdData(0x11);
lcdData(0x11);
lcdData(0x1F);
lcdData(0x1f);

lcdData(0xe);
lcdData(0x1b);
lcdData(0x11);
lcdData(0x11);
lcdData(0x11);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1f);

lcdData(0xe);
lcdData(0x1b);
lcdData(0x11);
lcdData(0x11);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1f);

lcdData(0xe);
lcdData(0x1b);
lcdData(0x11);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1f);

lcdData(0xe);
lcdData(0x1b);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1f);

lcdData(0xe);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1f);



//next line
gotoXy(0,1);

//Show custom char
lcdData(0x00);
lcdData(0x01);
lcdData(0x02);
lcdData(0x03);
lcdData(0x04);
lcdData(0x05);
lcdData(0x06);
prints(" BATTERY ");

 

MG

I don't know why I'm still doing this hobby

Last Edited: Sat. Jul 29, 2017 - 03:29 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Attachment(s): 

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

Last Edited: Sat. Jul 29, 2017 - 05:23 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks to all that helped...

Once more I apologise if I look like I don't read your posts carefully or I don't read/search Google before I ask here! I DO read your posts and search Google before asking here! And jgmdesign the 1st link you posted, doesn't work and I've been on the other 2 links you posted inpost #46.

 

And have any of you looked to the code I posted?

 

I'll ask some questions about the 2 last posts. The question is common for both posts.

 

We use lcd_command() function to set the CGRRAM start address. This tells we are going to write data in that specific memory "area"/location/address.

Then we actually write/store there the custom chars using the lcd_data() function.

Then in MicroGyro's post, he simply uses the gotoXY() function to set the line and column where we want to print any of the custom chars of CGRAM and lcd_data() function to print the custom chars from CGRAM. My question here is how the HD44780 controller knows where to print custom chars from CGRAM if we use lcd_data() function to write chars both on CGRAM and DDRAM?

 

I'm not sure I explained myself clearly enough.

 

lcd_command(0x40) says we are going to write in first address of CGRAM... Ok until here.

lcd_data(........) says we are going to store/save/write the custom chars in the above 0x40 address and next addresses.

 

gotoXY() says what line and cloumn we want to print the above custom chars!

lcd_data(.....) to print the custom chars from CGRAM.

 

But there is no command saying we "got out" of 0x40 memory area (CGRAM). How it knows we are now going to print in DDRAM?

 

 

Edited;

 

I see that in that 3rd, link, same as MicroGyro posted, they say they need to send a new command to set the DDRAM address like lcd_command(0x80) but I can't see it in any of the codes here or in that link!

 

Last Edited: Sat. Jul 29, 2017 - 10:01 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Read the Hitachi document I linked to!!! There is an EXCELLENT table showing the bit patterns for EVERYTHING you can do with the 44780.

 

EDIT: Table 6 on pages 24-25.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Sat. Jul 29, 2017 - 12:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Short answer: After a Set DDRAM address (i.e. 1aaaaaaa, where aaaaaaa is the address) all following data writes goes to DDRAM. After a Set CGRAM (i.e. 01aaaaaa) all following data writes goes to CGRAM.

 

Now go look at what gotoXY() actually does.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

JohanEkdahl wrote:

Read the Hitachi document I linked to!!! There is an EXCELLENT table showing the bit patterns for EVERYTHING you can do with the 44780.

 

EDIT: Table 6 on pages 24-25.

 

I know about the CGRAM and DDRAM address... I know you guys probably gonna be flamed up because what I'm going to say, but it's what I feel sometimes too! I think sometimes my posts aren't also carefully read.

 

I said in my previous post that my question is that I can't see in any of the codes discussed up to now how to distinguish where we are going to write a custom char. I can see in MicroGyro code the CGRAM initial address being set, the 0x40. But then I can't see the 0x80 address being written prior to print the custom chars in DDRAM. Also in that link posted somewhere above (http://www.circuitvalley.com/201...) I see the 0x40 but I can't see the 0x80. So how the controller knows that we want to print chars in DDRAM? And in that link they say that the 0x80 needs to be sent but I can't see it in their code either.

 

now we are ready to display this font on to lcd. but keep one thing in mind you should get back to DD RAM, to display this data on to screen . this can be done by setting DD RAM address. like for 16x2 char lcd first, row first character send lcdCmd(0x80);

So, this is the 2nd time also that I'm asking the same. However, what I keep getting is "read the datasheet"! Datasheet doesn't address Peter's libraries or anyone's code! :(

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

I'll answer what I posted.

 

PsySc0rpi0n wrote:
We use lcd_command() function to set the CGRRAM start address. This tells we are going to write data in that specific memory "area"/location/address. Then we actually write/store there the custom chars using the lcd_data() function.

That is correct.

 

"If you want to write you first custom character to 0x00 CG RAM location then you have to send lcd a command lcdCmd(0x40);
 After this now you are ready to send data to CG RAM location 0x00.

 After sending the whole pattern (1 custom char) for location 0x00  the location pointer will auto increase to 0x01 location. 

 Or if you want to store something to 0x03 location then send direct command lcdCmd(0x43);"

 

Example of whole pattern for 1 custom char (battery icon):

  1. lcdData(0x0E);
  2. lcdData(0x1B);
  3. lcdData(0x11);
  4. lcdData(0x11);
  5. lcdData(0x11);
  6. lcdData(0x11);
  7. lcdData(0x11);
  8. lcdData(0x1F);

 

PsySc0rpi0n wrote:
Then in MicroGyro's post, he simply uses the gotoXY() function to set the line and column where we want to print any of the custom chars of CGRAM and lcd_data() function to print the custom chars from CGRAM. My question here is how the HD44780 controller knows where to print custom chars from CGRAM if we use lcd_data() function to write chars both on CGRAM and DDRAM?

I used gotoXY() function to point to where I want to place my custom char then use lcd_data() to print to screen. That's for both CGRAM and CGROM (DDRAM holds what's on the screen)

 

For example: 

- I want to write a custom char to col 5 at row 1 then I simply use gotoXY(5, 1) and put my custom char number 4 on that location using lcd_data(0x03).

  You can put more custom char using gotoXY(5, 1) and then use lcd_data(0x03), lcd_data(0x03), lcd_data(0x03) which will place 3 same custom char which start  from col 5 row 1.

  First custom char saved is called using lcd_data(0x00) and so on. (LCD controller know which one you are call CGRAM or CGROM)

 

- After that custom char I want to print string so I simply use gotoXY(6, 1) and do print("My String") (or whatever your function to print string)

  I can put my gotoXY inside my print() to do it more easily, so I can use print(6, 1, "My String");

 

So how about back to CGROM after use custom char? Just simply do usual lcd_data() or print() after gotoXY() to overwrite what's in the screen. That's all.

 

One thing to be notice is even after you print string or custom char you can overwrite it using gotoXY() and lcd_data() or print(), but if the previous text is longer than new text then the previous text need to be erase first using lcd_clear (or you can easily overwrite it with blank char?) or it will remain in the screen which is not good.

 

Don't laugh at me, I can only do simple things, if it works it aint stupid. :)

That's an explanation from old guy doing LCD display. :)

 

 

MG

 

 

 

I don't know why I'm still doing this hobby

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

Bad internet connection :(

Sorry.

I don't know why I'm still doing this hobby

Last Edited: Sat. Jul 29, 2017 - 01:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
I can see in MicroGyro code the CGRAM initial address being set, the 0x40. But then I can't see the 0x80 address being written prior to print the custom chars in DDRAM.

 

No. You are not reading. Or reading but ignoring. A few posts ago I asked/hinted to have a look at what gotoXY() does. Did you do that?

 

I'll be explicit, and do the investigation you should have done. I do not have MicroGyros code for gotoXY, but I have Peter Fleurys code for lcd_gotoxy() (and any print positioning function for a 44780 LCD must do the same or something very similar). Here's Peters code:

 

void lcd_gotoxy(uint8_t x, uint8_t y)
{
#if LCD_LINES==1
    lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);
#endif
#if LCD_LINES==2
    if ( y==0 )
        lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);
    else
        lcd_command((1<<LCD_DDRAM)+LCD_START_LINE2+x);
#endif
#if LCD_LINES==4
    if ( y==0 )
        lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);
    else if ( y==1)
        lcd_command((1<<LCD_DDRAM)+LCD_START_LINE2+x);
    else if ( y==2)
        lcd_command((1<<LCD_DDRAM)+LCD_START_LINE3+x);
    else /* y==3 */
        lcd_command((1<<LCD_DDRAM)+LCD_START_LINE4+x);
#endif

}/* lcd_gotoxy */

I't's a bit convoluted because it has conditional compilation for different display sizes. Let's simplify it and see what it would look like for a 2-line display:

void lcd_gotoxy(uint8_t x, uint8_t y)
{
    if ( y==0 )
        lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);
    else
        lcd_command((1<<LCD_DDRAM)+LCD_START_LINE2+x);
}

So, regardless of if we want to go to line 0 or 1 (i.e. y == 0 or 1) we send a command to the display that has bit LCD_DDRAM set. This bit indicates that all data send after this command is to be written in DDRAM.

 

Conclusion: A gotoXY function always sets DDRAM address, and thus always selects DDRAM for data that follows.

 

Do you get it now?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Sat. Jul 29, 2017 - 02:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
A gotoXY function always sets DDRAM address, and thus always selects DDRAM for data that follows.

+1 yes

 

 

" 20 x 4 LCD - DDRAM Address            

  Row1     0x80 0x81 0x82 0x83 through 0x93
  Row2     0xCO 0xC1 0xC2 0xC3 through 0xD3
  Row3     0x94 0x95 0x96 0x97 through 0xA7
  Row4     0xD4 0xD5 0xD6 0xD7 through 0xE7 "

 

0x80 is address of DDRAM at row 1 col 1 to be specific. 0x81 is col 2 and so on. 

 

Edit: typo

 

MG

I don't know why I'm still doing this hobby

Last Edited: Sat. Jul 29, 2017 - 02:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
We use lcd_command() function to set the CGRRAM start address. This tells we are going to write data in that specific memory "area"/location/address.

Correct

 

PsySc0rpi0n wrote:
Then we actually write/store there the custom chars using the lcd_data() function.

Correct

 

PsySc0rpi0n wrote:
Then in MicroGyro's post, he simply uses the gotoXY() function to set the line and column where we want to print any of the custom chars of CGRAM and lcd_data() function to print the custom chars from CGRAM. My question here is how the HD44780 controller knows where to print custom chars from CGRAM if we use lcd_data() function to write chars both on CGRAM and DDRAM?

And HERE is where you are missing what I posted in post #48

 

and:

 

in my MAIN code I display them by using Mr. Fleury's library function "lcd_putc":

lcd_putc(0);		//display first custom character

and:

lcd_putc(1);		//display second custom character

Which if you look at the memory map above are CGRAM cells '0', and '1'...Where I stored my fabulous Custom Characters!!

 

 

PsySc0rpi0n wrote:
lcd_command(0x40) says we are going to write in first address of CGRAM... Ok until here. lcd_data(........) says we are going to store/save/write the custom chars in the above 0x40 address and next addresses.

meaning the start of the custom character ram area is 0x40.  TO make one character you use 8 locations, so for the first character is stored in locations 0x40 thru 0x47.  The second starts at 0x48 thru 0x50, and so on.

 

PsySc0rpi0n wrote:
gotoXY() says what line and cloumn we want to print the above custom chars! lcd_data(.....) to print the custom chars from CGRAM.

WRONG!!

Goto_xy tells the display exactly where on the screen to print the next character.....Custom or standard.

 

PsySc0rpi0n wrote:
But there is no command saying we "got out" of 0x40 memory area (CGRAM). How it knows we are now going to print in DDRAM?

Ahhh!  I think I see your confusion.  The short answer is you do not have to worry about any of that.  If you look at me short example you will see I don't do anything in regards to DDRAM directly.

 

Take a look at the table I posted above with the red circle in it, or better yet, look at the datasheet for a clear view as the table comes from the datasheet.  Look at the '0' character.  I will use this for the example..

 

If you look at the table location where '0' is locates....just to the top are '0011', and to the left is '0000'  This is the address where the character '0' is located. 

 

When I write:

lcd_putc("0");

the "0" is converted to the ASCII by your compiler equivalent of '0' which is 0x30...in binary this is 00110000.  LOOK as the chart..... High byte 0011 low byte 0000...which is 0x30 in HEX

 

So I could write this:

lcd_putc(0x30);

and I will get the same result....the number '0' printed at the current location.  What the LCD manufacturer(Hitachi) did was to make the worlds life easy by mapping their character table - Both Custom and Standard to match the ASCII table. Google ASCII tables and you will see what I mean.  Now in the true ASCII table there is a null for 0x00 and other commands in the first eight locations...IGNORE this on the ASCII table as the LCD does and uses them as locations for storing your custom characters.

 

Confused?  I was.  I did not read up much on the DDRAM as quite frankly I do not see much in using it as I can print my characters and the standard ones by simply using Fleurys library right out of the box and the CGRAM table.  I would recommend you simply do the same.  Why make your head hurt?  I know I know...because you want to understand EVERYTHING.  I get it.  But for the purpose of getting your screen to do what you want, the example code, and the links I used and posted above do the trick(the first link for some reason does not work from this site directly, but a copy/paste did).  Once you get a few custom characters showing on the screen THEN start poking around.  Your choice.

 

Ok, now back to locations and how things are stored:

In the AVR at some place in FLASH I have stored 16 hex numbers by doing this:

static const PROGMEM unsigned char CustomChar1[] =
{
		0x19,0x2,0x4,0x8,0x4,0xa,0x19,0x10
};

static const PROGMEM unsigned char CustomChar2[] =
{
		0x13,0x8,0x4,0x2,0x11,0x12,0x4,0x3
};

eight hex values for each character.  Each character has a unique name - CustomChar1, and CustomChar2

 

At runtime, the application writes CustomChar1 to CGRAM starting at location 0x40 using this loop:

lcd_command(CGRAM_Base_Addr);	//set the CGRAM address pointer to first character location

		for(uint8_t i=0; i<sizeof CustomChar1; i++)
		{
			lcd_data(pgm_read_byte_near(&CustomChar1[i]));		//write the data
		}

This means my eight hex values will occupy CGRAM locations 0x40 thru 0x47

 

Next I tell the LCD to store the next Custom Character at the the base address + 8 location (0x48)

//load second custom character

	lcd_command(CGRAM_Base_Addr + 8);	//set the CGRAM address pointer to the second character location

	for(uint8_t i=0; i<sizeof CustomChar2; i++)
	{
		lcd_data(pgm_read_byte_near(&CustomChar2[i]));			//write the data
	}	

and once this loop is done I return to the MAIN loop.

 

from here the code simply prints characters from the CGRAM/CGROM based on what you put into

lcd_putc();

if you place a hex value in the () then it will jump to that location in the table.  If you put a letter inside "", then the compiler will convert the letter to the ASCII equivalent and print that from the table.

 

In the second link above the author makes an excellent explanation of the CG table I posted a snippet of explaining where the CGRAM(custom chaacters are located) and CGROM are in the table.

 

Each location is a character cell that is eight bytes deep containing the eight hex values for the eight rows that make up a character.

 

Hope this clears up some of your questions.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

I see Johan ans Micro have posted while I was writing and I now understand what DDRAM is.  If my understanding is correct DDRAM are simply locations in the VISIBLE area of the display.

 

So when you use:

lcd_gotoxy(x,y);

the library converts your X/Y position to a HEX value for the location in DDRAM, and thats where your next character is printed.    The LCD will then increment the DDRAM counter to print the next character, unless you use the lcd_gotoxy() command to change this.

 

Thanks Johan and Micro!

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

The cells in DDRAM are single bytes, one per character position on the display. The CGRAM and CGROM contains bitmaps for rendering of characters, 8 bytes per character. You can think of the CGRAM+CGROM as one table with 128 bitmap entries. The 8 first bitmaps are writeable, the other 120 are read only. The table is used to translate a 1-byte value from DDRAM to a bitmask to render one character cell on the physical display .

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

I'll not be quoting because of the long post it become. I'll just tag each one of you that replied!

 

@MicroGyro I have already learned something else in your post! You said:

I used gotoXY() function to point to where I want to place my custom char then use lcd_data() to print to screen. That's for both CGRAM and CGROM (DDRAM holds what's on the screen)

I never thought about CGROM and other memory areas! Now I now that DDRAM is responsible be keeping the chars in the LCD. CGRAM is to store Custom Chars but still not absolutely clear about CGROM and not sure if a DDROM also exists. But it's ok for now. I think I don't need to know about those for what I'm trying to do.

 

 

@JohanEkdahl I have looked to almost every line of Peter Fleury's code. Of course I couldn't understand every and each line! About the specific lcd_gotoxy() I looked at it but nothing told me clearly that a 0x80 was being issued there. So maybe here you are right when you said I didn't looked carefully! I can take that on for sure! And yes, that was the answer I was looking to have!

 

Now I'm cleared about how the area where we are going to print chars is set! It's using lcd_gotocy() function for DDRM/CGROM and with lcd_command(0x40) for CGRAM.

 

 

@jgmdesign I also learned something new from your post although I think it wasn't what I was looking for! The stuff about "0" to be converted into a corresponding ASCII number, I know! But I understood how that table for datasheet is supposed to be read, upper bits and lower bits for each character and also that the Hitachi guys did that mapping with a 2nd purpose. The one you say that the Hitachi mapping of chars matches ASCII tables.

 

 

Thank you to you all!

 

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

JohanEkdahl wrote:
The cells in DDRAM are single bytes, one per character position on the display. The CGRAM and CGROM contains bitmaps for rendering of characters, 8 bytes per character. You can think of the CGRAM+CGROM as one table with 128 bitmap entries. The 8 first bitmaps are writeable, the other 120 are read only. The table is used to translate a 1-byte value from DDRAM to a bitmask to render one character cell on the physical display .

 

Ah ok... Another very good piece of information These terms were not very clear yet in my mind!

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

Ok, yesterday I made some custom chars and I was able to successfully print them. If I was the PROGMEM method instead of saving custom chars to CGRAM,will I be able to create and use more custom chars than the 8 the HD44780 can handle?

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

There are only eight definable characters using eight bytes each so 64 bytes in total. It's your choice whether you want to waste RAM to hold them or save that and only locate in flash. Sort of depends if you plan to change the definitions during run time.
.
BTW this is 2017 so use __flash which will make it easier.

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

And as for flash memory, how things works? Is there any specific documentation on how it works and how to implement custom chars and how to read them and print them into LCD?

 

Edited;

 

I'm trying to find stuff about PROGMEM and pgm_read_byte_near() but only the avr-gcc online manual comes up and there is no newbie explanation about it!

 

For instance, if I want to save my custom chars to FLASH memory, do I have to send any address prior to writing command like we do to CGRAM with the address 0x40?

 

Do I have limit of custom chars that I can save?

 

When I read one char from FLASH memory, and send it to DDRAM memory area, do I need to set the controller to the "next byte" to read the next custom char stored in FLASH memory does it also auto-increments?

 

If I overwrite some custom char in FLASH memory, does the old custom char gets updated in DDRAM with the new one that overwritten the old char?

 

These and probably a lot more questions will arise!

Last Edited: Sat. Jul 29, 2017 - 07:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
And as for flash memory, how things works? Is there any specific documentation on how it works and how to implement custom chars and how to read them and print them into LCD? Edited; I'm trying to find stuff about PROGMEM and pgm_read_byte_near() but only the avr-gcc online manual comes up and there is no newbie explanation about it! For instance, if I want to save my custom chars to FLASH memory, do I have to send any address prior to writing command like we do to CGRAM with the address 0x40? Do I have limit of custom chars that I can save? When I read one char from FLASH memory, and send it to DDRAM memory area, do I need to set the controller to the "next byte" to read the next custom char stored in FLASH memory does it also auto-increments? If I overwrite some custom char in FLASH memory, does the old custom char gets updated in DDRAM with the new one that overwritten the old char? These and probably a lot more questions will arise!

 

SUGGESTION.....FORGET ABOUT __FLASH as you are still confused about simply creating, and writing custom characters to the CGRAM... As you are using the Fleury example code...I think Stick with that and get your questions on using the LCD straight BEFORE delving into using __FLASH.  For the moment PROGMEM is fine.

 

Otherwise this thread is going to become more complicated than it already is. 

 

Just my Opinion.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

PsySc0rpi0n wrote:
About the specific lcd_gotoxy() I looked at it but nothing told me clearly that a 0x80 was being issued there.

lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);

LCD_DDRAM is 

#define LCD_DDRAM             7      /* DB7: set DD RAM address             */

and thus

1<<LCD_DDRAM

is binary 10000000 or hex 0x80 .

 

PsySc0rpi0n wrote:
It's using lcd_gotocy() function for DDRM/CGROM and with lcd_command(0x40) for CGRAM.

I'm not entirely sure what you mean here, but I think you're wrong:

  • lcd_gotoxy() will "select" DDRAM (since it sends an instruction/command with the high bit set, i.e. 1xxxxxxx)
  • lcd_command(0x40) will "select" CGRAM (since it sends an instruction/command with the two high bits set to 01, i.e. 01xxxxxx)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

jgmdesign wrote:

PsySc0rpi0n wrote:
And as for flash memory, how things works? Is there any specific documentation on how it works and how to implement custom chars and how to read them and print them into LCD? Edited; I'm trying to find stuff about PROGMEM and pgm_read_byte_near() but only the avr-gcc online manual comes up and there is no newbie explanation about it! For instance, if I want to save my custom chars to FLASH memory, do I have to send any address prior to writing command like we do to CGRAM with the address 0x40? Do I have limit of custom chars that I can save? When I read one char from FLASH memory, and send it to DDRAM memory area, do I need to set the controller to the "next byte" to read the next custom char stored in FLASH memory does it also auto-increments? If I overwrite some custom char in FLASH memory, does the old custom char gets updated in DDRAM with the new one that overwritten the old char? These and probably a lot more questions will arise!

 

SUGGESTION.....FORGET ABOUT __FLASH as you are still confused about simply creating, and writing custom characters to the CGRAM... As you are using the Fleury example code...I think Stick with that and get your questions on using the LCD straight BEFORE delving into using __FLASH.  For the moment PROGMEM is fine.

 

Otherwise this thread is going to become more complicated than it already is. 

 

Just my Opinion.

 

JIm

 

So, I have no way of using more than 8 custom chars if I don't use flash memory, correct? I also think I might still missing some basic concepts. You said to leave flash for now and use only PROGMEM. right?

 

I think I already understood CGRAM creation, storing and printing. It's the same as I used to do with 8051. There was a lot of discussion because, probably of my poor explanation of my doubts, anybody was understanding my struggle. My struggle was just because I never noticed where was the 0x80 to get back to DDRAM memory area after issuing the 0x40 to get into CGRAM memory area...

 

Now about PROGMEM and FLASH. I thought that when PROGMEM was used, we were storing custom chars in LCD flash memory. But looks like it's not like that! Can you explain me a little bit about existing memory types in this HD44780 controller and how they can be used? Or point me out some link where I can read about it! I don't think that datasheet explains in a newbie way this matter!

 

Thanks

 

 

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

JohanEkdahl wrote:

PsySc0rpi0n wrote:
About the specific lcd_gotoxy() I looked at it but nothing told me clearly that a 0x80 was being issued there.

lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);

LCD_DDRAM is 

#define LCD_DDRAM             7      /* DB7: set DD RAM address             */

and thus

1<<LCD_DDRAM

is binary 10000000 or hex 0x80 .

 

PsySc0rpi0n wrote:
It's using lcd_gotocy() function for DDRM/CGROM and with lcd_command(0x40) for CGRAM.

I'm not entirely sure what you mean here, but I think you're wrong:

  • lcd_gotoxy() will "select" DDRAM (since it sends an instruction/command with the high bit set, i.e. 1xxxxxxx)
  • lcd_command(0x40) will "select" CGRAM (since it sends an instruction/command with the two high bits set to 01, i.e. 01xxxxxx)

 

That was what I meant.

Inside gotoXY() there is that 0x80 command being issued implicitly. So it was that lcd_command(0x80) I was looking for that I also used with  8051 to select the DDRAM memory area.

And the other one is sent explicitly to select CGRAM memory area, so no questions about it!

 

Thanks!

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

So, now about the custom chars.

 

I wanted to do something to show to my daughter. And it was to print her first name using a bunch of custom chars, a lot more than 8.

 

For instance, my daughter's first name is BIA! So I wanted to draw each character using 5 columns and 4 rows (LCD has 4 rows) for each char.

So, for instance an "A" would look like this:

 

So, would this be possible to do with an LCD?

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

PsySc0rpi0n wrote:
So, I have no way of using more than 8 custom chars if I don't use flash memory, correct?

Incorrect.  You will have to load a new character, or set of characters into CGRAM.  Meaning you can have as many as you want, you only have eight at a time to work with.

 

PsySc0rpi0n wrote:
I also think I might still missing some basic concepts. You said to leave flash for now and use only PROGMEM. right?

Yes, you are missing a few basic concepts, that really have nothing to do with using PROGMEM, or __FLASH. I am only suggesting you hold off on jumping to another topic until you have understood the operation of the LCD first.  Using PROGMEM or __FLASH really has no impact on the way the CGRAM gets loaded in the end.

 

PsySc0rpi0n wrote:
I think I already understood CGRAM creation,

REally?  All these posts back and forth and you already knew what to do?

 

PsySc0rpi0n wrote:
Now about PROGMEM and FLASH. I thought that when PROGMEM was used, we were storing custom chars in LCD flash memory.

YOu are

 

PsySc0rpi0n wrote:
But looks like it's not like that!

Wrong! 

 

PsySc0rpi0n wrote:
Can you explain me a little bit about existing memory types in this HD44780 controller and how they can be used?

The datasheet mentions about using the space, but it's not worth it as the AVR has far more RAM available than a few bytes in a slow LCD.  In this case I strongly say forget about it....not worth the hassle.

 

 

If you are now all set on the LCD operation and no longer need our help on it, I suggest you start a new thread on the next item you do not understand.  If you have more questions on LCD, then add them to this thread.

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

Last Edited: Sat. Jul 29, 2017 - 11:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgmdesign wrote:

PsySc0rpi0n wrote:
So, I have no way of using more than 8 custom chars if I don't use flash memory, correct?

Incorrect.  You will have to load a new character, or set of characters into CGRAM.  Meaning you can have as many as you want, you only have eight at a time to work with.

 

...

...

...

 

Jim

 

Hum, ok, I see but there is a catch I think!

 

If you print a custom char at DDRAM and after that you change that custom char in CGRAM, it will update the DDRAM printed char with the updated char in CGRAM automatically, no? I remember something like that!

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

PsySc0rpi0n wrote:
If you print a custom char at DDRAM and after that you change that custom char in CGRAM, it will update the DDRAM printed char with the updated char in CGRAM automatically, no? I remember something like that!

CGRAM and DDRAM is 2 different memory area. So anything you do to CGRAM has no effect to DDRAM until you do gotoXY and lcd_data() or print().
.
DDRAM holds what on the screen means it holds the character so you won't be notice what's going on behind the screen. Or else you'll see flickering or blinking screen while you change the char.
.
So basically lcd_clear() doing is nothing than clearing DDRAM.
.
As other hint is to display some thing on the screen, say it temperature.
You don't have to change the whole text, just the value.
.
On screen: Temperature: 30 °C (assume this text placed on row 2)
.
You want to update the value 30 to 27 so what you should do is:
- gotoXY(13,1) - (13 is location of "3")
- print("27"). - overwrite it with 27
That's all. No need to print("Temperature: 27 °C")
.
I hope you know what I tried to explain. That's how DDRAM works.
.
But one thing to remember, RAM means it only holds when there's a vcc supply on it.
Once the vcc to LCD was cut (then powered back) and you only do gotoXY(13,1) and print("27") your "Temperature: °C" won't be there anymore. Except "27" at col 13 location.
.
I hope I make it clearer not more confusing. :)
.
Edit: - damn autocorrect

        - wrong answer about DDRAM refresh update. Changing at CGRAM which already displayed on the screen (inside DDRAM) will be updated (refreshed) by internal controller automatically.
.
MG

I don't know why I'm still doing this hobby

Last Edited: Sun. Jul 30, 2017 - 01:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It has been brought to my attention that I may have misread a comment by the op:

 

jgmdesign wrote:
PsySc0rpi0n wrote: Now about PROGMEM and FLASH. I thought that when PROGMEM was used, we were storing custom chars in LCD flash memory. YOu are

 

My reply is INCORRECT as I thought the OP was referring to the Microcontroller FLASH, and NOT the LCD.....the LCD has no flash memory.  The custom characters are stored in the Micro's FLASH and are transferred to the LCD on demand.

 

My apologies for the mis-information.

 

Thanks to frog_jr for bringing this to my attention.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

MicroGyro wrote:

PsySc0rpi0n wrote:
If you print a custom char at DDRAM and after that you change that custom char in CGRAM, it will update the DDRAM printed char with the updated char in CGRAM automatically, no? I remember something like that!

CGRAM and DDRAM is 2 different memory area. So anything you do to CGRAM has no effect to DDRAM until you do gotoXY and lcd_data() or print().
.
DDRAM holds what on the screen means it holds the character so you won't be notice what's going on behind the screen. Or else you'll see flickering or blinking screen while you change the char.
.
So basically lcd_clear() doing is nothing than clearing DDRAM.
.
As other hint is to display some thing on the screen, say it temperature.
You don't have to change the whole text, just the value.
.
On screen: Temperature: 30 °C (assume this text placed on row 2)
.
You want to update the value 30 to 27 so what you should do is:
- gotoXY(13,1) - (13 is location of "3")
- print("27"). - overwrite it with 27
That's all. No need to print("Temperature: 27 °C")
.
I hope you know what I tried to explain. That's how DDRAM works.
.
But one thing to remember, RAM means it only holds when there's a vcc supply on it.
Once the vcc to LCD was cut (then powered back) and you only do gotoXY(13,1) and print("27") your "Temperature: °C" won't be there anymore. Except "27" at col 13 location.
.
I hope I make it clearer not more confusing. :)
.
Edit: damn autocorrect
.
MG

 

 

Ok, I understood that! I just had the idea that when a custom char in CGRAM was changed, and if it was already somewhere printed in DDRAM, the one in DDRAM would be auto-updated to the new one saved in CGRAM.

 

Thanks for the explanation

Psy

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

jgmdesign wrote:

It has been brought to my attention that I may have misread a comment by the op:

 

jgmdesign wrote:
PsySc0rpi0n wrote: Now about PROGMEM and FLASH. I thought that when PROGMEM was used, we were storing custom chars in LCD flash memory. YOu are

 

My reply is INCORRECT as I thought the OP was referring to the Microcontroller FLASH, and NOT the LCD.....the LCD has no flash memory.  The custom characters are stored in the Micro's FLASH and are transferred to the LCD on demand.

 

My apologies for the mis-information.

 

Thanks to frog_jr for bringing this to my attention.

 

JIm

 

I suspected of that! Thanks for correcting your reply!

And in that case you mean either to save directly into Mega328 flash or to have external memory device and store/read from there, right?

 

And if possible I would like anyone to explain me what is the difference between using the PROGMEM and pgm_read_byte_near() and not using. Where is the chars saved using and not using those functions/macros.

 

Thanks

Psy

Last Edited: Sun. Jul 30, 2017 - 09:27 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can never display more than 8 different custom characters at a time because there are only 8 definable. If you go back and change one then all already on the display will change.
.
Have you thought about getting a GLCD as that's clearly what you really need!

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

clawson wrote:
You can never display more than 8 different custom characters at a time because there are only 8 definable. If you go back and change one then all already on the display will change. . Have you thought about getting a GLCD as that's clearly what you really need!

 

That's what I've been asking and some says it won't change and others says it will change!

 

So, what should I stick for?

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

PsySc0rpi0n wrote:
So, what should I stick for?

Just test it yourself. It's not hard to do it don't it? It won't break your MCU or LCD anyway.

 

 

 

 

 

MG

I don't know why I'm still doing this hobby

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

MicroGyro wrote:

PsySc0rpi0n wrote:
So, what should I stick for?

Just test it yourself. It's not hard to do it don't it? It won't break your MCU or LCD anyway.

 

 

MG

 

Sure, I'm writing the code to try it! I was just saying that you said it wouldn't change anything until lcd_gotoxy() or lcd_data() was used and clawson said it will!

 

clawson, I know about GLCD... You already said that to me in the past... I just don't have any of those GLCDs now!

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

PsySc0rpi0n wrote:

clawson wrote:

You can never display more than 8 different custom characters at a time because there are only 8 definable. If you go back and change one then all already on the display will change. . Have you thought about getting a GLCD as that's clearly what you really need!

 

 

That's what I've been asking and some says it won't change and others says it will change!

 

So, what should I stick for?

 

It will change. The controller is always refreshing the display, updating characters from what is in the CGRAM at the moment of refresh. To do what you want, you would have to synchronize with the refresh cycle of the HD44780 and change the CGRAM immediately before the display is updated for each character. I don't even think that's possible, and if possible only a good hacker would be able to do it, certainly in ASM, not with some library.

 

So you need to buy a graphical display, not a character one.

 

Now, just a small note to improve your English, in you first post you wrote:

PsySc0rpi0n wrote:
Now, most of things have been forgotten but I pretend to get them back.

 

The translation of "pretendo" to English is "intend", not "pretend". Beware of false friends.

Last Edited: Sun. Jul 30, 2017 - 11:54 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:

PsySc0rpi0n wrote:

clawson wrote:

You can never display more than 8 different custom characters at a time because there are only 8 definable. If you go back and change one then all already on the display will change. . Have you thought about getting a GLCD as that's clearly what you really need!

 

 

That's what I've been asking and some says it won't change and others says it will change!

 

So, what should I stick for?

 

It will change. The controller is always refreshing the display, updating characters from what is in the CGRAM at the moment of refresh. To do what you want, you would have to synchronize with the refresh cycle of the HD44780 and change the CGRAM immediately before the display is updated for each character. I don't even think that's possible, and if possible only a good hacker would be able to do it, certainly in ASM, not with some library.

 

So you need to buy a graphical display, not a character one.

 

Now, just a small note to improve your English, in you first post you wrote:

PsySc0rpi0n wrote:
Now, most of things have been forgotten but I pretend to get them back.

 

The translation of "pretendo" to English is "intend", not "pretend". Beware of false friends.

 

Ok, I'll consider the purchase of a GLCD in a near Future!

 

About the English note, thank you a lot! I'm some one that really intend and like to type and speak the best of my abilities! I rarely use "net" abbreviations such as "u" for "you" and "C" for "see" and stuff like that! I like the old fashioned way! 

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

Ok, I think the code is almost ready! But I have a problem with the usage of the macro PROGMEM. Compiler just ignores it!

 

I'll paste the code in some other site that handles identation a lot better than this and will paste here the compilation result.

 

Code is here:

 

Compilation result is:

avr-gcc -g -Wall -Os -mmcu=atmega328p -std=c99 -DF_CPU=16000000UL   -c -o test_lcd_mine1.o test_lcd_mine1.c
test_lcd_mine1.c:7:1: warning: ‘__progmem__’ attribute ignored [-Wattributes]
 void writeCustomChars(const PROGMEM unsigned char customChars[][8], uint8_t customCharOffset){
 ^
avr-gcc -g -Wall -Os -mmcu=atmega328p -std=c99 -DF_CPU=16000000UL -Wl,-Map,test_lcd_mine1.map -o test_lcd_mine1.elf test_lcd_mine1.o lcd.c
avr-objdump -h -S test_lcd_mine1.elf > test_lcd_mine1.lst
avr-objcopy -j .text -j .data -O ihex test_lcd_mine1.elf test_lcd_mine1.hex
avr-objcopy -j .text -j .data -O binary test_lcd_mine1.elf test_lcd_mine1.bin
avr-objcopy -j .text -j .data -O srec test_lcd_mine1.elf test_lcd_mine1.srec
avr-objcopy -j .eeprom --change-section-lma .eeprom=0 -O ihex test_lcd_mine1.elf test_lcd_mine1_eeprom.hex \
|| { echo empty test_lcd_mine1_eeprom.hex not generated; exit 0; }
avr-objcopy: --change-section-lma .eeprom=0x0000000000000000 never used
avr-objcopy -j .eeprom --change-section-lma .eeprom=0 -O binary test_lcd_mine1.elf test_lcd_mine1_eeprom.bin \
|| { echo empty test_lcd_mine1_eeprom.bin not generated; exit 0; }
avr-objcopy: --change-section-lma .eeprom=0x0000000000000000 never used
avr-objcopy -j .eeprom --change-section-lma .eeprom=0 -O srec test_lcd_mine1.elf test_lcd_mine1_eeprom.srec \
|| { echo empty test_lcd_mine1_eeprom.srec not generated; exit 0; }
avr-objcopy: --change-section-lma .eeprom=0x0000000000000000 never used

 

 

I'm already reading something about PROGMEM from some link of this forum I found in Google, so yes, I already Googled it!

Last Edited: Sun. Jul 30, 2017 - 12:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
But I have a problem with the usage of the macro PROGMEM. Compiler just ignores it!

Until you show some code here (not off-site) I bet one beer that the variables you are trying to store in PROGMEM are local to a function.

 

You can't do that.

 

They must be globals. (To be technically correct they need to be statically allocated but the simple way is to have them as "global" variables, i.e. outside of any function).

 

EDIT: Since you already googled it (supposing you used the error message as search term) you've already found this: https://www.avrfreaks.net/forum/w... . Quite clear.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Sun. Jul 30, 2017 - 01:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
I just had the idea that when a custom char in CGRAM was changed, and if it was already somewhere printed in DDRAM, the one in DDRAM would be auto-updated to the new one saved in CGRAM.

YES you are RIGHT and I'm COMPLETELY WRONG about this. I'm sorry for misleading you about this refreshing thing.

 

El Tangas wrote:
It will change. The controller is always refreshing the display, updating characters from what is in the CGRAM at the moment of refresh.

You are absolutely right!

 

I just tested this CGRAM thing, thank's to El Tangas which make me think to check it again. I feel stupid now. Sorry guys.

 

I edited my post #72 in case other reader will also get misleading by reading that.

 

 

 

MG

 

I don't know why I'm still doing this hobby

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

MicroGyro wrote:

PsySc0rpi0n wrote:
I just had the idea that when a custom char in CGRAM was changed, and if it was already somewhere printed in DDRAM, the one in DDRAM would be auto-updated to the new one saved in CGRAM.

YES you are RIGHT and I'm COMPLETELY WRONG about this. I'm sorry for misleading you about this refreshing thing.

 

JohanEkdahl wrote:

PsySc0rpi0n wrote:
But I have a problem with the usage of the macro PROGMEM. Compiler just ignores it!

Until you show some code here (not off-site) I bet one beer that the variables you are trying to store in PROGMEM are local to a function.

 

You can't do that.

 

They must be globals. (To be technically correct they need to be statically allocated but the simple way is to have them as "global" variables, i.e. outside of any function).

 

EDIT: Since you already googled it (supposing you used the error message as search term) you've already found this: https://www.avrfreaks.net/forum/w... . Quite clear.

 

Yes, already fixed! I have one other experienced "net" friend in IRC channels that already helped me sorting this out! I worked with a lot of AVRs in the past!

And yes, I was reading that same link I found through Google but haven't finished the reading!

 

Thanks

Psy

 

 

 

El Tangas wrote:
It will change. The controller is always refreshing the display, updating characters from what is in the CGRAM at the moment of refresh.

You are absolutely right!

 

I just tested this CGRAM thing, thank's to El Tangas which make me think to check it again. I feel stupid now. Sorry guys.

 

I edited my post #72 in case other reader will also get misleading by reading that.

 

 

 

MG

 

 

No reason t feel stupid... The best also make mistakes. If it was to feel stupid, how do you think I should feel? Stupid to the power of 1000??? xD

 

Thanks

Psy

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

So, let me explain how I conceptualize DDRAM and CGRAM.

 

DDRAM contains pointers to structures that are present in CGRAM (and ROM, for the default characters) and contain the actual characters. So DDRAM stores only the addresses of these structures. The actual data is in the structures.

 

Every refresh cycle, the controller follows those pointers, retrieves the associated structure and prints the data on screen. So if you change CGRAM, DDRAM doesn't change, but what is displayed does change.

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

PsySc0rpi0n wrote:
No reason t feel stupid... The best also make mistakes. If it was to feel stupid, how do you think I should feel? Stupid to the power of 1000??? xD

I'm glad you had such a big heart. :D

 

 

Cheers

MG

I don't know why I'm still doing this hobby

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

El Tangas wrote:
So if you change CGRAM, DDRAM doesn't change, but what is displayed does change.

I'm not sure I follow.

 

 

 

MG

I don't know why I'm still doing this hobby

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

He's saying you might have defined char 3 as AA, AA, AA, AA, AA, AA, AA, AA and then written seventeen 03's to DDRAM so they are dotted all over the display. If you now go back and change those AA to BB's then nothing in DDRAM changes. There are still seventeen 03's there but what's displayed changes.

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

MicroGyro wrote:

PsySc0rpi0n wrote:
No reason t feel stupid... The best also make mistakes. If it was to feel stupid, how do you think I should feel? Stupid to the power of 1000??? xD

I'm glad you had such a big heart. :D

 

 

Cheers

MG

 

No problem... I can understand that someone feels bad and I will always try to cheer him up!

 

MicroGyro wrote:

El Tangas wrote:
So if you change CGRAM, DDRAM doesn't change, but what is displayed does change.

I'm not sure I follow.

 

 

 

MG

 

I'm not following either!

Last Edited: Sun. Jul 30, 2017 - 02:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

See #89
.
(crikey, 89 posts for the simple concept of double indirection?)

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

El Tangas wrote:
DDRAM contains pointers to structures that are present in CGRAM (and ROM, for the default characters) and contain the actual characters. So DDRAM stores only the addresses of these structures. The actual data is in the structures.

 

Yes. Close to what I suggested somewhere above. The combination of CGRAM and CGROM forms a LUT (look-up table) or mapping from a single char value to a 8x8 bytes bitmap.

 

El Tangas wrote:
Every refresh cycle, the controller follows those pointers, retrieves the associated structure and prints the data on screen. So if you change CGRAM, DDRAM doesn't change, but what is displayed does change.
 

 

Yes. Let try to visualize this. What follows is not code running in the AVR but a description of roughly what goes on in the 44780 controller. Roughly!

 

1) Think of the combination of CGRAM and CGROM as one array of bitmaps, i.e. an 128x8 array of bytes. Let's call it "CGMEM". (The first 8x8 bytes are the CGRAM and the following 120x8 bytes are the CGROM).

 

2) The DDRAM consists of 80 bytes.The HD44780 controller constantly loops over all DDRAM elements, picks the value of the element, uses that as an index into the "CGMEM", gets the bitmap (8 bytes) and uses that to set the individual pixels in the physical display.

 

If this was C code, how would it look? Well, roughly:

 

typedef uint8_t[8] bitmap_t;

bitmap_t cgmem[128];  // Actually 8 bitmaps in CGRAM and 120 bitmaps in CGROM

uint8_t ddram[80]; 

while (1) {
    for (int i = 0; i<128; i++) {
        bitmap_t bitmap = cgmem[ddram[i]];

        // Use bitmap to set pixels in character cell i in physical display
    }
}

A change in CGRAM will hve an immediate effect on what is displayed even if there is no change in DDRAM.

 

The above code is an illustration of parts of the "back-end" of the 44780. There's more to it - hidden in my simple comment "Use bitmap to set pixels...".

 

The CGRAM and DDRAM is (at least conceptually) double-ported. I.e. at the same time the back-end does what I sketch above, the front end can write to CGRAM and DDRAM. The "front-end" is what your AVR is communicating with. What your AVRwrite to the 44780 goes through it's front end into CGRAM or DDRAM (or is interpreted as an instruction which affects the state of the 44780 in some way).

 

Again, this is "sketch" but not so far from the detailed truth. .E.g. take a look at the block diagram on page 3 in thee Hitacchi data sheet.

 


 

A side observation regarding MicroGyros code, mentioned in #47 (linking to http://www.circuitvalley.com/201... ):

 

MicroGyro creates a battery status indicator. He does so by defining 8 separate battery icons, each with a different "filling factor". It uses up all of the CGRAM. Different battery levels are displayed by using one of the 8 different characters on CGRAM. There is no space left for any other special characters.

 

A better solution Designate just one of the CGRAM characters/bitmaps for a battery indicator. To display a battery indicator, use this CGRAM character. To vary the actual battery indicator displayed, write different bitmaps to the CGRAM bitmap. You now have 7 bitmaps freee for other special characters.

 

When you think about it for a while, you can actually expand this technique to have 8 different "animated characters" displayed all at once. One battery indicator, one hourglass, one signal level indicator, two forming a stereo VU level indicator, one blinking eye, one beer glass being emptied, one 8x8 snake game, and another 8x8 snake game (in a different state than the first one!).

 

If you want an animation in one character position, you only need to use one of the eight custom characters.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Sun. Jul 30, 2017 - 02:53 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
See #89 . (crikey, 89 posts for the simple concept of double indirection?)

 

I saw it and that's what I said I was not following.

 

You said:

clawson wrote:
He's saying you might have defined char 3 as AA, AA, AA, AA, AA, AA, AA, AA ...

 

What does this means? What char 3 is that? DDRAM, CGRAM or what? Can you be more specific? And how that char 3 is declared?

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

Oh come on. Just read and think for once. There's spoon feeding then there's spoon feeding!
.
If you just "can't get" this feature then forget about trying to use it. Already it's clear to me that it's not going to deliver your final goal here anyway.
.
The big 'A' you show in #69 looks like it would need 13 new characters all defined and onscreen at once. You have only 8.

Last Edited: Sun. Jul 30, 2017 - 03:09 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Maybe an illustration can clear things up..

 

Taking your sketch of how you want to display a big "A" in 5x4 character cells, how many different special characters do you need? Lets put numbers on them!

 

 

Blank cells don't need any special characters. Next, some cells above have the same number because they use the same special character. Finally, your LCD probably already has a block character (all pixels set) in CGROM so you don't need a special character for the cells marked 14.

 

As Cliff says, you need 13 special characters, all at once. The 44780 on your display can only handle 8 at a time.

 

If you make 12 to instead look like 11 you've saved one special character.If you get rid of 7 and 8 you've saved two more. Make 3 look like 11 and that's another one. Then e.g. make 10 and 13 look like the 14s and you're home free.

But that is for one "big character" of your daughters name.

 

You either have to 

  • Get a GLCD, or
  • Devise a scheme where you use simpler character cell components. But eve "only horizontal and vertical lines - 4 angles, two lines and one cross" could not get you there. You'd need some non-vertical/horizontal also. And again you're over the limit of 8 special characters.

 

This falls back on the thing we repeat here ever so often: First plan what you want to do, investigate how it can be done and what hardware and software requirements you have, then acquire the hardware  and then do it. You've started at the wrong end.

 

If your requirement still stands (your daughters name in big letters) then get a GLCD. To get big letters you will need to pay more  (probably much more) for the GLCD than you did for  the character LCD.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Johan, but that's just the A. He said "BIA" and while the I may be possible with existing blocks a big B will require as much as A.
.
A GLCD could even have a picture of Bia.

Last Edited: Sun. Jul 30, 2017 - 04:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Johan, but that's just the A.

Gee, I wish [etc]... ;-)

Wait..

JohanEkdahl wrote:
But that is for one "big character" of your daughters name.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Ok, I'll give up on this idea!

 

I'll think about something else to make with the LCD!

I'm doing this now because next year (school year that starts in September) I'll be finishing my graduation and I'll need an LCD to show some information of my project that, if teachers agree, will be an antenna analyser or a Direction Finder! So I'm trying to get myself a bit ahead of schedule in terms of getting some basic knowledge with Mega328 and LCD!

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

I'm confused....

I was under the impression that you have 8051 knowledge - which should make using the AVR pretty easy, and you have used AVR...LOTS of them based on this:

 

PsySc0rpi0n wrote:
Yes, already fixed! I have one other experienced "net" friend in IRC channels that already helped me sorting this out! I worked with a lot of AVRs in the past! And yes, I was reading that same link I found through Google but haven't finished the reading!

To which storing stuff in the AVR FLASH memory should be a simple task.

 

PsySc0rpi0n wrote:
Ok, I'll give up on this idea! I'll think about something else to make with the LCD!

 

And after 98+ posts you elect to 'give up' on this and move on to a GLCD!? surpriseangry

 

Since it would appear that this whole thread was a waste of time in many respects how about you give us some background on what you DO know so we can answer accordingly in the future?

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

jgmdesign wrote:
And after 98+ posts you elect to 'give up' on this and move on to a GLCD!?

It has to be said that it was done on several resident 'freaks advice.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

jgmdesign wrote:

I'm confused....

I was under the impression that you have 8051 knowledge - which should make using the AVR pretty easy, and you have used AVR...LOTS of them based on this:

 

PsySc0rpi0n wrote:
Yes, already fixed! I have one other experienced "net" friend in IRC channels that already helped me sorting this out! I worked with a lot of AVRs in the past! And yes, I was reading that same link I found through Google but haven't finished the reading!

To which storing stuff in the AVR FLASH memory should be a simple task.

 

PsySc0rpi0n wrote:
Ok, I'll give up on this idea! I'll think about something else to make with the LCD!

 

And after 98+ posts you elect to 'give up' on this and move on to a GLCD!? surpriseangry

 

Since it would appear that this whole thread was a waste of time in many respects how about you give us some background on what you DO know so we can answer accordingly in the future?

 

Jim

 

jgmdesign I mistyped that sentence you made red! I was saying that a friend of mine in IRC channels, that worked a lot in the past with AVRs, helped me fixing that problem! I'm sorry for my mistake typing!

 

I have worked with 8051 but maybe you understood it the wrong way! I worked with 8051 in school context! We did a small game using an 8051, an LCD (16 x 2) and a 2 digit 7 segment display. I never worked in this area except for school purposes!

 

I said I'm giving up because as far as I understood, I can't draw my daughters name (3 big chars) with an LCD. So, why bother with something that I know it cannot be done?

 

You guys are always saying you waste your precious time with me. Well, it might have been wasted time for you, but I learnt quite some stuff in this thread. And if you think like that, then you always waste time when you teach/help others with things you already know! In other words, you only wouldn't be wasting time if you were discussing subjects you also don't know!

 

Ok, and as a personal note, I never worked in this area, never had any knowledge on electronics/micro-controllers and I only got the interest after in school we learned about micro-controllers! I also never worked with programming, except when I learned in school! So basically, this all came because of school!

 

I work in the fabrics sector, I draw patterns for almost every piece of clothe you can think about with the help of dedicated CAD software! I started studying again at the age of 31 after over 11 years after leaving school! Now I'm trying to graduate in Electrical Engineering in the branch of Electronics and Telecomms! And probably next ear I'll complete graduation!

 

Sorry for not clearing this info sooner!

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

Alternately, you could display 1 character (using only 8 special characters at a time as proposed by Johan in post #95) of the name at a time, hold it a couple of seconds and then display the next by changing the custom chars and the contents of that portion of the DDRAM.

 

 Or perhaps doing something like loop of the characters displaying one on each pass through the loop:

    B       display for first pass

      I     display for second pass

        A   display on third pass

then repeat, may give the "illusion" that they are all present. (

I do not have a character display to test to see if the timing would allow persistence of vision to make this work effectively.)

David

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

PsySc0rpi0n wrote:
You guys are always saying you waste your precious time with me. Well, it might have been wasted time for you, but I learnt quite some stuff in this thread.

 

So, that's what matters. There are people here from many different cultures and with different personalities. Some are very direct, for them it's perfectly normal, for others it may seem harsh, this is because of culture shock, mostly, so don't take it personally. Good luck with the project.

 

Edit:

frog_jr wrote:
Or perhaps doing something like loop of the characters displaying one on each pass through the loop: B display for first pass I display for second pass A display on third pass then repeat, may give the "illusion" that they are all present. ( I do not have a character display to test to see if the timing would allow persistence of vision to make this work effectively.)

 

This seems a good idea, you can divide the picture in frames, each one having only 8 custom characters, the rest blank. It will probably flicker badly, but it might be possible.

Last Edited: Sun. Jul 30, 2017 - 08:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:
Edit: frog_jr wrote: Or perhaps doing something like loop of the characters displaying one on each pass through the loop: B display for first pass I display for second pass A display on third pass then repeat, may give the "illusion" that they are all present. ( I do not have a character display to test to see if the timing would allow persistence of vision to make this work effectively.)   This seems a good idea, you can divide the picture in frames, each one having only 8 custom characters, the rest blank. It will probably flicker badly, but it might be possible.

 

I consider that a fairly bad idea, with small probability of success. Liquid crystal displays are not like LEDs. They need on/off-times (sort of PWM, but don't take that too literally). This is all taken care of by the 44780. (If you look in the Hitachi data sheet you will see mention of "bias" and this is what I'm talking about.)

 

I see two outcomes as most probable:

  • You will, in every character cell used, see a mix of the characters ('B', 'I', and 'A' all superimposed on one another) - likely very faint, or
  • You will see almost nothing, perhaps some flickering.

 

Add to this that your brain (and BIAs!) is a fantastic integrating machine (that's why you perceive film/TV as smoothly moving although it is e.g. 25 frames per second of still images - it's your brain doing that, not the TV set).

 

I would consider the experiment likely to be wasted time, if the goal is to geet something that works.

 

If the goal of the experiment is to see how bad it gets, then do go ahead. And please tell us what the results are! (Seriously! I'm curious!)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

PsySc0rpi0n wrote:
For instance, my daughter's first name is BIA! So I wanted to draw each character using 5 columns and 4 rows (LCD has 4 rows) for each char.
 

Back to your quest.

This is what cross in my mind. Maybe you can get a better idea after looking at this. Please take a look.

 

I'm not sure how to upload a video here so I zip it.

 

 

MG

Attachment(s): 

I don't know why I'm still doing this hobby

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

I'm sorry if this out of topic.

 

JohanEkdahl wrote:
If you want an animation in one character position, you only need to use one of the eight custom characters.

Challenge accepted!

The video is in the attachment.

 

The code:

const PROGMEM unsigned char custom_char[]={
0x0e, 0x1b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1f,
0x0e, 0x1b, 0x11, 0x11, 0x11, 0x11, 0x1f, 0x1f,
0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1f, 0x1f, 0x1f,
0x0e, 0x1b, 0x11, 0x11, 0x1f, 0x1f, 0x1f, 0x1f,
0x0e, 0x1b, 0x11, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
0x0e, 0x1b, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
0x0e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f};

void load_cust_char(unsigned char index)
{
 for(uint8_t i=0;i<8;i++) lcd_data(pgm_read_byte_near(&custom_char[i + index * 8]));
}

...

int main(void)
{
 Lcd_PutStr(0, 0, "Custom Font");
 Lcd_PutStr(0, 1, "BATTERY CHARGE");  
 lcd_gotoXY(15,1);
 lcd_data(0);       //first custom char only
    
 while(1)
 {
  for(uint8_t i=0;i<7;i++)
  {
    Lcd_Cmd(0x40);
    load_cust_char(i);
    _delay_ms(300);
  }
 }
}

 

Edit: changed code as EL TANGAS advised. thanks man!

 

 

MG

Attachment(s): 

I don't know why I'm still doing this hobby

Last Edited: Tue. Aug 1, 2017 - 01:18 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But remember what we have been discussing in this thread. You don't need to change update DDRAM. So try this:

 

// put this outside the loop
lcd_gotoXY(15,1);
lcd_data(0);       //first custom char only

 while(1)
 {
  for(uint8_t i=0;i<7;i++)
  {
    Lcd_Cmd(0x40);      //set CGRAM address 0
    load_cust_char(i);
    /*
    lcd_gotoXY(15,1);
    lcd_data(0);       //first custom char only
    */
    _delay_ms(300);
  }
 }

 

Last Edited: Mon. Jul 31, 2017 - 10:26 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MicroGyro wrote:

PsySc0rpi0n wrote:
For instance, my daughter's first name is BIA! So I wanted to draw each character using 5 columns and 4 rows (LCD has 4 rows) for each char.
 

Back to your quest.

This is what cross in my mind. Maybe you can get a better idea after looking at this. Please take a look.

 

I'm not sure how to upload a video here so I zip it.

 

 

MG

 

I liked this idea! Have you used any kind of screen shifting to do that animation?

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

El Tangas wrote:
But remember what we have been discussing in this thread. You don't need to change update DDRAM. So try this:

Done! Code edited!

Thanks man.

 

 

 

 

MG

I don't know why I'm still doing this hobby

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

PsySc0rpi0n wrote:
Have you used any kind of screen shifting to do that animation?
 

Nope. Nothing but print whole screen every 200ms. Just want to show you my idea so I don't really think of the appropiate code. 

 

I don't have idea how to use only 8 CGRAM to do that.

 

Please take a look at the attachment of what I tried to do. I use 1 CGRAM to do battery icon and 3 for AVR text animation. Not sure if this is the right way.But I guess that's what you can do with CGRAM not for the whole screen. Maybe GLCD?

 

 

 

 

Weeks of very poor internet connection is killing me :(

 

 

MG

Attachment(s): 

I don't know why I'm still doing this hobby

Last Edited: Tue. Aug 1, 2017 - 02:15 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, after a few days trying to make anything out of it, I have changed my idea a little bit! I'm now trying to make something a bit more simple which is to print the same name but in a different way.

 

I want now to print the name but with a scrolling up effect and using a big B made of several small Bs like this:

 

B
B B
B  B
B B
B
B B
B  B
B B
B

For now it's only this but starting to print one line at a time, starting from the bottom line of the LCD.

Later I'll try to add the other two chars to the mix.

 

But I'm still struggling with the code to correctly set the internal LCD pointer to the correct positions!

 

I have this so far and it is not working yet:

#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "lcd.h"

int main(void){
   char *chars[4]={"B", "B B", "B  B", "B B"};
   int j = 0, m = 3;

   lcd_init(LCD_DISP_ON);
   lcd_clrscr();

   _delay_ms(1000);

   for(int k = 0; k < 2; k++){ //2 halves of big B- Upper side is equal do lower side
      lcd_gotoxy(0, m);
      for(int i = 0; i < 4; i++){ //each variable index
         while(chars[i][j] != '\0'){ //run until the each of each index
            lcd_putc(chars[i][j++]);
         }
         j = 0, m--;
         _delay_ms(250);
      }
      lcd_gotoxy(0,0); //debug line
      lcd_puts("M val:"); //debug line
      lcd_gotoxy(6, 0); //debug line
      lcd_putc(m); //debug line
      _delay_ms(500); //debug line
   }
   for(;;);
   //return 0;
}

Any help is appreciated. And I'm sorry if the changes in my mind are going to upset anyone! I just want to make thing simple at the beginning!

 

Thanks

Psy

 

 

Edited;

 

The debug lines are not working correctly either! The "m" value is printing CGRAM custom chars and I never asked it to go to CGRAM memory (the 0x40 command)!

 

 

Edited 2;

post updated!

Last Edited: Wed. Aug 2, 2017 - 10:14 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You define:

char *chars[4]={"B", "B B", "B  B", "B B"};

Then you do:

while(chars[i][j] != '\0'){ //run until the each of each index
      lcd_putc(chars[i][j++]);

Isn't that 2 dimensional array? Didn't you get compiler warning with that?

 

What I did in my example is nothing but printing the whole screen (lines ?) each time and update it after about 200ms.

       Lcd_PutStr(0, 0, "     "); //col 0 row 0
       Lcd_PutStr(0, 1, "     "); //col 0 row 1
       Lcd_PutStr(0, 2, "     "); //col 0 row 2
       Lcd_PutStr(0, 3, "     "); //col 0 row 3
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, "     ");
       Lcd_PutStr(0, 1, "     ");
       Lcd_PutStr(0, 2, "     ");
       Lcd_PutStr(0, 3, "BBBB ");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, "     ");
       Lcd_PutStr(0, 1, "     ");
       Lcd_PutStr(0, 2, "BBBB ");
       Lcd_PutStr(0, 3, "B   B");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, "     ");
       Lcd_PutStr(0, 1, "BBBB ");
       Lcd_PutStr(0, 2, "B   B");
       Lcd_PutStr(0, 3, "BBBB ");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, "BBBB ");
       Lcd_PutStr(0, 1, "B   B");
       Lcd_PutStr(0, 2, "BBBB ");
       Lcd_PutStr(0, 3, "B   B");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, "B   B");
       Lcd_PutStr(0, 1, "BBBB ");
       Lcd_PutStr(0, 2, "B   B");
       Lcd_PutStr(0, 3, "BBBB ");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, "BBBB ");
       Lcd_PutStr(0, 1, "B   B");
       Lcd_PutStr(0, 2, "BBBB ");
       Lcd_PutStr(0, 3, "     ");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, "B   B");
       Lcd_PutStr(0, 1, "BBBB ");
       Lcd_PutStr(0, 2, "     ");
       Lcd_PutStr(0, 3, " III ");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, "BBBB ");
       Lcd_PutStr(0, 1, "     ");
       Lcd_PutStr(0, 2, " III ");
       Lcd_PutStr(0, 3, "  I  ");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, "     ");
       Lcd_PutStr(0, 1, " III ");
       Lcd_PutStr(0, 2, "  I  ");
       Lcd_PutStr(0, 3, "  I  ");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, " III ");
       Lcd_PutStr(0, 1, "  I  ");
       Lcd_PutStr(0, 2, "  I  ");
       Lcd_PutStr(0, 3, "  I  ");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, "  I  ");
       Lcd_PutStr(0, 1, "  I  ");
       Lcd_PutStr(0, 2, "  I  ");
       Lcd_PutStr(0, 3, " III ");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, "  I  ");
       Lcd_PutStr(0, 1, "  I  ");
       Lcd_PutStr(0, 2, " III ");
       Lcd_PutStr(0, 3, "     ");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, "  I  ");
       Lcd_PutStr(0, 1, " III ");
       Lcd_PutStr(0, 2, "     ");
       Lcd_PutStr(0, 3, "  A  ");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, " III ");
       Lcd_PutStr(0, 1, "     ");
       Lcd_PutStr(0, 2, "  A  ");
       Lcd_PutStr(0, 3, " A A ");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, "     ");
       Lcd_PutStr(0, 1, "  A  ");
       Lcd_PutStr(0, 2, " A A ");
       Lcd_PutStr(0, 3, "A   A");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, "  A  ");
       Lcd_PutStr(0, 1, " A A ");
       Lcd_PutStr(0, 2, "A   A");
       Lcd_PutStr(0, 3, "AAAAA");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, " A A ");
       Lcd_PutStr(0, 1, "A   A");
       Lcd_PutStr(0, 2, "AAAAA");
       Lcd_PutStr(0, 3, "A   A");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, "A   A");
       Lcd_PutStr(0, 1, "AAAAA");
       Lcd_PutStr(0, 2, "A   A");
       Lcd_PutStr(0, 3, "     ");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, "AAAAA");
       Lcd_PutStr(0, 1, "A   A");
       Lcd_PutStr(0, 2, "     ");
       Lcd_PutStr(0, 3, "     ");
       _delay_ms(200);
       
       Lcd_PutStr(0, 0, "A   A");
       Lcd_PutStr(0, 1, "     ");
       Lcd_PutStr(0, 2, "     ");
       Lcd_PutStr(0, 3, "     ");
       _delay_ms(200);

Surely that's ridiculous and not a great way but if you still have plenty of flash left this is the simplest way I guess.

Or you can do it with LUT for more neat code since it only repeated but at different place "text".

As you see you still have 15 column to print at each line which can give you "BOLD" or "Italic" effect, or do what frog_jr show you in post #102 which each character scroll in at different column.

 

Hope it helps.

 

 

MG

I don't know why I'm still doing this hobby

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

@MicroGyro, yeah that was my first approach and it is working. I just want to make a better code using loops!

 

I'm still trying to figure out what is wrong in my code because it is still not printing in the correct lines!

 

About the compilation errors/warnings, no, I'm not getting any warnings or errors!

 

The code I have is this one but as I said it's not yet working but I'll eventually get there!

 

#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "lcd.h"
 
int main(void){
   char *chars[4]={"B", "B B", "B  B", "B B"};
 
   lcd_init(LCD_DISP_ON);
   lcd_clrscr();
 
   for(uint8_t i = 3; i >= 0; i--){
      lcd_gotoxy(0, i);
      for(uint8_t j = 0, k = 0; j <= 3 - i ; j++){
         while(chars[j][k] != '\0')
            lcd_putc(chars[j][k++]);
      }
      _delay_ms(1000);
      lcd_gotoxy(0,0);
      lcd_puts("Debug");
      _delay_ms(1000);
      lcd_clrscr();
   }
   for(;;);
}

 

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

I'm not sure what's your code doing. (@@ )

 

 

 

MG

I don't know why I'm still doing this hobby

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

MicroGyro wrote:

I'm not sure what's your code doing. (@@ )

 

 

 

MG

 

I changed it a bit:

 

#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "lcd.h"
 
int main(void){
   char *chars[4]={"B", "B B", "B  B", "B B"};
 
   lcd_init(LCD_DISP_ON);
   lcd_clrscr();
 
   lcd_gotoxy(0, 3);                                 //go to first position wheren to print
   for(uint8_t i = 3; i >= 0; ){                     //will go trough all LCD lines, in an upwards diraction
      for(uint8_t j = 0, k = 0; j <= 3 - i ; j++){   //will go through all elements of variable chars
         while(chars[j][k] != '\0')                  //will go through all chars of each above element
            lcd_putc(chars[j][k++]);                 //print each char and move to next
         lcd_gotoxy(0, --i);                         //scroll up
      }
      lcd_clrscr();
   }
   for(;;);
}

I can't test the code because I'm at work and I don't know if it is possible to be tested online!

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

A char* array IS a two dimensional array. Think of the argv[] in a normal PC C program for example.

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

Well Sir... I'm not too good with that little star (asterix ?) thing.
Thank you for inform me Sir.
.
MG

I don't know why I'm still doing this hobby

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

Ok guys, I'm having a struggle here!

 

When I use lcd_gotoxy(), supposedly, a command to set DDRAM address should be issued, right?

 

The problem is that I'm calling that command and after that I try to print a number like lcd_putc(5) and it prints whatever is in CGRAM address 5! Why is that?

 

The code is this:

int main(void){
   char *chars[4]={"B", "B B", "B  B", "B B"};

   lcd_init(LCD_DISP_ON);
   lcd_clrscr();
   _delay_ms(250);

   for(;;){
      lcd_gotoxy(0, 3);
      for(uint8_t i = 3; i >= 0; ){
         for(uint8_t j = 0, k = 0; j <= 3 - i ; j++){
            while(chars[j][k] != '\0')
               lcd_putc(chars[j][k++]);
            lcd_gotoxy(13, 0);
            lcd_putc(k);
            lcd_gotoxy(0, --i);
            _delay_ms(1500);
         }
      }
      lcd_clrscr();
   }
}

 

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

PsySc0rpi0n wrote:
I try to print a number like lcd_putc(5) and it prints whatever is in CGRAM address 5! Why is that?

Because that is what your code says.

 

Another example:

lcd_putc(67);

will print what is in the CGRAM/CGROM at position 67, and that is a 'C'. I.e. it prints the character with ASCII value 67.

 

If you want to print the character '3' then it's

lcd_putc('3');

or possibly

lcd_putc(51);

Have a look at any ASCII table available on the Web, e.g. http://www.asciitable.com/ to see what ASCII values correspond to which characters.

 

This is absolute basics about printing characters, and the principle holds for any C program and not only for the 44780 display controller. E.g. if you, in a C program running on your PC, do

printf("%c", 67);

the character 'C' will be output from the program when running it.

 

In the case of the 44780, things are a little different:

 

Instead of the 32 first characters in the table being "unprintable" characters
 

  1. the first eight are your special characters
     
  2. the 9th to 31st might be blanks, or might be special characters. For examples see pages 17-18 of the Hitachi data sheet that I have repeatedly urged you to look at. The actual characters in these positions can vary between displays. (As I understand it a display manufacturer can order 44780s with custom CGROM contents, so see the data sheet for your specific display also. You can always test what is in CGROM of your display by just printing out chars from 0 to 255.)

 

So, the 44780 "character map" is not the same as the standard ASCII character map, but the principle that an output device has a mapping from a numerical char value to a character to display is the same regardless. (And just to make it really clear, I use char to speak about a variable in your program and character to speak about what you see on your display.)

 

Again, the difference between

lcd_putc(3);

and

lcd_putc('3');

is absolute basic C matter.

 

If this is a mystery to you I would suggest that you should start out by learning these principles, and the C programming language, by writing small test programs on a PC for a PC (i.e. the progrm runs von a PC). It is much simpler to learn C that way than to do it using a microcontroller as the running platform.

 

And the eternal (it seems) question:; When will you pick up a textbook on C and read it?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

What is your lcd_gotoxy() and lcd_putc() inside? Maybe something wrong inside?
And I'm still can't understand what's your code doing. Shouldn't you update the whole screen at once for each frame?
.
MG

I don't know why I'm still doing this hobby

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

@JohanEkdahl, I know about the ASCII table and how things are printed in HD44780. I'm just struggling how to print 'k' variable value, since lcd_putc(k) prints a CGRAM custom char and lcd_putc('k') printf the 'k' char itself! I also understood how things works when it comes to printing basic chars, and custom chars and other stuff in HD44780. My question is now how to print the 'k' variable!

 

And yes, I have PDF version of Dennis Ritchie C book and I read it some times!

 

@MicroGyro those 2 functions were written by some experienced gentleman! Peter Fleury, so they are working as supposed!

About the code, I know it's a bit confusing, I'm still trying my self to understand what is wrong with it and how to change it to make what I want!

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

PsySc0rpi0n wrote:
I'm just struggling how to print 'k' variable value

So why not ask about that?!? Above you wanted to print the character '3'.

 

Again, if k happens to be e.g. 68 then you will with 

 lcd_putc(k)

print the character 'D'. If you want to print the value of the variable k, i.e. as a string '68' ,then you must convert your integer variable k to a string with e.g. itoa() or sprintf().

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

JohanEkdahl wrote:

PsySc0rpi0n wrote:
I'm just struggling how to print 'k' variable value

So why not ask about that?!? Above you wanted to print the character '3'.

 

Again, if k happens to be e.g. 68 then you will with 

 lcd_putc(k)

print the character 'D'. If you want to print the value of the variable k, i.e. as a string '68' ,then you must convert your integer variable k to a string with e.g. itoa() or sprintf().

 

It's clear that I cannot express myself well...

 

I never wanted to print the character 3. I always wanted to print the 'k' variable value!

I'm sorry, I'm not the best writer! I'm doing the best I can!

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

Yes, communicating in text is different from communicating with speech. The advantege of text is that you can compose your text, take a break, come back and read it with the mindset "how will this be understood at the other end?".

Don't type your immediate thoughts into a post here as if you were speaking to someone in person. That is doomed to cause misunderstandings and confusion.

Anyway, it's itoa() or sprintf() you want..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Sat. Aug 5, 2017 - 11:10 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Johan I think he's looking for itoa() to convert the binary value in 'k' to ASCII printables.
.
The problem here seems to be trying to program an AVR in C without having first learned the basics of C (which is far easier done by cutting the AVR out of the loop and done on a PC alone).

Last Edited: Sat. Aug 5, 2017 - 11:16 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:

@JohanEkdahl, I know about the ASCII table and how things are printed in HD44780. I'm just struggling how to print 'k' variable value, since lcd_putc(k) prints a CGRAM custom char and lcd_putc('k') printf the 'k' char itself! I also understood how things works when it comes to printing basic chars, and custom chars and other stuff in HD44780. My question is now how to print the 'k' variable!

 

And yes, I have PDF version of Dennis Ritchie C book and I read it some times!

 

@MicroGyro those 2 functions were written by some experienced gentleman! Peter Fleury, so they are working as supposed!

About the code, I know it's a bit confusing, I'm still trying my self to understand what is wrong with it and how to change it to make what I want!

 

If you are sure that k is a single digit, that is, between 0 and 9, you can do lcd_putc(k+'0').

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

clawson wrote:
Johan I think he's looking for itoa() to convert the binary value in 'k' to ASCII printables.

So do I, and I have said so twice above.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

JohanEkdahl wrote:
Yes, communicating in text is different from communicating with speech. The advantege of text is that you can compose your text, take a break, come back and read it with the mindset "how will this be understood at the other end?". Don't type your immediate thoughts into a post here as if you were speaking to someone in person. That is doomed to cause misunderstandings and confusion. Anyway, it's itoa() or sprintf() you want..

 

That will be always an unknown... Nobody can predict what's going on in other's mind! And you bet I read my own text more than once and I got back a lot of times to replace words here and there and fix errors and so on and on! But it looks like it's never enough. The mistake is always on my side!

 

 

@clawson

I already said more than once that I have the basics of C, that I know about the ASCII table, I know how things are printed in terms of '%c', '%s' and so on, but I'm not an expert in any of the subjects! Neither C neither micro-controllers. And as this is the first time that I'm going through this particular situation of printing an integer that a variable is holding, I cannot guess, by magic, the solution, however, this is always considered lack of basic knowledge! The need of converting an integer to a char to be printed in a uC is not related with C, basics of C or advanced knowledge of C. In my opinion it is related to a specific need of HD44780. Any knowledge on C I could ever have, would tell me that that would need to be converted to a char to be printed!

Anyway, I'll take the blame, as usual.

 

Also, I would never need to convert an integer to a char to print the value if I was coding in a PC, so that would be useless in this situation!

 

 

 

 

El Tangas wrote:

PsySc0rpi0n wrote:

@JohanEkdahl, I know about the ASCII table and how things are printed in HD44780. I'm just struggling how to print 'k' variable value, since lcd_putc(k) prints a CGRAM custom char and lcd_putc('k') printf the 'k' char itself! I also understood how things works when it comes to printing basic chars, and custom chars and other stuff in HD44780. My question is now how to print the 'k' variable!

 

And yes, I have PDF version of Dennis Ritchie C book and I read it some times!

 

@MicroGyro those 2 functions were written by some experienced gentleman! Peter Fleury, so they are working as supposed!

About the code, I know it's a bit confusing, I'm still trying my self to understand what is wrong with it and how to change it to make what I want!

 

If you are sure that k is a single digit, that is, between 0 and 9, you can do lcd_putc(k+'0').

 

Yes, 'k' is holding a value between 0 and 4, so it shouldn't be a problem. But I got my situation solved now with itoa().

Last Edited: Sat. Aug 5, 2017 - 07:12 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
The need of converting an integer to a char to be printed in a uC is not related with C, basics of C or advanced knowledge of C.

 

Of course it is. Just go to a PC and try with the standard C function putchar(). Nothing to do with MCUs or the HD44780. What you need to understand is the difference between 1 and '1'.

 

edit: also, '...' used on a variable doesn't evaluate that variable. It gives the ASCII code of the character inside. If your variable name had more than one character, it would fail to even compile. So, you see, this is basic C knowledge you didn't have.

Last Edited: Sat. Aug 5, 2017 - 08:57 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:
What you need to understand is the difference between 1 and '1'.

My point entirely.

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

El Tangas wrote:

PsySc0rpi0n wrote:
The need of converting an integer to a char to be printed in a uC is not related with C, basics of C or advanced knowledge of C.

 

Of course it is. Just go to a PC and try with the standard C function putchar(). Nothing to do with MCUs or the HD44780. What you need to understand is the difference between 1 and '1'.

 

 

 

I know the difference between 1 and '1'... Please stop saying I don't know the difference between chars, integers and ASCII table correspondence. This starts to be exhausting to hear the same over and over again! 

 

And a putchar() function takes an integer as an argument but in this case, you cannot compare putchar() from standard C with lcd_putchar() from pfleury's libraries... They cannot be compared because when lcd_putchar() is called with an integer as an argument, it won't print the corresponding ASCII table char. It will print CGRAM address memory content corresponding to the integer passed to lcd_putc().

 

Anyway, what I would like help with was with my code. I can't figure out a way of doing what I want! I'll explain again because anytime I post here a question, I get all sort of answers  not directly related with my question and conversation deviates from main purpose!

 

I intend to get the following effect on my LCD:

 

 

Line 0 --------------------------

Line 1 --------------------------

Line 2 --------------------------

Line 3 B------------------------

 

------------------------------------------

 

Line 0 --------------------------

Line 1 --------------------------

Line 2 B-------------------------

Line 3 B B----------------------

 

------------------------------------------

 

Line 0 --------------------------

Line 1 B------------------------

Line 2 B B----------------------

Line 3 B  B---------------------

 

------------------------------------------

 

Line 0 B-----------------------

Line 1 B B---------------------

Line 2 B  B--------------------

Line 3 B B---------------------

 

------------------------------------------

 

Line 0 B B--------------------

Line 1 B  B-------------------

Line 2 B B--------------------

Line 3 B----------------------

 

------------------------------------------

 

Line 0 B  B-------------------

Line 1 B B--------------------

Line 2 B----------------------

Line 3 B B--------------------

 

------------------------------------------

 

Line 0 B B--------------------

Line 1 B----------------------

Line 2 B B--------------------

Line 3 B  B-------------------

 

------------------------------------------

 

Line 0 B----------------------

Line 1 B B--------------------

Line 2 B  B-------------------

Line 3 B B--------------------

 

------------------------------------------

 

Line 0 B B--------------------

Line 1 B  B-------------------

Line 2 B B--------------------

Line 3 B----------------------

 

 

I did the code the hard way for half of the B but I can't do it using loops!

 

The code I have so far is this, but it prints a P and it only scrolls up until the P is complete! Then it starts all over again!

#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdlib.h>
#include "lcd.h"

int main(void){
   char *chars[4]={"B", "B B", "B  B", "B B"};

   lcd_init(LCD_DISP_ON);
   lcd_clrscr();
   _delay_ms(250);

   for(;;){
      lcd_gotoxy(0, 3);
      for(uint8_t i = 3; i >= 0; ){
         for(uint8_t j = 0, k = 0; j <= 3 - i-- ; j++){

            while(chars[j][k] != '\0')
               lcd_putc(chars[j][k++]);

            k = 0;
            lcd_gotoxy(0, i);
            _delay_ms(1000);
         }

         lcd_clrscr();
         i = 3;
         lcd_gotoxy(0, 3);
      }
   }
}

 

And a video to better ilustrate

https://www.youtube.com/watch?v=...

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

You need to divide the problem in smaller problems. I suggest that you start by writing a function, that from array

 

char *chars[4]={"BB", "B B", "B  B", "B B", "BB"};

writes the lines from index "start" to index "end". Prototype:

 

void printlines (char** chars, int start, int end);

So, if you call printline(chars, 2, 4) would print:

 

B  B
B B
BB

 

Once this is done and working, we can continue.

 

Edit:btw, I think the library has a lcd_puts() function, you should use that to print each line, instead of multiple calls to lcd_putc().

Last Edited: Sat. Aug 5, 2017 - 10:14 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:

You need to divide the problem in smaller problems. I suggest that you start by writing a function, that from array

 

char *chars[4]={"BB", "B B", "B  B", "B B", "BB"};

writes the lines from index "start" to index "end". Prototype:

 

void printlines (char** chars, int start, int end);

So, if you call printline(chars, 2, 4) would print:

 

B  B
B B
BB

 

Once this is done and working, we can continue.

 

 

Is it this what you mean?

 

void print_array(char *array[], uint8_t start, uint8_t end){
   for (uint8_t j = 0; start <= end; start++){
      while(chars[start][j] != '\0')
         lcd_putc(chars[start][j++]);
   }
}

 

This does not care about location where to print! The example you gave suggests console printing, therefore, scrolling up is, so to speak, automatic!

Last Edited: Sat. Aug 5, 2017 - 10:18 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
This does not care about location where to print! The example you gave suggests console printing, therefore, scrolling up is, so to speak, automatic!

 

Indeed. So now, solve that problem, it's not difficult, is it? You will probably need global variables with the x and y positions. And use lcd_puts(), if the library has it.

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

Ok, but I think the problem is that one of the loops needs to change the exit condition, so that in the first run, it only prints the 1st array index, in the 2nd run it will print the 1st and the 2nd array indexes and so on! But I'll try!

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

PsySc0rpi0n wrote:

Ok, but I think the problem is that one of the loops needs to change the exit condition, so that in the first run, it only prints the 1st array index, in the 2nd run it will print the 1st and the 2nd array indexes and so on! But I'll try!

 

Yes, but that's why that function is needed. If you pass "start" and "end" equal, it should print only one line. The function doesn't care about anything else. Positioning the cursor, deciding how many lines to print, and which, should be done outside the function.

This is what I mean by dividing the problem into smaller problems.

 

edit: now, probably the simple and lazy way to solve this is to add empty strings beffore and after the real ones:

 

char *chars[4]={"", "", "", "", "BB", "B B", "B  B", "B B", "BB", "", "", "", ""};

this way, you can always print 4 lines starting at coords 0,0. Then you advance through the array, always printing a window of 4 lines.

Last Edited: Sat. Aug 5, 2017 - 10:44 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, I came up with this...

 

Not tested yet... Going to test now!

 

I have the positioning control of the LCD internal pointer inside that function!

 

Will test while you see my post.

 

void print_array(char *array[], uint8_t start, uint8_t end, uint8_t line){
   uint8_t offset = 1;

   for (uint8_t i = 0; start <= end; start++){
      while(array[start][i] != '\0')
         lcd_putc(array[start][i++]);
      if(line != 3)
         lcd_gotoxy(0, line + offset++);
      i = 0;
      _delay_ms(1000);
   }
}

int main(void){
   char *chars[4]={"B", "B B", "B  B", "B B"};

   lcd_init(LCD_DISP_ON);
   lcd_clrscr();

   for( ; ; ){
      for(uint8_t i = 3; i >= 0; i--){
         lcd_gotoxy(0, i);
         print_array(&chars[], 0, 3 - i, i);
      }
   }

 

I'm getting these errors after compiling:

avr-gcc -g -Wall -Os -mmcu=atmega328p -std=c99 -DF_CPU=16000000UL   -c -o test_lcd_mine3.o test_lcd_mine3.c
test_lcd_mine3.c: In function ‘main’:
test_lcd_mine3.c:30:29: error: expected expression before ‘]’ token
          print_array(&chars[], 0, 3 - i, i);
                             ^
test_lcd_mine3.c:30:10: error: too few arguments to function ‘print_array’
          print_array(&chars[], 0, 3 - i, i);
          ^
test_lcd_mine3.c:8:6: note: declared here
 void print_array(char *array[], uint8_t start, uint8_t end, uint8_t line){
      ^
test_lcd_mine3.c:22:10: warning: variable ‘chars’ set but not used [-Wunused-but-set-variable]
    char *chars[4]={"B", "B B", "B  B", "B B"};
          ^
<builtin>: recipe for target 'test_lcd_mine3.o' failed
make: *** [test_lcd_mine3.o] Error 1

 

Last Edited: Sat. Aug 5, 2017 - 11:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's &chars, not &chars[].

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

"B   B" is a rather dangerous initializer for [4]!

 

(while it "fits" you won't be getting \0 at the end) 

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

El Tangas wrote:

It's &chars, not &chars[].

 

 

#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdlib.h>
#include "lcd.h"

void print_array(char *array[], uint8_t start, uint8_t end, uint8_t line){
   uint8_t offset = 1;

   for (uint8_t i = 0; start <= end; start++){
      while(array[start][i] != '\0')
         lcd_putc(array[start][i++]);
      if(line != 3)
         lcd_gotoxy(0, line + offset++);
      i = 0;
      _delay_ms(1000);
   }
}

int main(void){
   char *chars[4]={"B", "B B", "B  B", "B B"};

   lcd_init(LCD_DISP_ON);
   lcd_clrscr();

   for( ; ; ){
      for(uint8_t i = 3; i >= 0; i--){
         lcd_gotoxy(0, i);
         print_array(&chars, 0, 3 - i, i);
      }
   }

 

 

Not working either.

 

avr-gcc -g -Wall -Os -mmcu=atmega328p -std=c99 -DF_CPU=16000000UL   -c -o test_lcd_mine3.o test_lcd_mine3.c
test_lcd_mine3.c: In function ‘main’:
test_lcd_mine3.c:30:22: warning: passing argument 1 of ‘print_array’ from incompatible pointer type
          print_array(&chars, 0, 3 - i, i);
                      ^
test_lcd_mine3.c:8:6: note: expected ‘char **’ but argument is of type ‘char * (*)[4]’
 void print_array(char *array[], uint8_t start, uint8_t end, uint8_t line){
      ^
avr-gcc -g -Wall -Os -mmcu=atmega328p -std=c99 -DF_CPU=16000000UL -Wl,-Map,test_lcd_mine3.map -o test_lcd_mine3.elf test_lcd_mine3.o lcd.c 
avr-objdump -h -S test_lcd_mine3.elf > test_lcd_mine3.lst
avr-objcopy -j .text -j .data -O ihex test_lcd_mine3.elf test_lcd_mine3.hex
avr-objcopy -j .text -j .data -O binary test_lcd_mine3.elf test_lcd_mine3.bin
avr-objcopy -j .text -j .data -O srec test_lcd_mine3.elf test_lcd_mine3.srec
avr-objcopy -j .eeprom --change-section-lma .eeprom=0 -O ihex test_lcd_mine3.elf test_lcd_mine3_eeprom.hex \
|| { echo empty test_lcd_mine3_eeprom.hex not generated; exit 0; }
avr-objcopy: --change-section-lma .eeprom=0x0000000000000000 never used
avr-objcopy -j .eeprom --change-section-lma .eeprom=0 -O binary test_lcd_mine3.elf test_lcd_mine3_eeprom.bin \
|| { echo empty test_lcd_mine3_eeprom.bin not generated; exit 0; }
avr-objcopy: --change-section-lma .eeprom=0x0000000000000000 never used
avr-objcopy -j .eeprom --change-section-lma .eeprom=0 -O srec test_lcd_mine3.elf test_lcd_mine3_eeprom.srec \
|| { echo empty test_lcd_mine3_eeprom.srec not generated; exit 0; }
avr-objcopy: --change-section-lma .eeprom=0x0000000000000000 never used

 

 

clawson wrote:

"B   B" is a rather dangerous initializer for [4]!

 

(while it "fits" you won't be getting \0 at the end) 

 

This is a subject that I do not understand very well, so I cannot talk much about this, but when I initialise the array as "char *chars[4]" I'm initialising an array of 4 "null terminated strings", so I that the number 4 present in that declaration is not determining the amount of chars in each string, rather is determining the amount of strings in that array! I don't know if what I said is correct, but is the idea I have...

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

Ok, I already fixed the array problems.

It should be:

 

Variable declaration

char *chars[4]={"B", "B B", "B  B", "B B"};

 

Function declaration

void print_array(char *array[], uint8_t start, uint8_t end, uint8_t line);

 

Function usage:

print_array(chars, 0, 3 - i, i);

 

or yet:

print_array(&chars[0], 0, 3 - i, i);

 

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

Your code is a bit confusing. If you want to print a string, why use:

      while(array[start][i] != '\0')
         lcd_putc(array[start][i++]);

instead of

    lcd_puts(array[start]);

I'm not familiar with Fleury's library, but it should work, right?

 

And if you just want to move the print position to the start of the next line, why don't you use:

    lcd_putc('\n');

 

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

I can do that, but the problem is not there! The loops are not working yet correctly!

 

After a few loops, only garbage is being printed in the LCD!

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

PsySc0rpi0n wrote:

I can do that, but the problem is not there! The loops are not working yet correctly!

 

After a few loops, only garbage is being printed in the LCD!

 

I understand that, but if your code is messy, people here won't even bother to try and decipher it. If it's clean, it's more likely someone will take a look and help you. So please rewrite it in a cleaner way and the bugs will be easier to find.

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

Ok, I have the code like this:

#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdlib.h>
#include "lcd.h"

void print_array(char *array[], uint8_t start, uint8_t end){
   for(; start <= end; start++){
      lcd_puts(array[start]);
   }
}

int main(void){
   char *chars[4] = {"B", "B B", "B  B", "B B"};

   lcd_init(LCD_DISP_ON);
   lcd_clrscr();

   for( ; ; ){
      for(uint8_t i = 3; i >= 0; i--){
         lcd_gotoxy(0, i);
         print_array(chars, 0, 3 - i);
      }
      _delay_ms(1000);
   }
}

But the loops are still not working! After some loops and some, what looks like, random lcd_gotoxy() calss, it only prints garbage!

Last Edited: Sun. Aug 6, 2017 - 08:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, after compiling the above code and uploading it onto the uC, it only prints garbage!

 

 

 

Edited;

 

I changed the code in some lines but still not good!

 

#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdlib.h>
#include "lcd.h"

void print_array(char *array[], uint8_t start, uint8_t end){
   for(; start <= end; start++){
      lcd_puts(array[start]);
   }
}

int main(void){
   char *chars[4] = {"B", "B B", "B  B", "B B"};

   lcd_init(LCD_DISP_ON);
   lcd_clrscr();

   for( ; ; ){
      for(uint8_t i = 3; i >= 0; i--){
         lcd_gotoxy(0, i);
         print_array(chars, 0, 3 - i);
         _delay_ms(1000);
         if( !i ){
            i = 3;
            lcd_clrscr();
            _delay_ms(500);
         }
      }
      //code is not reaching here
      lcd_gotoxy(0, 3); //debug lines
      lcd_puts("Here"); //debug lines
      _delay_ms(1000);  //debug lines
   }
}

 

There is yet a part of code missing because at some point, each array element is being printed in the same line!

 

This is how the code is running now:

https://www.youtube.com/watch?v=...

 

 

 

 

 

--------------------------edited 2;--------------------------

 

Ok, some more changes in the code and I think I'm closer!

 

#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdlib.h>
#include "lcd.h"

void print_array(char *array[], uint8_t start, uint8_t end, uint8_t curr_line){
   for(; start <= end; start++){
      lcd_puts(array[start]);
      lcd_gotoxy(0, ++curr_line);
   }
}

int main(void){
   char *chars[4] = {"B", "B B", "B  B", "B B"};

   lcd_init(LCD_DISP_ON);
   lcd_clrscr();

   for( ; ; ){
      for(uint8_t i = 3; i >= 0; i--){
         lcd_gotoxy(0, i);
         print_array(chars, 0, 3 - i, i);
         _delay_ms(1000);
         if( !i ){
            i = 3;
            lcd_clrscr();
            _delay_ms(500);
         }
      }
      //I think code is not reaching here
      lcd_gotoxy(0, 3);
      lcd_puts("Here");
      _delay_ms(1000);
   }
}

Video:

https://www.youtube.com/watch?v=...

Last Edited: Sun. Aug 6, 2017 - 09:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In my opinion, when you execute

 

      lcd_gotoxy(0, ++curr_line);

the last time, when curr_line = 3, you call

      lcd_gotoxy(0, 4);

Since 4 is an invalid line number, it's possible the function will have undefined behavior, causing unpredictable results, like printing that extra "B". I think you should get rid of the curr_line variable, and replace that problematic line by

      lcd_putc('\n');

to advance one line.

 

Edit: Ah, yes, your other problem of unreachable code. That is because of this block:

         if( !i ){
            i = 3;
            lcd_clrscr();
            _delay_ms(500);
         }

So, when i reaches 0, you make it 3 again. Then, the i-- of the for loop is executed, and you get i=2. This obeys the for condition i >= 0, so the for doesn't end, it starts again with i=2, that's why you start with 2 lines printed. Then this repeats forever.

 

BTW, you could have easily discovered this by debugging the code, you know... I suppose you're using Atmel Studio? It comes with a powerful debugger, so learn to use it.

Last Edited: Sun. Aug 6, 2017 - 10:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is getting bigger than a Cecil B. DeMille production (Cecil with a whistle on the Ce part). cheeky

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly