AVRgpp ISP and UPDI programmer

Important note

This page is about a personal project (by Mike, software, and Brian, hardware). Wordcraft does not develop, manufacture, sell or support AVRgpp. The contents of this page will change regularly and without notice.

The AVRgpp (General Purpose Programmer) is open source hardware and software designed for use with the Arduino IDE. It provides the following functions in a single unit:

  • an ISP programmer,
  • a UPDI programmer (with or without a 12V programming pulse),
  • a USB to serial interface.

Functions are selected via a 128x32 I2C OLED LCD and two buttons. The left button selects functions, the right button selects options.

AVRgpp can optionally provide power (5V or 3.3V) to the target system - within the limits of USB power.

With the supplied firmware AVRgpp supports programming but not JTAG debugging. It provides two spare data lines (plus ground) on a test/debug header which could be used for diagnostics or debugging - via software serial and suitable firmware.

Quick start

Assembled AVRgpps should come complete with all functions in firmware.

If you are assembling you own unit you will need to:

  • Burn a Pro Mini (ATmega328P (5V, 16MHz)) bootloader into the on-board processor.

    You will need another programmer to do this: AVR ISP MkII, USBasp or another AVRgpp.

  • Upload the AVRgpp sketch from the Arduino IDE. (Source code here.)


AVRgpp starts up ready to program a device using the last selected protocol. This speeds things up when programming multiple devices or when repeatedly changing code for a single device.


VCC (if previously selected) will be supplied to the target as soon as AVRgpp starts up - so check the VCC switch (5V or 3.3V) before connecting the target. Selecting 5V for a 3.3V target may permanently damage the target.

The photo belows shows AVRgpp starting up in UPDI programming mode.

Press the left button to display the menu

Use the "Store configuration" menu option if you make changes - for example, switching from ISP to UPDI programming or providing target VCC.

ISP programming a bootloader

  • Use the switch to select 5V or 3.3V power for the target (if required).
  • Select "TARGET VCC", "YES" from the OLED menu (if required).
  • Select "PROTOCOL", "ISP".
  • From the IDE select "Tools" then the target board and processor.
  • Select "Tools", "Programmer", "Arduino as ISP". (Not "ArduinoISP" or "ArduinoISP.org".)
  • Connect AVRgpp "ISP out" header to the target. Red wire to pin 1 on both.
  • From "Tools" select "Burn bootloader".
  • More ...

UPDI programming a bootloader

You must add "megaTinyCore" to the IDE before programming ATtinys via UPDI. More ...

  • Use the switch to select 5V or 3.3V power for the target (if required).
  • Select "TARGET VCC", "YES" from the OLED menu (if required.)
  • Select "PROTOCOL", "UPDI".
  • From the IDE select "Tools" then the target board and processor.
  • Select "Tools", "Programmer", "jtag2updi (megaTinyCore"
  • Connect the target to the 6-way right angle connector.

    The minimum connections are:

    UPDI and Gnd (AVRgpp could also provide VCC to the target (if required.)

  • From "Tools" select "Burn Bootloader".
  • More ...

An example of UPDI programming

The photo below shows AVRgpp connected to an ATtiny1614 mounted on a SOIC-14 breakout PCB on a small breadboard.

5V power for the ATtiny1614 is coming from AVRgpp via the "TARGET VCC", "YES" option. AVRgpp is ready to start UPDI programming and the tell-tale LED confirms that power has been applied.

The screen grab below shows the ATtiny1614 (with opiboot bootloader) selected from the list of processors supported by megaTinyCore.


If you wish to later upload code to the target directly from the Arduino IDE over USB you must select a target with a bootloader or you must select a bootloader from the options provide in the IDE when a target is selected. You must then burn that bootloader using AVRgpp.

Failure to install a bootloader will make it impossible to download code over USB but a device can still be programmed using AVRgpp from the IDE "Sketch", "Upload using programmer" option.

The "jtag2updi (megaTinyCore" programmer has been selected along with "Burn Bootloader".

The output from AVRDUDE shows that the previous programming session was successful.

Power is removed from the target after programming and AVRgpp is automatically reset to give a clean start.

USB to serial interface

The USB to serial interface allows AVRgpp to be used to upload code from the Arduino IDE or for serial communications via the Arduino IDE Serial Monitor or a PC app.

  • Use the switch to select 5V or 3.3V power for th target (if required).
  • Select "TARGET VCC", "YES" from the OLED menu (if required).
  • Select "PROTOCOL", "USB-SERIAL".
  • Connect the target to the 6-way right angle connector on AVRgpp.

    The minimum connections are:

    Tx, Rx, DTR and Gnd (and Vcc if AVRgpp is providing power).

  • You can now use AVRgpp in the same way as any other USB-serial module.
  • More ...

Brief specification

Video: please click here to download an MP4 video of AVRgpp telling you about itself.

  • PCB: 28mm x 60mm. It is small - about 1/3 the size of a credit card.
  • On-board ATmega328P: 5V, 16MHz.
  • Micro USB socket for connection to a PC via a CH330N USB-to-serial IC.
  • 6 way vertical ISP "In" header for bootloading the on-board ATmega328P.
  • 6 way vertical ISP "Out" header for bootloading or programming targets over ISP.
  • 6 way vertical "Target" header for serial or UPDI programming.
  • 6 way right angle "Target" header for serial or UPDI programming.
  • 3 way right angle "Test/Debug" header for PC1, PC12 and ground - may be used for software serial output and other purposes when developing code for the ATmega328P.
  • ST662 12V generator - on/off controlled by ATmega328P..
  • MC1403 IC to switch serial lines between on-board ATmega328P or target - controlled by ATmega328P.
  • Slide switch to select 5V or 3.3V for the target - on/off controlled by ATmega328P.
  • 128 x 32 I2C OLED display.
  • Two momentary buttons for menu selection and confirmation.
  • Options selected from the OLED menu may be stored in EEPROM ready for use in the future.

Video: please click here to download an MP4 video of AVRgpp showing the various menu options.

Is it for sale and how much is it?

Hardware and firmware development is complete using systems we assembled ourselves (shown here).

AVRgpp is open source and all files are available.

For us to offer it for sale we would need to order at least 100 assembled PCBs to get a reasonable price.

The selling prices (excluding tax and shipping) would then be:

  • £34.00 (approx $42.00): fully assembled complete with OLED, buttons and headers.
  • £3.00 (approx. $3.75): 6-way to 6-way ribbon cable for ISP programming.
  • £5.00 (approx. $6.25): 1m USB cable.
  • £6.00 (approx. $7.50): acrylic enclosure (frosted black or clear - including screws, nuts spacers).

Click here for a currency conversion web site.

Want one?

Important: this is not an offer for sale. We won't manufacture a batch unless there is sufficient demand so please contact us if you would like one.


AVRgpp is a "soft" device - its functions are determined by the program stored in its flash memory. ("Program", "code" and "sketch" are synonymous on this page.) The ATmega328P on AVRgpp could be programmed to do a lot more - it just depends on someone developing the right code!


AVRgpp does not cover the full range of AVR processors for programming - it supports those with the "traditional" 6-way ISP header and those with single wire UPDI programming.

To be accurate it supports those ISP processors supported by the Arduino IDE and AVRDUDE - plus UPDI processors supported by megaTinyCore.

The USB to serial interface should work with anything.


There are few UPDI programmers but a lot of superb open source software developed by various people around the world. Two of us (Mike, software, and Brian. hardware) therefore decided to build on their efforts and develop a programmer which is available for anyone to make or manufacture as Open Source Hardware

Shout outs

Many thanks to:

  • El Tangas for the original jtag2updi and very helpful advice on linking it with the AVRgpp menu.
  • Spence Konde for megTinyCore, an Arduino based programmer and helpful suggestions.
  • "MCUdude" for his original idea for a UPDI programmer. We took his idea and went over the top!


The AVRgpp hardware design and associated files are provided under the terms of the Creative Commons Attribution 4.0 International licence.

No warranties of any sort are provided for AVRgpp, the contents of this page or the files available in the download area. AVRgpp is designed for hobby use not commercial use and no liabilities of any sort will be accepted for the use of AVRgpp or the contents of this page. You are on your own, use at your own risk.

Wordcraft retains no intellectual property rights in relation to AVRgpp hardware and anyone may use any of the hardware related information on this page in any way they wish. Note: this applies only to the AVRgpp hardware described on this page. Others may or may not retain intellectual property rights in relation to software and other third party items referred to on this page.


AVRgpp hardware is unsupported.

The most common problems are covered in the trouble shooting section of this page.

Anyone requiring software support should follow the links to the various Open Source Software referred to on this page. or raise questions on the various Arduino and AVR forums.

Contact us with ideas for improvements to the AVRgpp.

Wordcraft has no commercial interest in AVRgpp and is a company developing, selling and supporting its own products. It has wages to pay and costs to cover so it will not respond to support requests concerning AVRgpp.

Why do we need programmers?

A "programmer" in this context is a device which uploads code to a processor, not a person who writes code.

The Arduino project arose from a very simple but elegant idea: to write code which will run on a wide variety of different processors in the Atmel (now Microchip) AVR range

Code written using the editor in the Arduino Integrated Development Environment (IDE) is compiled (using the "avr-gcc" open source compiler) into instructions suitable for a specific processor mounted on a specific board. Once compiled the code is uploaded to the board (using the "AVRDUDE" open source uploader).

Uploading is done from a PC USB port via a serial link (see below) to the target board. The same serial link may be used by the code to send data to the PC and to receive data from it. This ability to quickly program and test (using debugging and other messages sent from the code to the PC) over a single connection is one of the keys to Arduino's success.

In order to receive and store code sent over the serial link the processor requires some initial code - a "bootloader" - uploaded via a programmer. Different processors may require different bootloaders or different versions of a single bootloader - like the open source "optiboot" bootloader. The bootloader required for a specific board/processor is determined automatically by the IDE.

Schematic, PCB, pinouts and "front-end"


Personal preference determines how schematics are laid out - you say "tom-ato", I say "tom-ahto".

The one below links everything to everything because the AVRgpp is simple and small. Other people prefer to break down a schematic into logical parts, like Lego bricks, which readers have to put together in their minds. The hardware world mirrors the software world: some people prefer the Lego bricks of object oriented programming, others prefer procedural programming. Nothing is "right" or "wrong" - it's a matter of what suits and what gets the job done on target and within budget.

A PDF of the schematic is available from the downloads area.


Eagle files will be available from the downloads area.


ATmega328P pinout:

AVRgpp 6-way vertical headers:

Pin 1 is labelled on the PCB for each header.

VCC (if enabled by PD5 - see pinout above) is set by the "5V/3V3" switch for the ISP Out and both target headers.


The "front-end" is the part of a system you see - the OLED menu structure and buttons in the case of AVRgpp.

AVRgpp's heavy lifting is based on two pieces of open source software: "arduinoisp.ino" which comes with the Arduino IDE and turns an ATmege328P into an ISP programmer, and "jtag2updi" which turns it into a UPDI programmer. "arduinoisp.ino" is a single sketch with relatively straightforward code while "jtag2updi" is a much heavier beast, a "C" project tweaked to compile in the Arduino IDE and with multiple modules - some of which can be daunting for the average Arduino user!

The AVRgpp front-end brings these two pieces of software together with tweaks to enable them to live alongside one another. It then adds the OLED/button interface, the USB to serial interface and functions to enable target power (if required) and the optional 12V pulse for UPDI programming.

Memory shortage

AVRgpp ran out of memory - not program memory (32KB) but SRAM (2KB).

The program code doesn't take up a huge amount of room but the two pieces of programming software plus the front-end used up all the SRAM. Textual messages and the 512 byte buffer for the OLED took up quite a lot. Font definitions also take up a lot of space, even when put into program memory.

There are a number of strategies to reduce SRAM usage:

  • Put all the messages in program memory using the PROGMEM function. This was tried and it reduced SRAM usage to about 82% - which still felt a little tight.
  • Add a 23K256 32KB SPI SRAM and put the OLED buffer in it. This would work but means more hardware.
  • Scrap the OLED buffer and the fonts.

Since AVRgpp uses a relatively small number of OLED messages the third option was chosen by:

  • creating the messages as 512 byte bitmaps,
  • storing them in program memory,
  • copying them directly to the OLED without requiring a buffer.

A simple program was written, "messagegen.ino", to create the OLED messages and output them to the serial monitor in a form that could be added to the AVRgen front-end code. So, "messsagegen.ino" writes code - well, it writes definitions that can be included in code to store the bitmaps in program memory!

This may seem relatively convoluted but it also saves code space because no fonts are used and no functions are required to write to the OLED buffer - because there is no OLED buffer!

Theory of operation

Ignore this section if you are happy with in service programming, bootloaders, serial communications and the joys of resetting processors. On the other hand, it is always helpful to refresh your knowledge.

Building a system step by step

Processors straight from the factory contain microcode that enables them to be programmed. Microcode is hardwired, takes up no program memory, can't be changed and can do just enough to get code into program memory.

The actual method used will depend on the individual processor - the ATmega328P can be programmed in two or three ways but the most common is via an In Service Programming (ISP) header.

Let's built a computer using the ATmega328P.

  • Step 1: our lonely processor can do nothing - it has no power.
  • Step 2: a USB port can provide 5V.
  • Step 3: the processor requires a heartbeat, a clock. This is provided by the 16MHz crystal.
  • Step 4: we can get code into the processor via the 6-way ISP header.
  • Step 5: the processor's serial port can talk to a PC via a serial to USB converter chip.
  • Step 6: we can add a button and an LED to check our code is running.

We have turned our processor into a computer system with keyboard, display and communications!

AVRgpp can function as an ISP programmer to get code into the processor. In many cases this is as far as you need to go. After all, a burglar alarm that monitors sensors, flashes lights and makes noises is unlikely to require a change of code when it has been sold.


Not much has changed with computers over the last half century or more. Certainly things have become smaller, faster, more powerful and cheaper - but the basic principles are the same.

In September 1968 the author of this page booted his first processor - an IBM System 360/65 (cost for a single 360/65 system was about $20,000,000 in today's money).

It was called "Initial Program Load" (IPL) and was done with a blue (IBM blue!) button in the bottom right hand corner of the console. The dials above the "Load" button set the address of the device from which the bootloader was to be loaded - usually drum, disk or tape.

Once the bootloader was in place, user programs, most often on punched card, could be loaded via an IBM 1442 card reader using commands typed into the console golf ball typewriter.

The computer had 512KB of ferrite core memory, was water cooled at speeds up to 16MHz (it could give an ATmega328P a run for its money) and crashed several times a shift (like Windows XP) - so the "Load" button was in frequent use. Three 360/65s were linked together with an operating system called HASP to make the biggest and most expensive multi-processor system in the UK at the time.

The red buttons were for panicking and the lights were "real" light bulbs, not LEDs.

At 3.00am, when work jobs were done, the right assembler code could be loaded and the machine played tunes on a radio tuned to the correct frequency to pick up interference patterns coming from the ferrite core. Tunes could also be played on the IBM 1403 chain printer but it tended to wear out the chain! It took a lot of trial and error iterations to get the code right!

Click the image for a larger version.

Why do we need bootloaders?

(Warning: there are a few sentences below you may need to read twice to ensure you understand them!)

  • You may produce a product that connects to a PC USB port and you may want to provide updates to the internal code when the product is in the hands of a customer. You certainly don't want the customer to understand microprocessors or to go out and buy an ISP or UPDI programmer!

    You want to upgrade the firmware over the normal USB link between the customer's PC and the product.

  • To do this we need something inside the processor that recognises when it is being reprogrammed and this something is the bootloader code.

    When the processor is reset (or the power is turned on) the processor starts running code from a particular location in its program memory - if the bootloader starts at this location it will get control as soon as the processor is reset.

    The bootloader can hang around for a while (a few milliseconds or even a few seconds!) looking at its serial port to see if a program wants to be downloaded. If, after a reasonable time, it sees nothing it gives up and hands over to ("jumps to") any program already stored in program memory.

  • So, to get a new program into memory we must reset the processor so the bootloader can run.

    The processor is reset when power is applied to the processor, when it resets itself (a "software reset"), when a device is plugged into a USB port or when an application on the PC opens a serial port. The USB events cause a low signal level, (Data Terminal Ready, DTR), to be sent from the PC over the USB port to the device. The Arduino IDE uploader, AVRDUDE, opens a serial port (and therefore resets the processor) before it can communicate with the bootloader to upload code.

    The USB-to-serial chip (CH330N in the AVRgpp) converts the DTR signal into a low level on a line (the DTR or RTS line) which is connected to the Reset pin of the processor. A constant low level on Reset would hold the processor in reset mode - not a good idea if we want to communicate with it! So, the DTR/RTS line is connected to other circuitry before it reaches the processor and this converts the low signal into a low then high pulse so the processor is reset and then carries on to run the bootloader to receive the upload from AVRDUDE.

Job done!

Yes - for processors with a dedicated reset pin programmed via ISP. AVRgpp can handle that.

ATtinys and UPDI

Problem: there is no dedicated reset pin on some processors like the ATtinys that are programmed over a single Unified Program and Debug Interface (UPDI) pin. Even worse, the UPDI pin may have been assigned from a programming line to a reset line or an I/O line.

There are hardware and software solutions:

  • The hardware solution must be used if the UPDI pin has been assigned away from programming.

    A 12V pulse sent up the UPDI pin scares the processor into resetting that line as UPDI - not as reset and not as GPIO. Once forced into UPDI mode we can now reprogram it in the normal way. This requires a programmer capable of generating 12V - AVRgpp can do this.

    We can now program a bootloader into the ATtiny and, from then on, all future uploads can be done over the serial interface.

    AVRgpp can be used as a UPDI programmer to get the bootloader (or any other code) into the ATtiny.

  • However, our customer in the field doesn't have an AVRgpp or any other form of programmer so we need a software solution for uploading programs - assuming UPDI is left as a programming pin and the bootloader is in place.

    Note: UPDI programming is required only to install the bootloader, the UPDI pin can be disconnected from AVRgpp after this is done.

    Problem: we don't have a dedicated reset pin to get the bootloader running to receive code from AVRDUDE and, even when the bootloader is running, it will hang around for only so long before giving up. We have to physically reset the processor (power off, power on) and then we have 8 seconds to get our first program uploaded

    Once we have the first program in memory it would be nice to find a way to reset the processor when AVRDUDE wants to upload something else. We can do this with a software reset which every program uploaded should support. This requires an additional pin to monitor the DTR line but it is elegant in its simplicity - with no hardware required!

    // PA7 - IDE pin 3
    #define DTRPin 3
    void setup () {
      // Interrupt on falling edge of pin 3 (PA7)
      attachInterrupt(DTRPin, DTRLow, FALLING);
    // Routine to handle interrupt
    void DTRLow() {
      // Software reset to return to bootloader

How does this work?

We are attaching an interrupt to DTRpin (which could be any spare pin) so when the processor sees this pin falling from high to low it will interrupt what it is doing and jump to the DTRLow routine which contains a single line which causes a software reset.

So, your code can be merrily doing its thing but as soon as AVRDUDE (or any other PC application) opens a serial port to cause DTR to go low, your code will be interrupted, the processor will be reset and the bootloader will get control so, in the case of AVRDUDE, the new code can be uploaded.

Of course, if the serial port was opened by an application other than AVRDUDE, the bootloader will give up waiting and hand over control to any program already stored in program memory.

How you get your customer to run AVRDUDE is up to your imagination - but making it part of your PC app might be a good way to go! You could even write your own bootloader and your own uploader.

UPDI summary

  • Use AVRgpp to install a bootloader into the target ATtiny via UPDI. Disconnect the UPDI pin afterwards.
  • Use AVRgpp as a serial interface (see below) to link the target to the PC.
  • Prepare your first Arduino IDE sketch for the target (complete with the software reset code described above) and compile it to make sure it is clean..
  • To install the first program, reset the target (by removing and restoring power) and upload the sketch within 8 seconds.
  • To upload future sketches ensure that the DTR/RTS line is connected to the DTRpin defined for the software reset code.

Serial communications

In "the olden days" of the 1960s terminals were often connected to mainframe computers over "serial" links. A serial link can be thought of as two wires:

  • The transmitting ("Tx") pin on device A sends data to the receiving ("Rx") pin on device B.
  • The transmitting ("Tx") pin on device B sends data to the receiving ("Rx") pin device A.
  • Data is in the form of individual bits ("1"s or "0"s) that follow one another (serially) down the wire.
  • The speed of communications is expressed in bits per second (bps) - sometimes shown as "baud rate". In "the olden days" this may have been as low as 300 bps (the first acoustic modems operated at 300 bps) and 9600 bps was seen as "fast". The ATmega328P running at 5V and 16MHz can handle 115200 bps each way.
  • bps can be converted very roughly to bytes per second (Bps) by dividing by 9 - so 9600 bps is roughly 1066 Bps and 115200 bps is 12,800 Bps. (Why not divide by 8 because there are 8 bits per byte? Because extra bits are used to keep things running smoothly and this "overhead" adds roughly one bit per byte.)

Using the Arduino IDE

Getting code into a processor involves a number of steps.

  • Installing a bootloader using ISP or UPDI. AVRgpp can do this.
  • The Arduino Interactive Development Environment (IDE) is used to write code for a "target" microprocessor.
  • The code is "compiled" into instructions understood by the target.
  • The compiled code is "uploaded" to the target. A program called "AVRDUDE" does the uploading.

    The AVRgpp has been designed to operate as a serial interface converting USB to serial so AVRDUDE can upload code directly to a target from the IDE.

    The AVRgpp has a switch to direct the serial lines from the CH330N to either the target or to the ATmega328P. This means the code within AVRgpp can be changed - one set of code allows it to be used as an ISP programmer, another set allows it to be used as a UPDI programmer.

  • Uploading is done from a PC over a USB port. USB is a complicated "protocol" and most target processors like the ATmega328P don't speak USB!
  • Dedicated chips have been invented to convert USB into serial and serial into USB. The AVRgpp uses a CH330N chip to do this.

A bootloader for the AVRgpp

The AVRgpp could be supplied with a bootloader already installed (the same one used for the Pro Mini) or one can be uploaded to it from the Arduino IDE using a programmer such as the Atmel-ICE, the AVRISP mkII (discontinued by Microchip but try a Google search for "AVRISP mkii"), a USBasp or another AVRgpp.

Connect the "ISP in" header on AVRgpp to the chosen programmer then, from the IDE, select "Tools", "Pro Mini", "ATmega328P (5V, 16MHz)", the correct programmer, then "Burn Bootloader".

The example below used the AVRISP mkII to burn the bootloader into AVRgpp.

ISP programming

The photo below shows a typical target board with a 6-way ISP header on the right. A white dot on the PCB close to the header indicates pin 1. This header will be used to get the initial code (a bootloader or a complete application) into the processor on the board (the processor is on the other side of this board.)

The photo below shows the target connected the "ISP Out" header of AVRgpp which is itself connected to a PC via USB.

The red side of the ribbon cable is inserted into the target's 6-way header at the end marked by the white dot.

The steps for ISP programing are described above.

As well as burning bootloaders via ISP you can upload code directly to the target board (rather then going via the serial link) from "Sketch", "Upload using programmer" (or Ctrl+Shift+U).

Important note:

Uploading using a programmer allows your code to use all the program memory of the target processor - including space occupied by a previously uploaded bootloader. So, if you wish to upload future sketches via the serial link you must burn the bootloader first.

UPDI programming

You must add megaTinyCore to the IDE before programming ATtinys via UPDI.

The UPDI single wire programming interface is used on many of the latest AVR processors such as the ATtiny1614.

Adding support for the ATtinys

Before you can use AVRgpp for UPDI programming you must add support for these processors to the Arduino IDE. You can then write code for them and upload bootloaders and code using AVRgpp.

Support is provided by "megaTinyCore" and the simplest way to add it to the IDE is:

  • go to "File", "Preferences",
  • find the section "Additional Boards Manager URLs",
  • copy and paste this link:

  • go to "Tools", "Boards", "Boards Manager",
  • select "megaTinyCore by Spence Konde" and click "Install",

  • Advice: return to "Boards Manager" periodically and check that you have the latest version of megaTinyCore.

From the "Tools" menu you will now be able to select a range of processors supported by megaTinyCore.

The example below shows selection of the ATtiny1614 with optiboot bootloader.

The steps for UPDI programing are described above.

USB to serial interface

As described above, the "normal" way to upload code from the IDE is via a serial link which enables AVRDUDE on the PC to communicate with the bootloader in the target processor. It also enables code in the target to communicate bi-directionally with the PC.

USB has replaced the older serial connector on PCs so something has to convert from USB to serial, and from serial to USB. AVRgpp contains a CH330N chip which enables it to act as a bi-directional USB to serial interface.

The steps for using AVRgpp as a USB to serial interface are described above.


At first glance AVRgpp's firmware may look complicated - because it is!

We won't get into arguments about "style" and the "right" or "wrong" way to do things. Mike is an old-fashioned hacker - he started with 360 assembler, then PL/1, then PET Basic, then 6502 assembler, then years of building and running a company and employing people, then VB6, then AVR assembler then Arduino-type "C". He hates smartarse, "clever", show-off code and likes to see things clearly and prefers code on one side of the page and comments on the other so one can follow the logic simply by reading the comments. The days of 80 column terminals are long-gone and we now have big, high resolution displays - so why not use the space?

He also likes to make it clear where one function ends and another starts - again, for ease of reading - and to make it look pretty - "it may not work, but it sure looks pretty!" He has tried to edit most of the code "his way" but some of it is so "dense" that it needs more thought!

Please don't moan about "style" - if you don't like it, do it your own way - that's the joy of open source!

Other firmware

There is nothing to stop you treating AVRgpp as an Arduino Pro Mini and downloading different firmware - for example: the default "ArduinoISP" sketch that comes with the IDE or the original "jtag2updi" code. There will be no front-end, no OLED messages, no button usage and they can't both be downloaded at the same time (!) - but they should work.

There are three main parts to the "standard" AVRgpp firmware:


Written by Mike, this provides the OLED and button menu and calls the other code as required.

There are two parts:

  • avrgpp....ino: this is the front-end code. The "..." is replaced by the version number.
  • avrgpp.h: definitions etc. used by the front-end code including bitmaps for OLED messages.

ISP programming - based on ArduinoISP

Severly edited by Mike but originally written by Randall Bohn.

There are two parts:

  • avrisp.ino: this is the ISP programming code which responds to commands from AVRDUDE.
  • stk500_v1.h: this contains definitions etc. relating to version 1 of the STK500 protocol.

UPDI programming - based on jtag2updi

This is quite heavy stuff - just finding a way to call it, and escape when done, took several hours of sweated labour - it wasn't designed as an Arduino IDE friendly app. Severely edited by Mike but originally written by El Tangas who did a great job in getting UPDI programming sorted.

There are multiple parts:

  • jtag2updi.ino: this is the high level code that sets up various ports (buttons, VCC if required, 12V if required, LED) and identifies commands from AVRDUDE.
  • JTAG2.cpp: this receives and responds to JTAG commands from AVRDUDE. It also carries out CRC checking on JTAG packets.
  • JTAG2.h: definitions etc. used by JTAG2.cpp.
  • JICE_io.cpp: this uses the hardware USART in the processor to provide low level serial communications to receive characters from the PC and to send characters back. The "get" routine is the main loop here so it checks the AVRgpp buttons to see if the user wishes to escape.
  • JICE_io.h: definitions etc. used by JICE_io.cpp.
  • crc16.cpp: this carries out CRC calculations.
  • crc16.h: definitions and lookup table used by crc16.cpp.
  • UPDI_hi_lvl.cpp: UPDI high level code mainly concerned with resetting the target processor.
  • UPDI_hi_lvl.h: definitions etc. used by UPDI_hi_lvl.cpp.
  • UPDI_lo_lvl.cpp: UPDI low level code handling UPDI packets (defined in the target processor datasheet).
  • UPDI_lo_lvl.h: definitions etc. used by UPDI_lo_lvl.cpp.
  • updi_io.cpp: low level communications with the target using a software UART.
  • updi_io.h: definitions etc. used by updi_io.cpp.
  • updi_io_soft.cpp: alternative low level communications with the target using bit-banged serial communications partly implemented in assembler.
  • NVM.h: definitions and functions to support the target's version 1 Non Volatile Memory (NVM) controller.
  • NVM_v2.h: definitions and functions to support the target's version 2 Non Volatile Memory (NVM) controller.
  • sys.cpp: sets up timeouts etc based on processor speed.
  • sys.h: definitions etc. used by sys.cpp.

Simple really!


AVRgpp is small - the PCB is 28mm x 60mm - about 1/3 the size of a credit card.

We have designed an acrylic enclosure (73mm x 41mm x 17.6mm) to protect the connectors and make it less likely to lose AVRgpp! Six acrylic panels, four 3mm x 20mm screws, eight 3mm nuts, four 3mm x 6mm spacers.

Enclosure assembly tips

Put the countersunk screws through the top and drop the spacers into place.

Drop the PCB over the screws/spacers and losely fit the nuts. Do not tighten the nuts at this stage.

Wiggle the sides and ends into place. Check you have them the correct way up so you have easy access to the USB socket, Vcc switch, test/debug port and 6-way header.

Tighten the nuts then drop the back into place - you may need some more wiggling before the sides fit through the holes in the back.

Add the four remaining nuts and the sticky feet.

A 5.5mm nut spinner with the tip ground down is very useful for fitting 3mm nuts in tight spaces.

Trouble shooting

Most problems can be put down to:

  • not having the latest version of something,
  • compiling for the wrong target for serial programming. E.g.

    To put code into AVRgpp's on-board ATmega328P you must select "Pro Mini", "ATmega328P (5V, 16MHz".

    To put code into a target with an ATmega328P you must select "Pro Mini", "ATmega328P (5V, 16MHz".

    To put code into a UPDI target (ATtinyxxx) you must select it from the megaTinyCore list.

  • trying to upload using the wrong port,
  • installing the wrong bootloader - check the target board/processor/options,
  • setting switches incorrectly (putting 5V up a 3,3V target may destroy it),
  • getting confused.

So, check the Quick start instructions and then check:

  • Do you have the latest firmware in your AVRgpp?
  • Are you using the latest version of the Arduino IDE?
  • Are you using the latest version of megaTinyCore to support ATtinys?
  • Have you selected the correct protocol (ISP or UPDI) with AVRgpp?
  • Is the 6-way cable the right way round if using ISP programming? Red wire to pin 1 at both ends.
  • Have you connected UPDI to UPDI and Gnd to Gnd if using UPDI programming?
  • Have you selected the correct target board, processor and settings? For example: "Pro Mini", "ATmega328P (5V, 16MHz)" or"ATtiny1614 ... (optiboot)".
  • Have you selected the correct programmer within the Arduino IDE for burning bootloaders?

    "Arduino as ISP" for burning via ISP.

    "jtag2updi (megaTinyCore)" for burning via UPDI.

  • Have you selected the correct port for burning bootloaders or uploading code?

    Use Windows Device Manager to check which COM ports are connected.

  • Have you burnt the correct bootloader to the target before trying to compile and upload code?

    For ATtiny processors supported by megaTinyCore you must select the one with "(optiboot)" at the end of its name in the list,

    You must start a serial upload within 8 seconds of the ATtiny being reset.

  • Check the "5V/3V3" switch is set correctly for the target if you are using AVRgpp to power the target.

  • Note: an ATmega328P can support bidirectional serial up to 115200bps when operating at 5V with a 16MHz clock. At less than 16MHz it can support up to 57600bps. AVRgpp operates at 5V with a 16MHz clock.

Files available

Very important notice

Like all projects, this project is on-going and may change (or even disappear) without notice at any time.

The files created by us are open source and provided "as is" - with no warranties of any sort.

No correspondence will be entered into in relation to these files or this project.

You are free to make use of the information here in any way you wish - without support from us.

Sorry to sound so negative but we have other tbings to get on with and life is getting shorter by the day ....

For download:

Freely available on request

Doing things this way means we keep a handle on who may be using this stuff - it would be great if someone decided to make thousands of AVRgpps and sell them at a really good price ....

So, please contact us for:

  • Latest AVRgpp firmware source code (unsupported).
  • Latest AVRgpp BOM (Bill Of Materials - uncosted).


Please contact us (Mike and Brian) at avrgpp@wordcraft.com.