[CODE] [C] Simple Butterfly LCD driver

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

Freaks,

Below is the current code I am using in my ButtLoad project to control the LCD. I rewrote the code from Atmel's Butterfly example for size and speed - the resulting code is nice enough with little bloat. The routines are designed for displaying strings out of flash or SRAM only (no direct character writing, etc). I thought it was worth posting here.

Use LCD_Init(); to initialize the driver (routine stolen from Atmel's code :D). To show a string from SRAM use LCD_puts, or for strings located in flash (see my PROGMEM tutorial) use the LCD_puts_f function. Scrolling is automatic if the string is more than six characters long.

The LCD contrast can be use set between 0x00 (lightest) and 0x0F (darkest) via the LCD_CONTRAST_LEVEL(level) macro.

Use as you see fit.

LCD_Driver.c

/*
               BUTTLCD -- Butterfly LCD Driver

               Copyright (C) Dean Camera, 2008

            dean [at] fourwalledcubicle [dot] com
                  www.fourwalledcubicle.com
*/

/*
	This is a basic driver for the Butterfly LCD. It offers the ability to
	change the contrast and display strings (scrolling or static) from flash
	or SRAM memory only.
	
	This has been completly rewritten from the Atmel code; in this version, as
	much processing as possible is performed by the string display routines
	rather than the interrupt so that the interrupt executes as fast as possible.
*/

#define INC_FROM_DRIVER
#include "LCD_Driver.h"

//                                  LCD Text            + Nulls for scrolling + Null Termination
static volatile char     TextBuffer[LCD_TEXTBUFFER_SIZE + LCD_DISPLAY_SIZE    + 1] = {};
static volatile uint8_t  StrStart        = 0;
static volatile uint8_t  StrEnd          = 0;
static volatile uint8_t  ScrollCount     = 0;
static volatile uint8_t  UpdateDisplay   = false;
static volatile uint8_t  ShowColons      = false;
       volatile uint8_t  ScrollFlags     = 0;

const           uint16_t LCD_SegTable[] PROGMEM =
{
    0xEAA8,     // '*'
    0x2A80,     // '+'
    0x4000,     // ','
    0x0A00,     // '-'
    0x0A51,     // '.' Degree sign
    0x4008,     // '/'
    0x5559,     // '0'
    0x0118,     // '1'
    0x1e11,     // '2
    0x1b11,     // '3
    0x0b50,     // '4
    0x1b41,     // '5
    0x1f41,     // '6
    0x0111,     // '7
    0x1f51,     // '8
    0x1b51,     // '9'
    0x0000,     // ':' (Not defined)
    0x0000,     // ';' (Not defined)
    0x8008,     // '<'
    0x1A00,     // '='
    0x4020,     // '>'
    0x0000,     // '?' (Not defined)
    0x0000,     // '@' (Not defined)
    0x0f51,     // 'A' (+ 'a')
    0x3991,     // 'B' (+ 'b')
    0x1441,     // 'C' (+ 'c')
    0x3191,     // 'D' (+ 'd')
    0x1e41,     // 'E' (+ 'e')
    0x0e41,     // 'F' (+ 'f')
    0x1d41,     // 'G' (+ 'g')
    0x0f50,     // 'H' (+ 'h')
    0x2080,     // 'I' (+ 'i')
    0x1510,     // 'J' (+ 'j')
    0x8648,     // 'K' (+ 'k')
    0x1440,     // 'L' (+ 'l')
    0x0578,     // 'M' (+ 'm')
    0x8570,     // 'N' (+ 'n')
    0x1551,     // 'O' (+ 'o')
    0x0e51,     // 'P' (+ 'p')
    0x9551,     // 'Q' (+ 'q')
    0x8e51,     // 'R' (+ 'r')
    0x9021,     // 'S' (+ 's')
    0x2081,     // 'T' (+ 't')
    0x1550,     // 'U' (+ 'u')
    0x4448,     // 'V' (+ 'v')
    0xc550,     // 'W' (+ 'w')
    0xc028,     // 'X' (+ 'x')
    0x2028,     // 'Y' (+ 'y')
    0x5009,     // 'Z' (+ 'z')
    0x1441,     // '['
    0x8020,     // '\'
    0x1111,     // ']'
    0x0000,     // '^' (Not defined)
    0x1000      // '_'
};

// ======================================================================================

/*
 NAME:      | LCD_Init
 PURPOSE:   | Initializes the Butterfly's LCD for correct operation, ready to display data
 ARGUMENTS: | None
 RETURNS:   | None
*/
void LCD_Init(void)
{
	// Set the initial contrast level to maximum:
	LCD_CONTRAST_LEVEL(0x0F);

    // Select asynchronous clock source, enable all COM pins and enable all segment pins:
    LCDCRB  = (1<<LCDCS) | (3<<LCDMUX0) | (7<<LCDPM0);

    // Set LCD prescaler to give a framerate of 64Hz:
    LCDFRR  = (0<<LCDPS0) | (3<<LCDCD0);    

	// Enable LCD and set low power waveform, enable start of frame interrupt:
    LCDCRA  = (1<<LCDEN) | (1<<LCDAB) | (1<<LCDIE);
}

/*
 NAME:      | LCD_puts
 PURPOSE:   | Displays a string from flash onto the Butterfly's LCD
 ARGUMENTS: | Pointer to the start of the flash string
 RETURNS:   | None
*/
void LCD_puts_f(const char *FlashData)
{
	/* Rather than create a new buffer here (wasting RAM), the TextBuffer global
	   is re-used as a temp buffer. Once the ASCII data is loaded in to TextBuffer,
	   LCD_puts is called with it to post-process it into the correct format for the
	   LCD interrupt.                                                                */

	strcpy_P((char*)&TextBuffer[0], FlashData);
	LCD_puts((char*)&TextBuffer[0]);
}

/*
 NAME:      | LCD_puts
 PURPOSE:   | Displays a string from SRAM onto the Butterfly's LCD
 ARGUMENTS: | Pointer to the start of the SRAM string
 RETURNS:   | None
*/
void LCD_puts(const char *Data)
{
	uint8_t LoadB       = 0;
	uint8_t CurrByte;

	do
	{
		CurrByte = *(Data++);
		
		switch (CurrByte)
		{
			case 'a'...'z':
				CurrByte &= ~(1 << 5);                   // Translate to upper-case character
			case '*'...'_':	                             // Valid character, load it into the array
				TextBuffer[LoadB++] = (CurrByte - '*');
				break;
			case 0x00:                                   // Null termination of the string - ignore for now so the nulls can be appended below
				break;
			default:                                     // Space or invalid character, use 0xFF to display a blank
				TextBuffer[LoadB++] = LCD_SPACE_OR_INVALID_CHAR;
		}
	}
	while (CurrByte && (LoadB < LCD_TEXTBUFFER_SIZE));

	ScrollFlags = ((LoadB > LCD_DISPLAY_SIZE)? LCD_FLAG_SCROLL : 0x00);

	for (uint8_t Nulls = 0; Nulls < 7; Nulls++)
	  TextBuffer[LoadB++] = LCD_SPACE_OR_INVALID_CHAR;  // Load in nulls to ensure that when scrolling, the display clears before wrapping
	
	TextBuffer[LoadB] = 0x00;                           // Null-terminate string
	
	StrStart      = 0;
	StrEnd        = LoadB;
	ScrollCount   = LCD_SCROLLCOUNT_DEFAULT + LCD_DELAYCOUNT_DEFAULT;
	UpdateDisplay = true;
}

/*
 NAME:      | LCD_vect (ISR, blocking)
 PURPOSE:   | ISR to handle the display and scrolling of the current display string onto the LCD
 ARGUMENTS: | None
 RETURNS:   | None
*/
ISR(LCD_vect, ISR_NOBLOCK)
{
	if (ScrollFlags & LCD_FLAG_SCROLL)
	{
		if (!(ScrollCount--))
		{
			UpdateDisplay = true;
			ScrollCount   = LCD_SCROLLCOUNT_DEFAULT;
		}
	}

	if (UpdateDisplay)
	{
		for (uint8_t Character = 0; Character < LCD_DISPLAY_SIZE; Character++)
		{
			uint8_t Byte = (StrStart + Character);

			if (Byte >= StrEnd)
			  Byte -= StrEnd;
			
			LCD_WriteChar(TextBuffer[Byte], Character);
		}
		
		if ((StrStart + LCD_DISPLAY_SIZE) == StrEnd)    // Done scrolling message on LCD once
		  ScrollFlags |= LCD_FLAG_SCROLL_DONE;
		
		if (StrStart++ == StrEnd)
		  StrStart     = 1;

       if (ShowColons)
            *((uint8_t*)(LCD_LCDREGS_START + 8)) = 0x01;
        else
            *((uint8_t*)(LCD_LCDREGS_START + 8)) = 0x00;

		UpdateDisplay  = false;                         // Clear LCD management flags, LCD update is complete
	}
}

/*
 NAME:      | LCD_WriteChar (static, inline)
 PURPOSE:   | Routine to write a character to the correct LCD registers for display
 ARGUMENTS: | Character to display, LCD character number to display character on
 RETURNS:   | None
*/
static inline void LCD_WriteChar(const uint8_t Byte, const uint8_t Digit)
{
	uint8_t* BuffPtr = (uint8_t*)(LCD_LCDREGS_START + (Digit >> 1));
	uint16_t SegData = 0x0000;

	if (Byte != LCD_SPACE_OR_INVALID_CHAR)              // Null indicates invalid character or space
	  SegData = pgm_read_word(&LCD_SegTable[Byte]);	

	for (uint8_t BNib = 0; BNib < 4; BNib++)
	{
		uint8_t MaskedSegData = (SegData & 0x0000F);

		if (Digit & 0x01)
		  *BuffPtr = ((*BuffPtr & 0x0F) | (MaskedSegData << 4));
		else
		  *BuffPtr = ((*BuffPtr & 0xF0) | MaskedSegData);

		BuffPtr += 5;
		SegData >>= 4;
	}	
}

/*
 NAME:      | LCD_ShowColons
 PURPOSE:   | Routine to turn on or off the LCD's colons
 ARGUMENTS: | Boolean - true to turn on colons
 RETURNS:   | None
*/
void LCD_ShowColons(const uint8_t ColonsOn)
{
	ShowColons    = ColonsOn;
	UpdateDisplay = true;
}

LCD_Driver.h

/*
               BUTTLCD -- Butterfly LCD Driver

               Copyright (C) Dean Camera, 2008

            dean [at] fourwalledcubicle [dot] com
                  www.fourwalledcubicle.com
*/

#ifndef LCDDRIVER_H
#define LCDDRIVER_H

	// INCLUDES:
	#include 
	#include 
	#include 
	#include 
	
	// EXTERNAL VARIABLES:
	extern volatile uint8_t ScrollFlags;
	
	// DEFINES:
	#define LCD_LCDREGS_START          ((uint8_t*)&LCDDR0)
	#define LCD_SPACE_OR_INVALID_CHAR  0xFF
	
	#define LCD_CONTRAST_LEVEL(level)  do{ LCDCCR = (0x0F & level); }while(0)
	#define LCD_WAIT_FOR_SCROLL_DONE() do{ while (!(ScrollFlags & LCD_FLAG_SCROLL_DONE)) {} }while(0)
	
	#define LCD_SCROLLCOUNT_DEFAULT    6
	#define LCD_DELAYCOUNT_DEFAULT     20
	#define LCD_TEXTBUFFER_SIZE        20
	#define LCD_SEGBUFFER_SIZE         19
	#define LCD_DISPLAY_SIZE           6

	#define LCD_FLAG_SCROLL            (1 << 0)
	#define LCD_FLAG_SCROLL_DONE       (1 << 1)	

	// PROTOTYPES:
	void LCD_puts_f(const char *FlashData);
	void LCD_puts(const char *Data);
	void LCD_Init(void);
	void LCD_ShowColons(const uint8_t ColonsOn);
	
	#if defined(INC_FROM_DRIVER)
	  static inline void LCD_WriteChar(const uint8_t Byte, const uint8_t Digit);
	#endif

#endif

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

Last Edited: Wed. Dec 16, 2009 - 03:27 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I downloaded the whole package and gave it a try. I'm loading it to Butterfly using boot loader. With the build from your .zip file, I see a RAM ST displayed on the LCD. But when I built it with my WinAvr environment (no modification), and reloaded it to the Butterfly, I see nothing running (nothing on the screen).

Any idea?

Thanks

ps.
Here is what my WinAvr build looks like:

> "make.exe" all

-------- begin --------
avr-gcc (GCC) 3.3.2
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Compiling: Test.c
avr-gcc -c -mmcu=atmega169 -I. -gdwarf-2 -DF_CPU=8000000UL -Os -I"C:\WinAVR\avr\include" -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -mcall-prologues -Wall -Wstrict-prototypes -Wendif-labels -Winline -Wa,-adhlns=Test.lst -std=gnu99 -MD -MP -MF .dep/Test.o.d Test.c -o Test.o
cc1.exe: warning: `dwarf-2': unknown or unsupported -g option

Compiling: LCD_Driver.c
avr-gcc -c -mmcu=atmega169 -I. -gdwarf-2 -DF_CPU=8000000UL -Os -I"C:\WinAVR\avr\include" -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -mcall-prologues -Wall -Wstrict-prototypes -Wendif-labels -Winline -Wa,-adhlns=LCD_Driver.lst -std=gnu99 -MD -MP -MF .dep/LCD_Driver.o.d LCD_Driver.c -o LCD_Driver.o
cc1.exe: warning: `dwarf-2': unknown or unsupported -g option
LCD_Driver.c:171: warning: return type defaults to `int'
LCD_Driver.c:171: warning: function declaration isn't a prototype
LCD_Driver.c: In function `ISR':
LCD_Driver.c:171: warning: type of `LCD_vect' defaults to `int'
LCD_Driver.c:210: warning: control reaches end of non-void function

Linking: LCDDemo.elf
avr-gcc -mmcu=atmega169 -I. -gdwarf-2 -DF_CPU=8000000UL -Os -I"C:\WinAVR\avr\include" -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -mcall-prologues -Wall -Wstrict-prototypes -Wendif-labels -Winline -Wa,-adhlns=Test.o -std=gnu99 -MD -MP -MF .dep/LCDDemo.elf.d Test.o LCD_Driver.o --output LCDDemo.elf -Wl,-Map=LCDDemo.map,--cref -lm

Creating load file for Flash: LCDDemo.hex
avr-objcopy -O ihex -R .eeprom LCDDemo.elf LCDDemo.hex

Creating load file for EEPROM: LCDDemo.eep
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O ihex LCDDemo.elf LCDDemo.eep

Creating Extended Listing: LCDDemo.lss
avr-objdump -h -S LCDDemo.elf > LCDDemo.lss

Creating Symbol Table: LCDDemo.sym
avr-nm -n LCDDemo.elf > LCDDemo.sym

Size after:
LCDDemo.elf :
section size addr
.data 12 8388864
.text 914 0
.bss 53 8388876
.noinit 0 8388929
.eeprom 0 8454144
Total 979

-------- end --------

> Process Exit Code: 0

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

You need to update your AVRLibC installation - you've got an older one where "ISR" is not defined. Since it is not defined, WinAVR just treats it as a standard int function, and so it does not handle the ISR interrupt vector.

Download the latest AVRLibC binaries from http://download.savannah.gnu.org... and extract over the top of the old ones (extract to WinAVR folder, overwrite existing files).

If you really do not wish to update for some reason, then either change "ISR" to "SIGNAL" or use my "Better GCC Interrupt Macro", available in another post in this tutorial forum.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Thanks very much for your help Dean. I download the 1.4.5 libc and it works fine now :)

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

I've just updated my first post with my latest code.

I've reduced the code footprint quite a lot, and eliminated the segment buffering (unneeded since the update time is under a few milliseconds). Total ISR time has been reduced, and now the LCD routine can be interrupted by other ISRs. I've coded the interrupt routine in such a way that it cannot interrupt itself, preventing stack overflows.

Eliminating the segment buffering has greatly reduced the RAM requirements of the driver.

Feedback welcome!

EDIT: I've created a simple test file, and linked it against both Atmel and my own driver:

int main(void)
{
    LCD_Init();
	
	LCD_puts_f(PSTR("AVR BUTTERFLY GCC"));
	LCD_puts("AVR BUTTERFLY GCC");

	for (;;) {}
	
	return 0;
}

My Driver:

Program:     810 bytes (4.9% Full)
(.text + .data + .bootloader)

Data:         50 bytes (4.9% Full)
(.data + .bss + .noinit)

Atmel's Driver:

Program:    1106 bytes (6.8% Full)
(.text + .data + .bootloader)

Data:         71 bytes (6.9% Full)
(.data + .bss + .noinit)

Note that the RAM above includes in both cases the 18 byte SRAM string in the test program as well as the RAM used by the drivers.

I'm yet to come up with a good way to measure the speed of the two drivers, so if anyone has any ideas in that respect please put them here.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Hello!

I'm newbei and I just uploadted this LCD driver to my Butterfly.
And tried to print the "LCD_puts("RAM STRING");" function,
instead of getting "RAM STRING" I've got "RA*+,W" on my LCD.
Any ideas why this driver doesn't work?
I'v tried few 'homemade' drivers and they doesn't work on my Butterfly,
but they work on my friends old butterfly.
The time that my LCD works is when I put the original software in it.

Any ideas??

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

That's odd henge - all Butterflies should have identical displays. I've heard of the latest boards having contrast issues, but not incorrect display like you're getting.

1) When did you purchase your Butterfly?
2) Have you made any modifications to the board?
3) What revision of the official firmware did you board use?

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Jeah, it's odd and even odder is that I accedently fixed it.
I changed the LCD framerate from 32 Hz to 64 Hz:
LCDFRR = (3<<LCDCD0); Now text is right on all segments and now
you can see the text from all the angles. Before you couldn't see the
text directly from front.

I tought that my soldering had damaged the board but when I uploaded the original software (rev07
it worked fine. In the rev07 the frame rate is 32 Hz and it works. I hadn't hat the time to figure this out yet.

If someone has an explantion for this, I'd like to hear it.

-henge :shock:

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

Work on my butterfly, but it won't scroll for some reason. All I see on the screen is "FLASH"..but it won't scroll the whole string. Any ideas why? I compiled with winavr

Chief Tinkerer

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

EDIT: Nevermind, I'm tired.

What is the exact string you're trying to scroll? If the string is less than or equal to 6 characters in length it will stay static, and will only scroll if it is larger than the number of connected character cells on the Butterfly's LCD.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

That's why I am confused. It's set to print the default string in your test.c program which is "FLASH STRING 2". All the screen reads is "FLASH" and if I put in "FLASHSTRING", the screen will read "FLASHS" but won't scroll. Any ideas?

abcminiuser wrote:
EDIT: Nevermind, I'm tired.

What is the exact string you're trying to scroll? If the string is less than or equal to 6 characters in length it will stay static, and will only scroll if it is larger than the number of connected character cells on the Butterfly's LCD.

- Dean :twisted:

Chief Tinkerer

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

Well, if the string is displaying, the ISR is firing correctly - so I assume you've executed a sei(); in your main code. Odd that it isn't scrolling, perhaps I made a copy-paste error somewhere. Can I PM you the updated and known-working driver so you can test it out with your board?

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

You bet, anything helps. I'm a little lost as to why the text won't scroll. I would love to get this driver working.

abcminiuser wrote:
Well, if the string is displaying, the ISR is firing correctly - so I assume you've executed a sei(); in your main code. Odd that it isn't scrolling, perhaps I made a copy-paste error somewhere. Can I PM you the updated and known-working driver so you can test it out with your board?

- Dean :twisted:

Chief Tinkerer

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

I've just updated my original and second posts to new versions of the code. The new code is faster, adds the LCD_WAIT_FOR_SCROLL_DONE() macro - which, as its name implies, causes program execution to halt until the message has scrolled across the LCD - and works with lowercase characters. Obviously the LCD still displays all characters in uppercase, however I've added code to automatically translate the lower case characters into uppercase characters.

New driver size is slightly larger:

Program:     834 bytes (5.1% Full)
(.text + .data + .bootloader)

Data:         50 bytes (4.9% Full)
(.data + .bss + .noinit)

However should be very slightly faster and fuller-featured. Still beats the Atmel driver by 272 bytes - and should be much faster to boot!

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Just tried to compile your test file with latest AVR Studio and WinAVR, here the result:

avr-gcc.exe -mmcu=atmega169p -Wall -gdwarf-2 -O0 -MD -MP -MT LCD_Test.o -MF dep/LCD_Test.o.d -c ../LCD_Test.c
In file included from ../LCD_Test.c:3:
../LCD_Driver.c: In function 'LCD_puts':
../LCD_Driver.c:161: error: 'for' loop initial declaration used outside C99 mode
../LCD_Driver.c: In function '__vector_22':
../LCD_Driver.c:191: error: 'for' loop initial declaration used outside C99 mode
../LCD_Driver.c: In function 'LCD_WriteChar':
../LCD_Driver.c:225: error: 'for' loop initial declaration used outside C99 mode
make: *** [LCD_Test.o] Error 1
Build failed with 3 errors and 0 warnings...

Whats my mistake?

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

You need to turn on the "C99" C standards mode. By default the compiler compiles in a variation of the old "C89" standard which does not allow for variables to be declared inside of a for loop.

If you're using a makefile, change your -std line to:

CSTANDARD = -std=gnu99

If using AVRStudio as a frontend:

Project Menu -> Configuration Options. Select the "Custom Options" tab, in the text box type "-std=gnu99" and press the "Add" button. Click "Ok" to close the window and it should work fine.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Thanks
Its a very usefull driver. :D

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

hmm... doesn't seem to work on this Butterfly here.

The LCD shows nothing... and if examined closely, one can see a slight flickering at one end of the LCD, but nothing else.

Could the frequency of the Butterfly specified in the Makefile be the cause of the problem? :?

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

The makefile frequency shouldn't make any difference, but by all means give it a go. Did you initialize the driver via the Init routine before writing to it? Are you enabling interrupts?

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

thanks! :lol:
adding a sei(); before the init solved the problem.
From the previous comments I somehow got the notion that I am NOT supposed to enable interrupts for the driver to work... I guess it was pretty much the other way.

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

May you help ? I search program that help to create table LCD_SegTable for nation chars.

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

I've got a program I found on the net a while ago to design custom Butterfly LCD characters, which I can post if you like. However, the Butterfly LCD is very limited in what it can display, and you will not be able to add in accents or non-English characters.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

I loaded your program on to butterfly...But i am not getting any text on my lcd...what might be the problem.

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

I can post if you like.
Dean, please send the program.

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

sairahul321 wrote:
I loaded your program on to butterfly...But i am not getting any text on my lcd...what might be the problem.

There could be a variety of reasons - first up, are you sure you've loaded the program correctly, and started it by cycling power and pushing the joystick upwards?

I've attached the Butterfly LCD program. I didn't make it and found it on 'Freaks a while ago, so I've no claims to authorship nor any ability to support it.

- Dean :twisted:

Attachment(s): 

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

I tried to compile this driver and here is my error:

C:/Programme/Atmel/WinAVR/avr/include/avr/signal.h:36:2: warning: #warning "This header file is obsolete. Use ."
../Lcd_driver.c: In function `LCD_Init':
../Lcd_driver.c:113: error: `LCDCCR' undeclared (first use in this function)
../Lcd_driver.c:113: error: (Each undeclared identifier is reported only once
../Lcd_driver.c:113: error: for each function it appears in.)
../Lcd_driver.c:116: error: `LCDCRB' undeclared (first use in this function)
../Lcd_driver.c:116: error: `LCDCS' undeclared (first use in this function)
../Lcd_driver.c:116: error: `LCDMUX0' undeclared (first use in this function)
../Lcd_driver.c:116: error: `LCDPM0' undeclared (first use in this function)
../Lcd_driver.c:119: error: `LCDFRR' undeclared (first use in this function)
../Lcd_driver.c:119: error: `LCDPS0' undeclared (first use in this function)
../Lcd_driver.c:119: error: `LCDCD0' undeclared (first use in this function)
../Lcd_driver.c:122: error: `LCDCRA' undeclared (first use in this function)
../Lcd_driver.c:122: error: `LCDEN' undeclared (first use in this function)
../Lcd_driver.c:122: error: `LCDAB' undeclared (first use in this function)
../Lcd_driver.c:122: error: `LCDIE' undeclared (first use in this function)
../Lcd_driver.c: At top level:
../Lcd_driver.c:191: warning: `LCD_vect' appears to be a misspelled signal handler
../Lcd_driver.c: In function `LCD_WriteChar':
../Lcd_driver.c:232: error: `LCDDR0' undeclared (first use in this function)
make: *** [Lcd_driver.o] Error 1
Build failed with 15 errors and 2 warnings...

can someone help me to fix it?

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

Remove the #include - it's no longer needed as the file includes all its previous functionality.

As for the other errors, it looks like you're not compiling for the MEGA169. Have you set up your environment to compile with the mmcu set to the MEGA169?

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Thanks!
I forgot to set to mega169. My mistake. Now successfully compiled. :P

But after I flashed it to the board, my LCD (STK502) shows nothing :cry:

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

Did you load in the test application?

I've not tested the STK502 with the driver, but if the connections are the same as the Butterfly it should all work just fine. Does anyone here have a STK502 which they've successfully used with my code?

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Did you snable the interrupts?
The first time I started playing with the butterfly I forgot to call 'sti' to enable interrupts... and nothing on the LCD...

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

Thanks. It works! Like Pedro said, i didnt enable the interrupts.

How i want to put like this:

Hello
(lcd clear)
Good Morning!
(lcd clear)

then the screen repeat itself

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

You can use the following snippet to do what you want. It performs an infinite loop, displaying a string from flash memory, waiting for it to scroll across the display, then displaying the next string and waits for that one to scroll, and repeats.

for (;;)
{
LCD_puts_f(PSTR("HELLO"));
LCD_WAIT_FOR_SCROLL_DONE();
LCD_puts_f(PSTR("GOOD MORNING"));
LCD_WAIT_FOR_SCROLL_DONE();
}

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Anytime I try and compile this driver using AVR Studio 4, it locks my machine up. Does anybody else have this problem? Am I doing something wrong?

EDIT: I have solved the lockup problem by upgrading AVR Studio and changing to C99 mode.

Thanks all.

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

Does this driver support the use of the LCD's colons at all? If not, how would I go about enabling them?

Thanks

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

Quote:

Does this driver support the use of the LCD's colons at all? If not, how would I go about enabling them?

It does now, just updated the original post. Now use LCD_ShowColons(0x01) to turn them on, and LCD_ShowColons(0x00) to turn them off. Can't test at the moment, but it should work just fine.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Quote:
It does now, just updated the original post. Now use LCD_ShowColons(0x01) to turn them on, and LCD_ShowColons(0x00) to turn them off. Can't test at the moment, but it should work just fine.

- Dean :twisted:

The code works great.

Thank you very much!!!

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

Dean-

Please excuse my ignorance here, but I am trying to understand a bit about how you turn the colons on and off, but I can't seem to figure it out. The code functions great, i would just like to know a bit more about how it works. I am trying to turn them on and off individually but would like to understand a bit more about character mapping. Feel free to PM me or email me if you would prefer.

Thanks,

Zach

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

Zach,

I had trouble with it also. It's been a long while since I wrote the bulk of the driver, so I can't remember all the specifics. I do remember that each character is 16 bits (each mapping to one of the character LCD segments) which is split into four 4-bit nibbles. Each nibble is loaded into four LCD digit registers spaced five bytes apart, in the low-nibbles for the even digit numbers, and high-nibbles for the odd numbered digits.

All seemed like pure voodoo at the time, but seems to work well so I left it at that. For the "special" characters such as the little arrows along the top of the display and the colons I have no idea, I resorted to using my JTAG to flip the LCD register bits in turn until I found the appropriate bit/register.

Character mapping is as follows from what I can remember:

  HIGH NIBBLE       LOW NIBBLE
[DIGIT1_NIBBLE1 | DIGIT0_NIBBLE1] LCDDR0
[DIGIT3_NIBBLE1 | DIGIT2_NIBBLE1] LCDDR1
[DIGIT5_NIBBLE1 | DIGIT4_NIBBLE1] LCDDR2
[DIGIT1_NIBBLE2 | DIGIT0_NIBBLE2] LCDDR3
[DIGIT3_NIBBLE2 | DIGIT2_NIBBLE2] LCDDR4
[DIGIT5_NIBBLE2 | DIGIT4_NIBBLE2] LCDDR5
[DIGIT1_NIBBLE3 | DIGIT0_NIBBLE3] LCDDR6
[DIGIT3_NIBBLE3 | DIGIT2_NIBBLE3] LCDDR7
[DIGIT5_NIBBLE3 | DIGIT4_NIBBLE3] LCDDR8
[DIGIT1_NIBBLE4 | DIGIT0_NIBBLE4] LCDDR9
[DIGIT3_NIBBLE4 | DIGIT2_NIBBLE4] LCDDR10
[DIGIT5_NIBBLE4 | DIGIT4_NIBBLE4] LCDDR11

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Hello Dean,

i found your LCD-ibrary really useful, but I have a little problem with it.

I just cant't write a character to a specific position on the display, like with LCD_putc().

I tried to use LCD_WriteChar for this and pass it an ASCII-character, but it doesn't print what I was expecting.
I dont really understand what LCD_WriteChar is doing. What do you pass to it?

Could you please help me figure out how to do that?

Thanks :)

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

Finally, a success:
I turned "static inline LCD_WriteChar()" into a plain "LCD_WriteChar()" and defined the following macro:

#define LCD_putc(digit,character) LCD_WriteChar((char)character  - '*', digit)

Not a beauty but it works sufficiently. Maybe somebody finds a more elegant and generic solution :)

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

Hi, Folks:

I found Dean's elegant code for the Butterfly LCD to be very clean and useful, so I've made a few minor modifications in order to add flashing digits and timers to support joystick input.

I've included general-purpose, easy to use routines to initialize and read the joystick, with proper debounce and autorepeat functions (using the LCD frame interrupt as a time base).

I also wrote a new Real Time Clock with a global 6-byte BCD buffer. The buffer provides a time base for dataloggers supporting 1 second, 10 seconds, 1 minute, 10 minutes, 1 hour and 10 hour data sampling intervals. Everything is demonstrated with a stand-alone application that turns the Butterfly into a real-time clock, settable using the joystick.

You might argue that the Butterfly as delivered already provides an RTC, but take a look at that code! Besides, what's the fun in using something out of the box? I've posted the source code in the Projects section and attached the zipped code to this message. Let me know if you have suggestions or problems with any of it!

Cheers, Jim

Attachment(s): 

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

Good daytime!
I'm using LCD driver not for a butterfly, but for another lcd-display (TN Glass, 1/4 duty, 1/3 bias, Operation voltage: 3.0V, 4com*24seg) + mega329 uC. When i try to compile next code, i'm having "LCDDR0 undeclared" problem and can't find why.

Please, help.

main.c

/*
uC: ATmega329
avr-gcc (WinAVR 20081205) 4.3.2
*/

#define F_CPU 4000000UL //FCPU=4MHz
#define MCU atmega329

  
#include 
#include 
#include 

#include 
#include 

int main(void)
{ 
	
	LCD_Init(); 
    
	LCD_puts_f(PSTR("AVR BUTTERFLY GCC")); 
	LCD_puts("AVR BUTTERFLY GCC"); 

	for (;;) {} 
    
	return 0; 
}

My error-list:
Compiling C: main.c
avr-gcc -c -mmcu=atmega329 -I. -gdwarf-2 -DF_CPU=4000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./main.lst -std=gnu99 -Wundef -MMD -MP -MF .dep/main.o.d main.c -o main.o
In file included from main.c:19:
./lcd_driver.c: In function '__vector_22':
./lcd_driver.c:209: error: 'LCDDR0' undeclared (first use in this function)
./lcd_driver.c:209: error: (Each undeclared identifier is reported only once
./lcd_driver.c:209: error: for each function it appears in.)
./lcd_driver.c: In function 'LCD_WriteChar':
./lcd_driver.c:225: error: 'LCDDR0' undeclared (first use in this function)
make.exe: *** [main.o] Error 1

Thanks a lot!
And sorry for my english, if it's bad

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

Sorry, i found problem:
file should be

   // DEFINES: 
   #define LCD_LCDREGS_START          ((uint8_t*)&LCDDR00) 

instead of:

   // DEFINES: 
   #define LCD_LCDREGS_START          ((uint8_t*)&LCDDR0) 

also i enabled interrupts, added sei() after lcd_init(). Is it right? LCD is still off - i thought there should be something abnormal, because of incorrect segment table, but there is nothing :( why?

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

Hello!

I'm newbei and i'm using keypad as input to my butterfly.
i tried to display on my butterfly lcd based on what i've key in from the keypad.

any ideas how this could be works??

This is my keypad 4x4 AVR-GCC C language:

#include

int main()

{

//high nibble for output(columns) low for input(rows);

DDRB=0xF0;

//enable internal pullups for PB0-PB3

PORTB=0x0F;

//Port D for indication only

DDRD=0xFF;

while (1) //loop key check forever

{

//first column

PORTB =0b01111111;

//check for rows and send key number to portD

//instead sending key number to PORTD you can use

// any function that serves pressed button

if (bit_is_set(PINB, 3)) PORTD=1;

if (bit_is_set(PINB, 2)) PORTD=2;

if (bit_is_set(PINB, 1)) PORTD=3;

if (bit_is_set(PINB, 0)) PORTD=4;

//second column

PORTB =0b10111111;

if (bit_is_set(PINB, 3)) PORTD=5;

if (bit_is_set(PINB, 2)) PORTD=6;

if (bit_is_set(PINB, 1)) PORTD=7;

if (bit_is_set(PINB, 0)) PORTD=8;

//third column

PORTB =0b11011111;

if (bit_is_set(PINB, 3)) PORTD=9;

if (bit_is_set(PINB, 2)) PORTD=10;

if (bit_is_set(PINB, 1)) PORTD=11;

if (bit_is_set(PINB, 0)) PORTD=12;

//fourth column

PORTB =0b11101111;

if (bit_is_set(PINB, 3)) PORTD=13;

if (bit_is_set(PINB, 2)) PORTD=14;

if (bit_is_set(PINB, 1)) PORTD=15;

if (bit_is_set(PINB, 0)) PORTD=16;

}

}

Please help me to display any character on my lcd. Crying or Very sad

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

Use my driver. You're trying to drive the LCD segments with normal DC output, which will quickly damage them if you end up getting it working. You need to use my driver, which uses the MEGA169's internal LCD driver circuitry that supplies the correct AC signals to the LCD segments to turn them on correctly.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

what the name of your driver and where can i get it?

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

Quote:

what the name of your driver and where can i get it?

This thread perhaps?

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

what the name of your driver and where can i get it?

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

Use my driver

Quote:

what driver?

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

Use my driver
Quote:

what driver?

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

Have you actually READ this thread?!?! As I say the driver you seek is in the very first post of this thread.

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

Maybe he fails to realize that this is page 3 of the thread...

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

hehehe..
sorry guys...

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

hey there..

the code that dean post on the first page of this forum really help me
but my question is which code i want to use.is it .c or .h.

when i build the .c code using avr studio it stated that this code have error but when i build with .h code there is no error

could someone tell me which code are suitable for this software?(avr studio)

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

You need both .c and .h files. The question reveals that your knowledge of the C programming language is close to none. You should get a good book on C and start reading.

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 still can't build the code

there are errors and warning

these are the error that my avr show when i build that code

Quote:
Build started 25.3.2009 at 23:37:15
avr-gcc.exe -mmcu=atmega169 -Wall -gdwarf-2 -O0 -MD -MP -MT demo1.o -MF dep/demo1.o.d -c ../demo1.c
../demo1.c:2:24: error: LCD_Driver.h: No such file or directory
../demo1.c:5: error: 'LCD_TEXTBUFFER_SIZE' undeclared here (not in a function)
../demo1.c:5: error: 'LCD_DISPLAY_SIZE' undeclared here (not in a function)
../demo1.c:5: error: empty scalar initializer
../demo1.c:5: error: (near initialization for 'TextBuffer')
../demo1.c:6: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'StrStart'
../demo1.c:7: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'StrEnd'
../demo1.c:8: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'ScrollCount'
../demo1.c:9: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'UpdateDisplay'
../demo1.c:10: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'ShowColons'
../demo1.c:11: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'ScrollFlags'
../demo1.c:13: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'LCD_SegTable'
../demo1.c: In function 'LCD_Init':
../demo1.c:82: warning: implicit declaration of function 'LCD_CONTRAST_LEVEL'
../demo1.c:85: error: 'LCDCRB' undeclared (first use in this function)
../demo1.c:85: error: (Each undeclared identifier is reported only once
../demo1.c:85: error: for each function it appears in.)
../demo1.c:85: error: 'LCDCS' undeclared (first use in this function)
../demo1.c:85: error: 'LCDMUX0' undeclared (first use in this function)
../demo1.c:85: error: 'LCDPM0' undeclared (first use in this function)
../demo1.c:88: error: 'LCDFRR' undeclared (first use in this function)
../demo1.c:88: error: 'LCDPS0' undeclared (first use in this function)
../demo1.c:88: error: 'LCDCD0' undeclared (first use in this function)
../demo1.c:91: error: 'LCDCRA' undeclared (first use in this function)
../demo1.c:91: error: 'LCDEN' undeclared (first use in this function)
../demo1.c:91: error: 'LCDAB' undeclared (first use in this function)
../demo1.c:91: error: 'LCDIE' undeclared (first use in this function)
../demo1.c: In function 'LCD_puts_f':
../demo1.c:107: warning: implicit declaration of function 'strcpy_P'
../demo1.c:108: warning: implicit declaration of function 'LCD_puts'
../demo1.c: At top level:
../demo1.c:118: warning: conflicting types for 'LCD_puts'
../demo1.c:108: warning: previous implicit declaration of 'LCD_puts' was here
../demo1.c: In function 'LCD_puts':
../demo1.c:119: error: 'uint8_t' undeclared (first use in this function)
../demo1.c:119: error: expected ';' before 'LoadB'
../demo1.c:120: error: expected ';' before 'CurrByte'
../demo1.c:124: error: 'CurrByte' undeclared (first use in this function)
../demo1.c:131: error: 'LoadB' undeclared (first use in this function)
../demo1.c:136: error: 'LCD_SPACE_OR_INVALID_CHAR' undeclared (first use in this function)
../demo1.c:141: error: 'ScrollFlags' undeclared (first use in this function)
../demo1.c:141: error: 'LCD_FLAG_SCROLL' undeclared (first use in this function)
../demo1.c:143: error: expected ';' before 'Nulls'
../demo1.c:143: error: 'Nulls' undeclared (first use in this function)
../demo1.c:148: error: 'StrStart' undeclared (first use in this function)
../demo1.c:149: error: 'StrEnd' undeclared (first use in this function)
../demo1.c:150: error: 'ScrollCount' undeclared (first use in this function)
../demo1.c:150: error: 'LCD_SCROLLCOUNT_DEFAULT' undeclared (first use in this function)
../demo1.c:150: error: 'LCD_DELAYCOUNT_DEFAULT' undeclared (first use in this function)
../demo1.c:151: error: 'UpdateDisplay' undeclared (first use in this function)
../demo1.c:151: error: 'true' undeclared (first use in this function)
../demo1.c: At top level:
../demo1.c:161: warning: return type defaults to 'int'
../demo1.c: In function 'ISR':
../demo1.c:162: error: 'ScrollFlags' undeclared (first use in this function)
../demo1.c:162: error: 'LCD_FLAG_SCROLL' undeclared (first use in this function)
../demo1.c:164: error: 'ScrollCount' undeclared (first use in this function)
../demo1.c:166: error: 'UpdateDisplay' undeclared (first use in this function)
../demo1.c:166: error: 'true' undeclared (first use in this function)
../demo1.c:167: error: 'LCD_SCROLLCOUNT_DEFAULT' undeclared (first use in this function)
../demo1.c:173: error: 'uint8_t' undeclared (first use in this function)
../demo1.c:173: error: expected ';' before 'Character'
../demo1.c:173: error: 'Character' undeclared (first use in this function)
../demo1.c:175: error: expected ';' before 'Byte'
../demo1.c:177: error: 'Byte' undeclared (first use in this function)
../demo1.c:177: error: 'StrEnd' undeclared (first use in this function)
../demo1.c:180: warning: implicit declaration of function 'LCD_WriteChar'
../demo1.c:183: error: 'StrStart' undeclared (first use in this function)
../demo1.c:184: error: 'LCD_FLAG_SCROLL_DONE' undeclared (first use in this function)
../demo1.c:189: error: 'ShowColons' undeclared (first use in this function)
../demo1.c:190: error: expected expression before ')' token
../demo1.c:190: error: 'LCD_LCDREGS_START' undeclared (first use in this function)
../demo1.c:192: error: expected expression before ')' token
../demo1.c:194: error: 'false' undeclared (first use in this function)
../demo1.c:196: warning: control reaches end of non-void function
../demo1.c: At top level:
../demo1.c:204: warning: type defaults to 'int' in declaration of 'uint8_t'
../demo1.c:204: error: expected ';', ',' or ')' before 'Byte'
../demo1.c:232: warning: type defaults to 'int' in declaration of 'uint8_t'
../demo1.c:232: error: expected ';', ',' or ')' before 'ColonsOn'
In file included from ../demo1.c:253:
c:/winavr/bin/../avr/include/avr/pgmspace.h:857: error: conflicting types for 'strcpy_P'
../demo1.c:107: error: previous implicit declaration of 'strcpy_P' was here
../demo1.c:283: warning: conflicting types for 'LCD_WriteChar'
../demo1.c:283: error: static declaration of 'LCD_WriteChar' follows non-static declaration
../demo1.c:180: error: previous implicit declaration of 'LCD_WriteChar' was here
make: *** [demo1.o] Error 1
Build failed with 67 errors and 11 warnings...

hope you can help me

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

As often the case the only important error in all thta is:

../demo1.c:2:24: error: LCD_Driver.h: No such file or directory 

I'd concentrate on that one first and once you've resolved it I'm guessing the other errors will evaporate.

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

oh ok..
so i must install the LCD driver 1st rite??

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

"install" - what are you talking about?

You go to the first post in this thread. You select all the text under LCD_Driver.c you copy it, you create a blank file called LCD_Driver.c and paste it in then save it. You then do the same with the text under LCD_Driver.h and save that to LCD_Driver.h. You make sure these two files are in the same directory as your other project files. In one of your own .c files where you plan to use functions in LCD_Driver.c you simply add the line:

#include "LCD_Driver.h"

Then in the list of files to be built in the project you add LCD-Driver.c to the list. Now build the project and it should all just work.

Cliff

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

Make sure that a copy of both the .c and the .h file are in the directory used by your AVRStudio project. In the AVR GCC directory tree on the left of AVRStudio click on 'Source Files' and 'Add Existing File(s)' to add the .c file, then in the 'Header Files' also use 'Add Existing File(s)' to add the .h file. Now when you click Compile AVRStudio should be able to find both files.

Smiley

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

i follow what you ask me to do and i can build it.
but the prob is the program shows warning there

Quote:
rm -rf fyp.o fyp.elf dep/* fyp.hex fyp.eep
Build succeeded with 0 Warnings...
avr-gcc.exe -mmcu=atmega169 -Wall -gdwarf-2 -DF_CPU=1000000UL -O0 -fsigned-char -std=gnu99 -MD -MP -MT fyp.o -MF dep/fyp.o.d -c ../fyp.c
In file included from ../fyp.c:2:
../LCD_Driver.h:48:8: warning: no newline at end of file
avr-gcc.exe -mmcu=atmega169 -Wall -gdwarf-2 -DF_CPU=1000000UL -O0 -fsigned-char -std=gnu99 -MD -MP -MT LCD_Driver.o -MF dep/LCD_Driver.o.d -c ../LCD_Driver.c
In file included from ../LCD_Driver.c:21:
../LCD_Driver.h:48:8: warning: no newline at end of file
../LCD_Driver.c:255:3: warning: no newline at end of file

avr-gcc.exe -mmcu=atmega169 fyp.o LCD_Driver.o -lm -o fyp.elf
avr-objcopy -O ihex -R .eeprom fyp.elf fyp.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex fyp.elf fyp.eep || exit 0
c:\WinAVR\bin\avr-objcopy.exe: there are no sections to be copied!

AVR Memory Usage
----------------
Device: atmega169

Program: 1718 bytes (10.5% Full)
(.text + .data + .bootloader)

Data: 33 bytes (3.2% Full)
(.data + .bss + .noinit)

Build succeeded with 3 Warnings...

what the problem with that warning

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

Quote:

warning: no newline at end of file

Well what do you THINK that warning means?

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

Quote:

what the problem with that warning

The problem is exactly what the warning says. There is no newline at the end of the file. How can that be unclear?

IIRC this can be a problem for the some compilers (not seeing the last token in the file). The simple remedy is to edit those files. Go to the last line. Place the caret after that last character on the line. Hit enter. Save the file and exit. Repeat for all files that generate the warning.

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 follow what you ask me to do and i can build it.
but the prob is the program shows warning there

Quote:
rm -rf fyp.o fyp.elf dep/* fyp.hex fyp.eep
Build succeeded with 0 Warnings...
avr-gcc.exe -mmcu=atmega169 -Wall -gdwarf-2 -DF_CPU=1000000UL -O0 -fsigned-char -std=gnu99 -MD -MP -MT fyp.o -MF dep/fyp.o.d -c ../fyp.c
In file included from ../fyp.c:2:
../LCD_Driver.h:48:8: warning: no newline at end of file
avr-gcc.exe -mmcu=atmega169 -Wall -gdwarf-2 -DF_CPU=1000000UL -O0 -fsigned-char -std=gnu99 -MD -MP -MT LCD_Driver.o -MF dep/LCD_Driver.o.d -c ../LCD_Driver.c
In file included from ../LCD_Driver.c:21:
../LCD_Driver.h:48:8: warning: no newline at end of file
../LCD_Driver.c:255:3: warning: no newline at end of file

avr-gcc.exe -mmcu=atmega169 fyp.o LCD_Driver.o -lm -o fyp.elf
avr-objcopy -O ihex -R .eeprom fyp.elf fyp.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex fyp.elf fyp.eep || exit 0
c:\WinAVR\bin\avr-objcopy.exe: there are no sections to be copied!

AVR Memory Usage
----------------
Device: atmega169

Program: 1718 bytes (10.5% Full)
(.text + .data + .bootloader)

Data: 33 bytes (3.2% Full)
(.data + .bss + .noinit)

Build succeeded with 3 Warnings...

what the problem with that warning

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

I'm out.

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

sorry about the double post..
internet connection at my place so slow so it cause error like that

anyway thanks for the advice
my program now work properly without warning
you are really nice people

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

Hye,
I have compile both keypad and lcd butterfly code C in a AVR Studio without warning and error.
But after i downloaded to AVR there was a buzzing sound appear.
Why is it happened?? Is it my coding mistake or AVR problem?

I attach the code for reference. Hope someone can help.. :cry:

Attachment(s): 

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

Look at the Butterfly schematic to see which pin is attached to the piezo element (buzzer) then note which part of you code is toggling that pin at an audio frequency.

Smiley

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

i already change my keypad from PORTB to PORTD and i don't hear any "buzzing" sound.

but my problem now is the LCD doesn't show anything when i download the program to AVR

i'm using LCD driver which i get on the 1st thread of this forum

could anybody help me

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

You really need to look at the Butterfly schematic.

Also read:
http://www.smileymicros.com/down...

Smiley

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

i already look the butterfly schematic but i still got the problem..

my keypad cannot sent data to buttefly lcd

this is my keypad code

Quote:

#include

int main()

{

//high nibble for output(columns) low for input(rows);

DDRB=0xF0;

//enable internal pullups for PB0-PB3

PORTB=0x0F;

//Port D for indication only

DDRD=0xFF;

while (1) //loop key check forever

{

//first column

PORTB =0b01111111;

//check for rows and send key number to portD

//instead sending key number to PORTD you can use

// any function that serves pressed button

if (bit_is_set(PINB, 3)) PORTD=1;

if (bit_is_set(PINB, 2)) PORTD=2;

if (bit_is_set(PINB, 1)) PORTD=3;

if (bit_is_set(PINB, 0)) PORTD=4;

//second column

PORTB =0b10111111;

if (bit_is_set(PINB, 3)) PORTD=5;

if (bit_is_set(PINB, 2)) PORTD=6;

if (bit_is_set(PINB, 1)) PORTD=7;

if (bit_is_set(PINB, 0)) PORTD=8;

//third column

PORTB =0b11011111;

if (bit_is_set(PINB, 3)) PORTD=9;

if (bit_is_set(PINB, 2)) PORTD=10;

if (bit_is_set(PINB, 1)) PORTD=11;

if (bit_is_set(PINB, 0)) PORTD=12;

//fourth column

PORTB =0b11101111;

if (bit_is_set(PINB, 3)) PORTD=13;

if (bit_is_set(PINB, 2)) PORTD=14;

if (bit_is_set(PINB, 1)) PORTD=15;

if (bit_is_set(PINB, 0)) PORTD=16;

}

}

what's the problem of this code because i can compile it on avr studio

is there any additional connection to interface this keypad and this butterfly lcd??

i really appreciate your kindest to help me find this problem

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

I must be misunderstanding your question since both the Butterfly schematics and the 'Butterfly Alternate Pin Uses' document that I provided a link to for you both show that PORTD is connected to the PORTD pad AND to 8 of the LCD pins - so as one should see on the schematic or read in the document, you cannot use PORTD for both the LCD and as an input port at the same time.

And I just looked at your code and now my question is: what function in your code is sending data to the LCD? Earlier you said you changed your keypad from PORTB to PORTD and the buzzing stopped, but your code doesn't show this. Were you trying to turn on individual LCD elements with the write to PORTD?

And looking further back, I see that Dean suggested you use his LCD driver, so now I'm even more confused about what you are asking.

Please answer:
1. Did you try to use Dean's driver?
2. If so, why doe's it not show up in you code listing?
3. If you read the Butterfly Schematics how could you not know that your code would cause the Piezo element to buzz?
4. You said that after you changed ports the buzzing stopped, but you show the same code unchanged?
4. And if you read the Schematics and the Alternate Pin Use document, how could you not know that moving the keypad to PORTD would interfere with the LCD?

Again, I must be missing something in your question.

Smiley

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

oh sorry..
i didn't mention it to you before..
after read the schematic i know that the Piezo element is in PINB5.
It's true that in the early i try to connect my keypad to PORTD but after reading the schematic, i change it back to PORTB because i realize PORTD will interfere the LCD.

my answer for your question..

1. yes, i 'm using dean's driver.
2. i send you the full code of my program include Dean's driver.
3. i already ask my friends.they said maybe the connection from the keypad to butterfly makes the buzzing sound.
your question 4 and 5 i already explain at above

sorry again because sending you the not update program

here i send you my new program

hope i already answer your question..

thanks

Attachment(s): 

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

Your keypad.c code:

#include 
#include "LCD_Driver.h"

int main()

{

//high nibble for output(columns) low for input(rows);

DDRD=0xF0;

//enable internal pullups for PB0-PB3

PORTD=0x0F;

//Port D for indication only

DDRB=0xFF;

while (1) //loop key check forever

	{

		//first column

		PORTD =0b01111111;

		//check for rows and send key number to portD

		//instead sending key number to PORTD you can use

		// any function that serves pressed button

		if (bit_is_set(PIND, 3)) PORTB=1;

		if (bit_is_set(PIND, 2)) PORTB=2;

		if (bit_is_set(PIND, 1)) PORTB=3;

		if (bit_is_set(PIND, 0)) PORTB=4;

		//second column

		PORTD =0b10111111;

		if (bit_is_set(PIND, 3)) PORTB=5;

		if (bit_is_set(PIND, 2)) PORTB=6;

		if (bit_is_set(PIND, 1)) PORTB=7;

		if (bit_is_set(PIND, 0)) PORTB=8;

		//third column

		PORTD =0b11011111;

		if (bit_is_set(PIND, 3)) PORTB=9;

		if (bit_is_set(PIND, 2)) PORTB=10;

		if (bit_is_set(PIND, 1)) PORTB=11;

		if (bit_is_set(PIND, 0)) PORTB=12;

		//fourth column

		PORTD =0b11101111;

		if (bit_is_set(PIND, 3)) PORTB=13;

		if (bit_is_set(PIND, 2)) PORTB=14;

		if (bit_is_set(PIND, 1)) PORTB=15;

		if (bit_is_set(PIND, 0)) PORTB=16;

	}

}

Now I know I'm missing your question because this code has nothing in it that uses Dean's LCD code. I thought your question was about getting the output of a keypad to show on a the Butterfly LCD using Dean's code, but I don't see anywhere that you use Dean's code, so what am I missing?

Smiley

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

sorry..
i really confuse now..
what do you mean by this keypad code has nothing in it that uses Dean's LCD code.
am i using a wrong coding for this keypad?
what the function of #include "LCD_Driver.h"

if my keypad program is wrong, can you help and guide me how to make my project works or can you give some suggestion what link should i go and guidelines to settle this problem

thanks :?

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

Quote:

what do you mean by this keypad code has nothing in it that uses Dean's LCD code.

Just #include'ing a .h file does NOT make use of any of the facilities it provides. This only happens when you call one or more of the functions that it documents.

To USE the LCD library you should be calling LCD_Init() near the start of your program and then later (probably) LCD_puts() to put message strings on the display. Otherwise what were you expecting to see on the display?

Cliff

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

amiraliff wrote:
sorry..
i really confuse now..
what do you mean by this keypad code has nothing in it that uses Dean's LCD code.
am i using a wrong coding for this keypad?
what the function of #include "LCD_Driver.h"

if my keypad program is wrong, can you help and guide me how to make my project works or can you give some suggestion what link should i go and guidelines to settle this problem

thanks :?

Please read:
https://www.avrfreaks.net/index.p...
Then get the Butterfly Quick Start Guide from my website along with the Butterfly FAQ and a few other free and helpful documents that you can use to get started. I would further suggest you look at some of the source code I provide and at the Smiley's Workshops to learn the fundamentals before attempting a keypad.

After reading all this then if you have additional questions please start a new thread on using a keypad with a Butterfly. This tread is not the appropriate place for this discussion.

Smiley

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

hi again
im having a problem with dean's lcd driver

when i try to compile this driver, there is an error's appear

Quote:
c:/winavr/bin/../lib/gcc/avr/4.1.1/../../../../avr/lib/avr5/crtm169p.o:(.init9+0x0): undefined reference to `main'
make: *** [lcd.elf] Error 1

hope u guys out there can help me

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

Well that's telling you that no where in the files being compiled is there a function called main() - all C programs must have this.

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

oh...

so where should i put the main() function

i try to write it but there still have an error

so can u tell me where the best place i should write this function

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

hi
i already download dean's driver on my butterfly but it shows nothing on my butterfly lcd.

what's the problem?

and what's the function of this code (i take from dean's driver)

Quote:
0xEAA8, // '*'
0x2A80, // '+'
0x4000, // ','
0x0A00, // '-'
0x0A51, // '.' Degree sign
0x4008, // '/'
0x5559, // '0'
0x0118, // '1'
0x1e11, // '2
0x1b11, // '3
0x0b50, // '4
0x1b41, // '5
0x1f41, // '6
0x0111, // '7
0x1f51, // '8
0x1b51, // '9'
0x0000, // ':' (Not defined)
0x0000, // ';' (Not defined)
0x8008, // '<'
0x1A00, // '='
0x4020, // '>'
0x0000, // '?' (Not defined)
0x0000, // '@' (Not defined)
0x0f51, // 'A' (+ 'a')
0x3991, // 'B' (+ 'b')
0x1441, // 'C' (+ 'c')
0x3191, // 'D' (+ 'd')
0x1e41, // 'E' (+ 'e')
0x0e41, // 'F' (+ 'f')
0x1d41, // 'G' (+ 'g')
0x0f50, // 'H' (+ 'h')
0x2080, // 'I' (+ 'i')
0x1510, // 'J' (+ 'j')
0x8648, // 'K' (+ 'k')
0x1440, // 'L' (+ 'l')
0x0578, // 'M' (+ 'm')
0x8570, // 'N' (+ 'n')
0x1551, // 'O' (+ 'o')
0x0e51, // 'P' (+ 'p')
0x9551, // 'Q' (+ 'q')
0x8e51, // 'R' (+ 'r')
0x9021, // 'S' (+ 's')
0x2081, // 'T' (+ 't')
0x1550, // 'U' (+ 'u')
0x4448, // 'V' (+ 'v')
0xc550, // 'W' (+ 'w')
0xc028, // 'X' (+ 'x')
0x2028, // 'Y' (+ 'y')
0x5009, // 'Z' (+ 'z')
0x1441, // '['
0x8020, // '\'
0x1111, // ']'
0x0000, // '^' (Not defined)
0x1000 // '_'

hope anyone can explain it to me

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

That's just data saying which segments should be lit to display the character listed in each comment

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

hi
i already download dean's driver on my butterfly but it shows nothing on my butterfly lcd.

what's the problem?

anyone can help??

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

Quote:

so where should i put the main() function

In one of your C source files.

In the earlier posts in this thread you reported that you succeeded to build and download a complete AVR application. This implies that you have at least some knowledge about the main function, why it is needed and where it should go, yes? If not, now is a good time to get a good book on the C programming language and start reading.

You do realise that Deans code in LCD_driver.c and LCD_driver.h is the LCD driver only with no main program? (In the Tutorial thread where he presented the driver he has posted a small main program a few posts down).

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

Hey Guys,

I´m bit confused about the test program from Dean he wrote:

LCD_puts_f(PSTR("AVR BUTTERFLY GCC"));
LCD_puts("AVR BUTTERFLY GCC");

So in according to the LCD_Driver.c:
LCD_puts_f is storing data in the flash and LCD_puts in the SRAM (so its volatile).

If I write something only wit LCD_puts_f on the LCD screen it will disappear after the power was shutted of, but it´s not the case.

So the questition is why the data is still there?

Thanks

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

Quote:

So the questition is why the data is still there?

Well two options:

1) you've actually found a bistable (aka "Zero power") LCD - http://en.wikipedia.org/wiki/Liq... or

2) there's still power (maybe just a trickle capacitance?) to the LCD

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

Ok, but normally under no-power conditions after switching of the data from SRAM should be erased, isn´t it so?

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

In no power conditions nothing should appear - the crystals in the LCD need an AC biasing voltage continually applied to keep them twisted so they block the polarised light. If you remove power that process stops (except in "bistable") and they all untwist so that the display appears blank. If you are seeing something other than this then there MUST be power still applied or you have ghosts in the machine!

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

hi
i'm trying to use keypad and want to display it on my butterfly lcd
can i use dean's lcd driver?

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

Quote:

i'm trying to use keypad and want to display it on my butterfly lcd
can i use dean's lcd driver?

Maybe, but you have to prove it to us...

Point is: Given the vague technical description the answer probably is "yes, Deans driver should be usable in such a case".

Give us a stronger technical description and the answer will be more definite.

Or, do what I suspect you wanted to all along and ask "How?". In that case you must supply us with a more definite description of your project at this stage, or you will get no meaningful answers at 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

Hey,

I´ve tried to display a variable over the LCD_puts function, but it didn´t work.

So I wrote simple into the main function:

int x = 1;
LCD_puts(x);

But it comes nothing. It works, however, if I write insted: LCD_puts("x");

Where is the problem?

Thanks!

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

LCD_puts() is looking for a string as it's argument (ie, an array of characters with a null at the end).
To print the value of a variable, you need to convert it to a string first. You can use sprintf, itoa, or convert it yourself.
/mike

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

Thanks for the fast anwser! Now I got it, it was just too long that I programmed the last time.

But I noticed, that sprintf needs a lot of memory, is there another possibility to convert it to a string by myself?

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

Quote:

is there another possibility to convert it to a string by myself?

1. Look for a function itoa(...) in your run-time library.

2. Yes, you could write it yourself. Repeated integer division and remainder by 10 should give you the digits (from least to most significant) in the remainder and the number for the next repetition in the division result. In order to convert a single digit integer value to the corresponding character representation yuo just add the integer representation of the digit '0', like so

digitAsCharacter = digitInAnInteger + '0';

You build up your string from right to left (that order is the tricky part), and don't forget that the string should have a terminating zero char!

If you do a search of this site you will probably find several discussions on alternative implementations that might be more efficient in some aspect.

Unless you are in a real trouble with flash memory and really know what you are doing, I'd stay with itoa(...).

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: Thanks and greetings from Lulea!

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

Just to drag up a really old post . . . quick question on the interrupt routine. You say that the LCD ISR allows other interrupts, but I don't see anything explicitly allowing it. I would expect an sei() or similar, is that the case? In my application, I'm running TC1 at Fclk/8, and need to get a OC1B to do something. It seems like that just isn't happening frequently, and I'm guessing that if that interrupt doesn't get the timer value in the 8 clock cycles where the timer value and OC1B match, the interrupt is lost. I've checked all my other interrupts, and they're a couple clock cycles long at worst. Am I at least looking in the right place?
Thanks!

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

Hi,

You are correct that the latest version does not explicitly re-enable interrupts in the ISR to allow other interrupts to interrupt it while the ISR is running (boy, that's a mouthful to say!). The fix is as simple as changing:

ISR(LCD_vect)

To:

ISR(LCD_vect, ISR_NOBLOCK)

In a recent version of avr-libc (i.e. less than a year or two old).

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Cool, thanks for the input. I'll give it a shot. I had tried manually enabling interrupts (sei) and disabling the LCD interrupt at the beginning of the interrupt, and re-enabling it at the end (again, a mouthful that is way to confusing), but no result. I ended up just changing my code around a bit to do a hardware PWM mode rather than software, but on the butterfly, that means PB5 is the only option when using the joystick, and it's tied to the speaker, very annoying results :P Time to start looking at a different controller and an external LCD if I get serious about this project! Thanks again!

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

I was getting all kinds of errors when I tried to compile code containing Atmel's LCD drivers, so I decided to use this one. I got the sample code Dean wrote to compile with no errors or warnings using WinAVR.

When I download the HEX file to my board using AVR Studio, nothing happens. I'm pretty sure I'm downloading it right, because when I put the default Butterfly program back on there, it works fine.

Any suggestions?

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

wegstar wrote:
thanks! :lol:
adding a sei(); before the init solved the problem.

I added sei() and the program worked!!! I've been working on this for 2 weeks!!! I'm so happy!! Here's the code I used:

#include
#include

int main(void)
{
sei();
LCD_Init();

LCD_puts_f(PSTR("AVR BUTTERFLY GCC"));
LCD_puts("AVR BUTTERFLY GCC");

for (;;) {}

return 0;
}

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

I also had trouble getting the LCD_WriteChar() function to work until I added universalist's macro and took "static inline" off of the original definition. Which I don't understand but guess I don't need to at this point. It took me a couple of tries to see that the order of the arguments was reversed ... not sure if that was intentional.

I appreciate Dean's tutorial. I'm new to using C on MCUs although I've been playing with them in assembler for quite some time. Lots to learn! I'm pursing two paths: first, starting with tiny programs that, for example, beep the piezo sounder when the joystick is moved, and second, trying to use other people's code (such as this driver) -- which I suppose is one of the big advantages of C.

Nick

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

Works very well! Thanks for posting it.

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

hi,

i wanna ask about how to add LCD_UpdateRequired function to dean's code..

thanks..

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

hakagiri wrote:
hi,

i wanna ask about how to add LCD_UpdateRequired function to dean's code..

thanks..

Please start a new thread or at least continue with the thread you already started at:
https://www.avrfreaks.net/index.p...

The purpose of the tutorial threads is to discuss the tutorial, not solve unrelated problems.

Smiley

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

oh.. okay, i'm sorry... :D

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

Quote:

The purpose of the tutorial threads is to discuss the tutorial, not solve unrelated problems.


As such I'm going to lock this thread. If anyone has anything to add to the original article PM js, plons or clawson and ask us to temporarily unlock this.

Moderator

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

Quote:

i wanna ask about how to add LCD_UpdateRequired function to dean's code..

It would just be something simple like:

void LCD_UpdateRequired(void)
{
    UpdateDisplay = true;
}

Added to the driver code.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Thanks for this LCD driver, it allowed me to get characters on the screen with next to zero nowledge of C 8)
I noticed that

LCD_WAIT_FOR_SCROLL_DONE();

Does not check if the text is long enough to scroll, and if it isnt, waits forever...

For the solar hotwater controller that I am building I need the numbers (and eventially will need the arrows). I was going to ask if you could do it for me, but I have come up with a brute force hack on your code, without really understanding it too well that gives the numbers 1-5 sequentially. i.e if 3 then you get 3,2,1. I'me sure theres a much nicer way of doing it. I havnt check the 3 as R200(?) is desoldered atm

diff /usr/src/AVR/include/LCD_Driver.c /usr/src/AVR/butterfly/LCD-test/LCD_Driver.c
29a30
> 		volatile uint8_t  LCDNumbers      = 5;
228,229c229,264
<     if (Byte != LCD_SPACE_OR_INVALID_CHAR)              // Null indicates invalid character or space 
<       SegData = pgm_read_word(&LCD_SegTable[Byte]);    
---
>     if (Byte != LCD_SPACE_OR_INVALID_CHAR) {             // Null indicates invalid character or space 
>     /* To adds pecial characters to scrolling display we have thre cases 
>      * for 1-5:
>      * 1 and 2, OR 0x4 to Digit 0 and 1 (2 and 3 on LCD) respectivly
>      * 4 and 5, OR 0x2 to Digit 2 and 3 (4 and 5 on LCD) respectivly
>      * 3, set LCDDR3=0x1, as I think this is not written to for normal CSS characters
>      * Ime sure theres a better way (and there is for just 1 and 2...
>      * But ime doing this with a long list of if statements...
>      */    
>       if (LCDNumbers >= 5 && Digit == 3)
> 	      SegData = pgm_read_word(&LCD_SegTable[Byte])|0x2;
> 		else if (LCDNumbers >= 4 && Digit == 2)
> 	      SegData = pgm_read_word(&LCD_SegTable[Byte])|0x2;
> 		else if (LCDNumbers >= 2 && Digit == 1)
> 		  SegData = pgm_read_word(&LCD_SegTable[Byte])|0x4;
> 		else if (LCDNumbers >= 1 && Digit == 0)
> 		  SegData = pgm_read_word(&LCD_SegTable[Byte])|0x4;
> 		else 
> 		  SegData = pgm_read_word(&LCD_SegTable[Byte]);	  	 
> 	 }
> 	 else
> 		 if (LCDNumbers >= 5 && Digit == 3)
> 	      SegData = 0x2;
> 		else if (LCDNumbers >= 4 && Digit == 2)
> 	      SegData = 0x2;
> 		else if (LCDNumbers >= 2 && Digit == 1)
> 		  SegData = 0x4;
> 		else if (LCDNumbers >= 1 && Digit == 0)
> 		  SegData = 0x4;
> 		else 
> 		  SegData = 0x0 ;	
> 		  
> 	if (LCDNumbers >= 3 && Digit == 0)
> 	   LCDDR3 = 0x1;
> 	 else 
> 	   LCDDR3 = 0x0;
253a289,300
>     UpdateDisplay = true; 
>  }
> 
>  /* 
>   NAME:      | LCD_ShowNumbers 
>   PURPOSE:   | Routine to sequentially turn on the LCD's numbers 
>   ARGUMENTS: | Highest number, 0 for none 
>   RETURNS:   | None 
>  */ 
>  void LCD_ShowNumbers( uint8_t LNumbers) 
>  { 
>     LNumbers    = LCDNumbers; 

the LCD_ShowNumbers() thing doesn't work, but setting the value LCDNumbers seems to, again due to my complete ignorance of C.

If you could improve on this and perhaps do it in a way that allowed for more general orring of bits to LCDDR* then I could try and fill in the rest to get arrows working. I can see myself doing it with another heap of if statements, which doesnt feel very eloquent.
I guess its more general to call LCD_Numbers() and have just this number appear, and as such LCD_Arrows() and have the corresponding arrow appear.

and... theres always one more thing... I would like to use portD, which means making sure that there is no way that anything gets put on segments 5,6,and 7 (All special segments except 9 are ok tho). How can I be sure of this by modifying your driver?

TIA

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

Hi there!
I've got a Butterfly, and I'm trying since fife weeks to write something on the display...
I'm new on AVR but I know the C-Language well. I've tried to make a new Project with AVRStudio 5 and copied the code from Dean (first comment) I've made a headerfile for the LDC_Driver.h but nothing works... :(
The only thing I can do, is to put the programm which was on it at first.
I'm becoming desperate of trying...
Can somebody help, even when it's a old thread??

THX in advence

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

Will this code work with my Atmega169?

Thanks

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

Depends if it's attached to an LCD with the same segment layout as the Atmel Butterfly or not.

However even if the segment layout is different the general technique should be adaptable.

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

clawson wrote:
Depends if it's attached to an LCD with the same segment layout as the Atmel Butterfly or not.

However even if the segment layout is different the general technique should be adaptable.

Well, it is an AVR Butterly board.

Please let me know what you mean by "LCd with the same segment layout as the Atmel Butteryfly or not."

Thanks

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

Quote:

Well, it is an AVR Butterly board.

This is a joke right? It's a LCD driver for the Butterfly board, which has the ATMEGA169 on it. Therefore, if you have a Butterfly board with said MEGA169 on it there's a fairly good chance it will be compatible.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Thanks buddy....it helped me a lot!

Success is optional, choose wisely!

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

Thank you Dean for posting the LCD driver - it worked for me perfectly the first time.

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

Hello,

 

Sorry for bringing back this old thread. My main question is more about C/C++ programming.

 

Original AVR Butterfly LCD has 16 bits for one digit, but my LCD has 8 bits.

 

Original LCD_WriteChar method:

 

/*
 NAME:      | LCD_WriteChar (static, inline)
 PURPOSE:   | Routine to write a character to the correct LCD registers for display
 ARGUMENTS: | Character to display, LCD character number to display character on
 RETURNS:   | None
*/
static inline void LCD_WriteChar(const uint8_t Byte, const uint8_t Digit)
{
	uint8_t* BuffPtr = (uint8_t*)(LCD_LCDREGS_START + (Digit >> 1));
	uint16_t SegData = 0x0000;

	if (Byte != LCD_SPACE_OR_INVALID_CHAR)              // Null indicates invalid character or space
	  SegData = pgm_read_word(&LCD_SegTable[Byte]);	

	for (uint8_t BNib = 0; BNib < 4; BNib++)
	{
		uint8_t MaskedSegData = (SegData & 0x0000F);

		if (Digit & 0x01)
		  *BuffPtr = ((*BuffPtr & 0x0F) | (MaskedSegData << 4));
		else
		  *BuffPtr = ((*BuffPtr & 0xF0) | MaskedSegData);

		BuffPtr += 5;
		SegData >>= 4;
	}	
}

 

If I change this line:

*BuffPtr = ((*BuffPtr & 0x0F) | (MaskedSegData << 4));

to this line:

*BuffPtr = ((*BuffPtr & 0x0F) | (MaskedSegData << 2));

I can "move cursor" to the second digit fine, but it doesn't move to the third digit.

 

So my main questions are about this particular LCD_WriteChar method from C/C++ perspective:

1) what means SegData & 0x0000F in this line? Why 0x0000F instead of 0x0F?

uint8_t MaskedSegData = (SegData & 0x0000F);

2) what means Digit & 0x01 in this line?

if (Digit & 0x01)

3) what means this line?

*BuffPtr = ((*BuffPtr & 0x0F) | (MaskedSegData << 4));

 

Regards,

Furieux

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

Are you really talking about a segment LCD driven by a 169 or a 329?

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

Hi Clawson,

Yes, sorry, I’m actually talking about 329.

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

1) 0xF is exactly the same as 0x000F (or any number of leading 0s in fact) but I think the author is making the point that it's masking the bottom 4 from the full 16 bits.

 

2) a & 1 test is usually an even/odd test. Even numbers are 0 when & 1 while odd numbers return 1 which is interpreted as "true" in a conditional test.

 

3) the line is taking the bottom 4 bits of what is already in the location pointed to then putting MaskedSegData into the upper 4 bits.

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

Ok, could you please help me to analyze this function deeper?

 

uint8_t* BuffPtr = (uint8_t*)(LCD_LCDREGS_START + (Digit >> 1));

Here BuffPtr is defined which corresponds to LCD registers starting with LCDDR0. Next would be LCDDR5, then LCDDR10, and then LCDDR15 (according to COM0, COM1, COM2, and COM3). This is clear for me. But again - what Digit >> 1 means here?

 

Then,

uint16_t SegData = 0x0000;

Here SegData is declared with initial value.

 

Then,

if (Byte != LCD_SPACE_OR_INVALID_CHAR)
    SegData = pgm_read_word(&LCD_SegTable[Byte]);

Here it's checking if Byte is not invalid character and if it is not, then avr function pgm_read_word() is parsing LCD_SegTable[] array for the Byte value and then store it to the SegData variable.

For example, let's take number 0 to be shown on my segment LCD which in my case in array LCD_SegTable[] is defined as 0x3132

 

Then,

for (uint8_t BNib = 0; BNib < 4; BNib++) {

Here it is looping through nibbles (4 bits). I think this is because AVR Butterfly LCD has 16 bits for the digit. But in my case I have 8 bits, so I thought I need to loop only through two nibbles? I tried to change here BNib < 2, but then wrong segments are lit.

 

Then,

uint8_t MaskedSegData = (SegData & 0x0000F);

Here MaskedSegData is defined and it takes SegData value which was read from LCD_SegTable[] array (in this example it is 0x3132) and then it is AND-ed with bottom 4 bits. Right?

If I convert 0x3132 from hex to bin, i get

0000 0000 0011 0001 0011 0010

AND-ed with 1111 it is then

0000 0000 0011 0001 0011 0010 right? The same!

Why it is AND-ed in the first place? You wrote that it is checking for even/odd numbers. Why it is needed here?

 

Then,

if (Digit & 0x01)
    *BuffPtr = ((*BuffPtr & 0x0F) | (MaskedSegData << 4));

This I cannot understand at all. It's AND-ing Digit with 1 (if the last bit is 1?) and if true, then BuffPtr is AND-ed with bottom 4 bits and then OR-ed... what that means? It's definitely related to LCDDRx, but I can't get the point.

 

Then,

else
    *BuffPtr = ((*BuffPtr & 0xF0) | MaskedSegData);

So if AND-ing Digit with 1 is false (the last bit is 0?), then BuffPtr is AND-ed with top 4 bits and then again OR-ed... what that means?

 

And finally,

BuffPtr += 5;
SegData >>= 4;

BuffPtr now is incremented by 5 (this probably is related to those LCDDR0, LCDDR5, LCDDR10 and so on, or LCDDR1, LCDDR6, LCDDR11 and so on). This probably is needed because next for loop iteration will be on the next register. Right?

And SegData? This I don't understand at all. What SegData = SegData >> 4 means in the first place? I know that shifting to the right is basically dividing, but I'm not sure if it's that case here.

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

As you already seem to be getting lost with some basic C code.

I would suggest setting a side the code you have at the moment and take your time to get to grips with the C operators.

All your questions seem to be coming from not understanding what the specific operators do and in what order they are executed.

 

Also you have to have a good look at the datasheet.

My first guess it that the pointer BuffPtr is initialized to point to the start of the RAM area in the chip that holds the actual display data. so what segments on the display are off or on

All that is done is to update the state of certain pixels that need to be updated to display the correct character on the display itself

 

All the programmer has done is instead of putting some calculations on separate lines they have combined them on a single line to make the code better readable ( in their eyes... )

 

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

meslomp wrote:
As you already seem to be getting lost with some basic C code. I would suggest setting a side the code you have at the moment and take your time to get to grips with the C operators.
+10

 

Exactly what I was going to say. You can't really hope to use a code like this until you understand it and to understand it you need a grasp of some of the basic concepts in C like shifting and masking.

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

Ok, I got it.

Until that my only option will be to just leave unconnected those two pins (unneeded 8 bits) and use the same code...

Anyway, thanks for the help!

Last Edited: Mon. Jul 9, 2018 - 10:52 AM