AVR Butterfly Primer

I have been curious about the AVR micros for some time now. I was excited to see that Digi-Key was selling (among others) the AVR Butterfly evaluation board. And its only $19.99 plus shipping! I could not pass that up even if I ended up not using the thing. I have had it for a number of weeks now just looking at it wondering, "Okay, so where do I start". That is what this web page is all about, I am still quite the newbie when it comes to the AVR, but I have not been able to find anything useful on the web for the Butterfly, so I decided to do my own page.

The breakthrough for me was the AVR for beginners tutorial at www.avrfreaks.net. Basically all it did was blink the port b bits on and off, but that was enough. I am getting ahead of myself, you are welcome to head over to avrfreaks and get a step by step, button by button, walk through of your first program. I am not going to go so slow.

Step 1: Serial Cable

I dont know if this is an AVR thing or a mega169 thing but all you need to program your AVR Butterfly is three wires and a connector. The following diagram comes from section 3.7 in the AVR Butterfly Eval Kit Users Guide The smaller table is unreadable in the pdf, so dont bother trying to read it here or in the pdf, use the larger table to hook up your three wires...Some soldering is required/recommended.

Step 2: Software Tools

I am almost completely Windows free at home (I run Linux almost all the time, rarely Windows), but for the moment I only know about Windows tools for the AVR (please send links if you have Linux tools). You might has well get AVR Studio 4 for Windows and start there. One way to get there is start at www.atmel.com search on "butterfly", go to the AVR Butterfly page (the first hit), then select Tools & Software on the left and go to the AVR Studio 4 link. Download, install, all of that stuff. You can work through the IDE or you can pull out the important tools. C:\Program Files\Atmel\AVR Tools\ is where you want to start. In the AvrAssembler directory grab avrasm32.exe and in the Appnotes directory under that grab the m169def.inc file. Under AvrProg grab avrprog.exe.

Step 3: First Program

Use the AVR Studio IDE or your favorite text editor to write your first AVR program:

.include "m169def.inc"

.org 0x0000
    rjmp RESET

RESET:
    ldi R16, 0xFF
    out DDRB,R16

Loop:
    dec R16
    out PORTB, R16
    rjmp Loop

What I did was stick an led on the port b pins on the AVR board, which is the 10 pin horizontal group on the lower left side of the board. The first 8 pins are port b, pin 9 is gnd. I put the led on pins 9 and 8 (port b bit 7). With the program above the led just turns on, the next example will slow it down.

So you have entered your program. If in the IDE do a build project and it will make a .hex file.
If you are using the command line tool then:

C:\>avrasm32 -fI -o one.hex one.asm
AVRASM: AVR macro assembler version 1.57  (Nov 15 2002 10:58:00)
Copyright (C) 1995-2002 ATMEL Corporation

Creating   'one.hex'

Assembling 'one.asm'
Including  'm169def.inc'

Program memory usage:
Code             :    6 words
Constants (dw/db):    0 words
Unused           :    0 words
Total            :    6 words

Assembly complete with no errors.

I did not feel the Atmel documntation was clear on how to program this thing. If you have the as-shipped example application loaded, you can follow the menus down to a point to load the program, but since you are not re-loading that app, it is a one shot deal, not worth discussing. Here is how to load a program, no matter what is currently in there. The two holes on the lower right corner of the board along the right side (one on above the other) are a reset and ground.

1) Short these together and release, this puts it into a bootloader program I presume which is in eeprom.
2) Now press and hold the joystick (press straight down like it is a push-button, not in a direction like a joystick).
3) Run the avrprog.exe program (or AvrProg from the IDE, under Tools I think). This only works if the board is plugged in, and the battery is in, and you have done a reset and you are holding the button when the avrprog program starts. If you do it right you will get a window that looks like this:

4)[Browse...] and find your .hex file (it will remember from the last time so you dont have to do this very often)
5)Under Flash press the Program button, this will load and verify your program.
6)Exit completely out of avrprog. If you dont you may forget you left it running and you will go nuts trying to figure out why you cant get a second copy of avrprog to run and recognize the board.
7)Press the joystick in the up direction this will start your program.

Now if you hook up an led from port b bit 7 to ground (mine is soldered on) the led will light, you wont see it flashing. If you change your program to this:

.include "m169def.inc"

.org 0x0000
    rjmp RESET

RESET:
    ldi R16, 0xFF
    out DDRB,R16

Loop:

    ldi R17, 0x01
aloop:
    inc R17
    cpi R17, 0x00
    brne aloop

    dec R16
    out PORTB, R16
    rjmp Loop

The led will blink, AND, the piezo will buzz. Bit 6 of port b goes to the piezo.

Step 4: LCD

The lcd is not what I am used to but thats okay it does work. There are a number of ways to solve the problem, and I will leave that up to you. You may want to pick up a couple of application notes from Atmel. AVR064, and AVR065. Search for "AVR064" on their website. AVR064 also has some software, you will want to download it too. The butterfly documentation talks about the lcd being the same as the STK502 and they reference the above app notes. Looking at the app notes and other documentation I pieced together this program:

.include "m169def.inc"

.org 0x0000
    rjmp RESET

RESET:


    ldi r16, 0xB7
    sts LCDCRB, r16

    ldi r16, 0x10
    sts LCDFRR, r16

    ldi r16, 0x0F
    sts LCDCCR, r16

    ldi r16, 0x80
    sts LCDCRA, r16


    ldi r16,0xFF
    sts LCDDR0,r16
    sts LCDDR1,r16
    sts LCDDR2,r16
    sts LCDDR3,r16
;    sts LCDDR4,r16
    sts LCDDR5,r16
    sts LCDDR6,r16
    sts LCDDR7,r16
    sts LCDDR8,r16
;    sts LCDDR9,r16
    sts LCDDR10,r16
    sts LCDDR11,r16
    sts LCDDR12,r16
    sts LCDDR13,r16
;    sts LCDDR14,r16
    sts LCDDR15,r16
    sts LCDDR16,r16
    sts LCDDR17,r16
    sts LCDDR18,r16
;    sts LCDDR19,r16




hang:
    rjmp hang

The ATmega169 docs walk you through setting up the LCD, and looking at the c code provided with AVR064 you can piece together the rest of the story. The above code will turn on all of the lcd segments. Good, bad, or otherwise, you have to deal with each segment individually, you cant just tell some lcd controller I want you to put an 'A' on the first segment, you have to go and turn on some segments and turn off others to get what you want.

This code was supposed to be like the C example and the asm example in the manual where the 0x80 for the LCDCRA register for example is not written as 0x80 but 1 shifted left LCDEN, but I am having a bit of an html problem with a double less than so I just figured out the bits instead. Since the settings above are pretty ridgid for the butterfly you wont need the flexibility to change them so I guess it doesnt matter.

The LCD itself is capable of displaying the segments in the top picture but only the segments in the bottom picture are wired up on the butterfly.

The next figure shows the relationship between the segments and bits in the register.

What they are trying to say here is that the lower nybble of LCDDR0, LCDDR5, LCDDR10, and LCDDR15 control the segments of the first digit. The upper nybble of LCDDR0, 5, 10, and 15 controls the second segment. The lower nybble of LCDDR1, 6, 11, and 16 control the third digit and so on. If you look in the AVR064 example, the LCD_character_table has all the stuff already figured out for you. If you look at the figure above showing the letter A you will see that the first nybble gets a 0x1 because the A segment is set but the K segment is not. The next nybble gets a 0x5, because the B and F segments need to be on and H and J segments need to be off. Basically the registers for the letter A are 0x1, 0x5, 0xF, 0x0. If you look at the table in the AVR064 C example you will see that they have the value 0x0f51 for the letter A. Which has all the nybbles just in the reverse order of what you would think. From there I went down the list to get the values for HELLO.

;H    0x0f50,
;E    0x1e41,
;L    0x1440,
;L    0x1440,
;O    0x1551,

And wrote another small program:

.include "m169def.inc"

.org 0x0000
    rjmp RESET

RESET:

    ldi r16, 0xB7
    sts LCDCRB, r16

    ldi r16, 0x10
    sts LCDFRR, r16

    ldi r16, 0x0F
    sts LCDCCR, r16

    ldi r16, 0x80
    sts LCDCRA, r16



    ldi r16,0x00

    ldi r17,0x10
    sts LCDDR0,r17
    ldi r17,0x00
    sts LCDDR1,r17
    ldi r17,0x01
    sts LCDDR2,r17
    sts LCDDR3,r16
;    sts LCDDR4,r16

    ldi r17,0x45
    sts LCDDR5,r17
    ldi r17,0x44
    sts LCDDR6,r17
    ldi r17,0x05
    sts LCDDR7,r17
    sts LCDDR8,r16
;    sts LCDDR9,r16

    ldi r17,0xef
    sts LCDDR10,r17
    ldi r17,0x44
    sts LCDDR11,r17
    ldi r17,0x05
    sts LCDDR12,r17
    sts LCDDR13,r16
;    sts LCDDR14,r16

    ldi r17,0x10
    sts LCDDR15,r17
    ldi r17,0x11
    sts LCDDR16,r17
    ldi r17,0x01
    sts LCDDR17,r17
    sts LCDDR18,r16
;    sts LCDDR19,r16



hang:
    rjmp hang

The documentation and the C example in AVR064 lean towards using interrupts so that you can update all of the segments within one refresh cycle. I have not looked into that yet, perhaps it is important, perhaps it doesnt matter, most likely it depends on the application. Either of the examples above clearly show that if the content is static you dont need to bother, just set it and leave it.

There are a number of holes left out of the above register specs, for example bits 1, 2, 5 and 6 of LCDDR0 and other bits in simliar registers control the segments above and below the main digits. I dont know the specific mapping for these bits at this time

Step 5: ADC

If you look at the downloads section below and grab the light.asm example (too big to embed in this web page) it shows you how to sample from the adc, specifically the light sensor. Also note that I am not doing any of that LCD interrupt stuff they talk about in the mega169 document, and the display looks fine.

The ADC code was derived from the C example that is loaded in the Butterfly when you buy it. The AVR064 example, which is geared towards a different eval board, helps for the LCD but doesnt help for the ADC. I started with the AVR064 C code and it didnt work then moved over to the actual Butterfly C code, subtle differences.
temp.asm reads the temperature input on the adc

Step 6: Linux

Cool, now I dont have to boot windows if I dont want to. First off you can run avrasm32.exe using wine. Second, the AVR109 Self Programming app note, just does not apply to the butterfly. Dont bother with it at all. The source code for the bootloader is available on atmels website, looking at the code (main.c mostly) its pretty simple to see what you have to do to make it work. So I wrote my own loader for Linux. ser.c is hardcoded for com2 BTW.
xterm.c
ser.c
ser.h

Step 7: Auto-Start

I followed the wrong path for a while on this one, but it is solved now. If you want to use your Butterfly in a project and you dont want to have to push the joystick up to start it running, the solution is pretty simple. Short the joystick in the up position.

First off on the right side of port D you will find external power pins, remove the battery and apply power to these pins plus on the top, ground on the bottom. I have been using 5v from a pc power supply and have not harmed anything yet. On right side of port B you will find ground and the joystick up pin, short these together and anytime you apply power to this board it will start running your application. I recommend using pins and a jumper so you can remove the jumper and re-program the board.

Step 8: Uart

The uart is setup for 19200 N81 send and receive by the boot loader, so you dont have to set it up if you dont want to. To send wait for UDRE to be clear in UCSRA, to receive check RXC. Here is an example program that echos whatever comes in, checking UDRE is not necessary here other than to have some code to cut and paste from.
mainloop:

getit:
    lds r20,0xC0
    andi r20,0x80
    breq getit
    lds r18,0xC6

sendit:
    lds r20,0xC0
    andi r20,0x20
    breq sendit
    sts 0xC6,r18

    rjmp mainloop

Documents and Downloads

AVR Butterfly Manual
AVR Instruction Set
AVR ATmega169
AVR ATmega169 supplement
AVR065: LCD
AVR064: Temp and LCD
first.asm
second.asm
lcdall.asm
lcdhello.asm
light.asm
temp.asm

Links

http://www.ecrostech.com

That is all for now, I will add more as I figure it out

avr ta dwelch tod com