Why are we here and what have we done to deserve this?

Note: All the files here


Understanding what we are doing

This page has the presumptuous objective to serve as a reference and summarize what are ISPs at an understandable level and why we need them for the projects within the FabAcademy program. I am no electronics expert, but I firmly believe it’s important to dedicate some time to understand what’s going on and why we do things before we delve into more complex ideas and build projects on top of them. This page has been inspired by Ali Shtarbanov’s work on demystifying the FabISP and aims to provide further understanding about what an ISP is and why we build one.

Memories in a microcontroller

Let’s start from the very basics and understand how a microcontroller manages it’s memory. In general, there are three types of memory in a microcontroller:

  • Data memory : memory for storing the data processed during run time (including also the registers, stack, etc.). This memory is a volatile memory, meaning, when the device is reset, it will be lost.
  • Program memory: memory in which the program (or code) is stored. This memory is non volatile, meaning that it won’t be lost if the device is reset.
  • EEPROM : memory which can be used for storing non volatile data and changeable during run-time.

Image credit: Arduino

Depending on the type of microcontroller, each memory will have different sizes, or it might not even exist. Here, we will focus on the Program Memory, sometimes also called Flash Memory. Program Memory (also Read-Only-Memory) is used for permanently saving the program (CODE) being executed, and it can be divided into two sections: Boot Program section and the Application Program section.

Boot loader section

In the image above, one might have noticed that there is a dedicated part of the program memory to something called Boot Flash Section. This is also sometimes called bootloader or boot program section and it’s a part of the program that executes after every time there is a reset of the microcontroller. This area of the memory is protected against deletion and can not be rewritten unless one specifically means to do so. It also has the capability to change the major part (application section) of the flash content. The purpose of this bootloader area is to connect the microcontroller to the outer world, for example a PC, and transfer a new firmware into the main part of the flash memory. This is normally done at the very beginning of the microcontroller wake-up and, in case of: 1. failure in the transfer or 2. no PC requesting to send a firmware into the flash, the bootloader should finish it’s job and hand-over the control to the main part of the firmware, if any.

Now, what happens with the ATtiny44? Well, that it simply has no bootloader section in the flash memory, as stated in the Page 159 of the ATTiny Datasheet, and more importantly, it’s not waiting for any external device to program it via Serial Protocol, such as USB. This means that we need other means to access the flash memory of the microcontroller and, for this, we will use an ISP programmer. An ISP programmer is therefore a specialized hardware that will be used to reflash microcontrollers without this bootloader section, which we won’t be able to connect directly to a PC. Also, it can be used to reflash the bootloader into the microcontroller. Further reading can be found here regarding bootloaders and ISP, as well as the Arduino Reference for this topic.

Finally, to have further reference, much more detailed information can be found in this ATMEL/Microchip Application Note.

Implementation on the FabISP

Let’s now go into a more technical detail that might surpass the knowledge thirst of some readers. I really, really, really, really recommend reading Ali’s website and at least the following tutorials for proper understanding of the concepts needed:

For the FabISP we will be using the basic 6-wire programming interface, as specified in the above mentioned ATMEL Application Note:

Where all these pins are explained in the SPI tutorial above:

  • In SPI, only one side generates the clock signal (usually called CLK or SCK for Serial ClocK). The side that generates the clock is called the “master”, and the other side is called the “slave”. There is always only one master (which is almost always your microcontroller), but there can be multiple slaves.

  • When data is sent from the master to a slave, it’s sent on a data line called MOSI, for “Master Out / Slave In”. If the slave needs to send a response back to the master, the master will continue to generate a prearranged number of clock cycles, and the slave will put the data onto a third data line called MISO, for “Master In / Slave Out”.

Image Credit: SparkFun

We can summarize all this in the following image, but note we will be using a different Serial Communication on the PC side:

Image Credit: ATMEL

Now, how do we know where to connect the different pins of the 6-wire connector to the ones in the ATTiny44? From the Section 19.5 of the ATtiny datasheet, we will find all the necessary instructions for the Serial Programming. Below, the needed connections are summarized:

Symbol Pins I/O Description
MOSI PA6 I Serial Data In
MISO PA5 O Serial Data Out
SCK PA4 I Serial Clock

Hardware implementation

Now, we get to the point of implementing this in our hardware. From the already referenced work from Ali, I detail my own understanding of the FabISP below, going through the same series of tutorials and which I believe are necessary to understand the FabISP implementation:

So! Let’s go for it! We’ll split it for better understanding into setting the FabISP as a programmer and as a target. We have to remember that the FabISP will be programmed through the ISP port the first time and not through the USB port (remember the bootloader?).

FabISP as a target

Here is what we really need in terms of hardware to get the ATtiny programmed via ISP:

  • The voltage PIN of the ISP will supply power to the ATtiny44 and is obviously connected to the VCC Pin of the microcontroller. Also, to prevent noise from getting into our supply, it’s wired to ground through C1, a 1uF capacitor, serving as a noise filter for the supply voltage. More filtering could be included in the circuit by adding more capacitors in parallel, however it is probably not necessary. This line will have to be opened with the SJ2 jumper or simply cutting the line once the device has been reprogrammed. Why? Because otherwise, when we use the FabISP as a programmer, we will be using the USB to power both, the FabISP and the device being reprogrammed.

  • Now, reading the Datasheet, we find that the PB3 pin has RESET capability and that both the Flash and the EEPROM can be reprogrammed by serial SPI bus while RESET is pulled to GND (Section 19.5). This means we want the PB3 pin to be set to LOW when we reprogram the ATtiny for the first time (either to RST or to GND) and the rest of the time to be set to HIGH, using the R5 pull-up resistor. Again, this line has a jumper (SJ1) in between the PB3 and the RST pin of the ISP in order to be pull-up once reprogrammed.

  • The rest of the pins are directly connected as in the above table regarding the necessary intructions for Serial Programming.

FabISP as a programmer

Here is what we really need in terms of hardware to once the ATtiny is serving as a ISP programmer:

  • Starting from the USB connector, the voltage is pretty straight forward: it’s connected to the VCC PIN of the ATtiny, it’s pulling-up the PB3 (RESET) pin through R5 and it has the already explained capacitor to filter out noise in the power supply.
  • The USB protocol is based on differential signal and it sends the information based on the D+ and D- lines (indicated as + and - on the diagram). In order to specify that the USB device is a low speed device, the convention is to pull-up the D- signal. Differently, D+ is to be pulled-up if it’s to be recognised as a high speed device. This is done through the R1 and R2 resistors. Both lines are plugged into a couple of Zener diodes + resitors in order to serve as voltage clippers (refer to the above tutorial), limitting the D+ and D- lines to 3.3V, since the I/O pins of the ATtiny could be up to (theoretically 5V), since it’s powered at 5V.
  • Ground is (obviously) wired to GND in the ATtiny and the ISPs GND, as well as to the resonator (or a crystal oscillator, both possibilities accepted) of 20MHz. The latter being connected to the PB0/PB1 pins as referenced in the datasheet:

Image Credit: ATMEL

That’s it! If we sum up both circuits, we get to Neil’s board:

Understanding the Machining process

Through the group assignment, we will go through the process of fabricating a Traces-width board, assessing how separated can our traces be, as well as how thin they could potentially be. The board we will be machinning is found below, and we will be using copper PCBs machined in either a Roland MonoFab SRM-20 or a Modela MDX-20. Here is the link to my colleagues sites:

The traces png file to be machined with a 1/64” tool:

To cut the board out of the copper layer, we will use a 1/32” tool on the following profile:

Both png files will be passed through the FabModules. Note that this tool will detect changes between BLACK and WHITE in the png files and generate a path in it for the machinning process.

The settings selected for the PCB traces are:

  • Upload image as *.png
  • Output file as Roland mill (*.rml)
  • PCB traces (1/64)
  • Machine: SRM-20
  • Origin: X0, Y0 and Z0 are set to 0mm, in order to keep the same origin as the locally defined in the machine
  • ZJog is set to 2mm, meaning that the machine will lift the tool 2mm while not cutting
  • Xhome, Yhome, Zhome are set to 0mm, 0mm and 5mm. The latter being the most important, since it is the value at which the tool will be positioned once the job is finished. If this value it’s zero, it will scratch the whole copper surface, very likely breaking the tool
  • Cut depth: 0.1mm
  • Offset: 4. It’s the number of offsets that the program will calculate out of the BLACK-WHITE transitions. A number of -1 will remove all the copper.
  • Offset-overlap: 50%, relative to the tools diameter (1/64” in this case)

The settings selected for the PCB outline (only detailing the ones that are different):

  • Cut Depth: 0.5mm
  • Stock thickness: 1.5mm
  • Number of offsets: 1

Note that the generated traces with these settings are wrong, apparently because the below line is not properly detected:

In order to solve this, we flipped the image upside down in order to have the cutting traces in the lower side of the cut. Finally, with the selected settings we did not cut through all the material, having to cut manually the board. This can be checked beforehand with a spatula, prior to removing the board from the machine.

After this, the board is cleaned with a razor/blade to remove some parts and finally is sanded with a metal sponge to have a clean result.

Manufacturing the FabISP

Once we know what the FabISP does and how to use the machine, let’s get to manufacture our own actual board! I have made some modifications on Neil’s board, basicly to: add a RED power LED and to add a GREEN LED in the SCK communication with the target (inspired by Brian’s work). I have also made the exercise of routing everything myself again, using KiCad from scratch. I have never done this before, so I did not optimise at all the layout. Below you can find some captures of the PCB layout and the Schematics. All files can be found under this link.

NB: You will find there are actually two designs: one trial with MicroUSB (FabISPMicro), which I find particularly difficult to solder, and another one with a MiniUSB connector (FabISPMini). Below, all the resulting work is related with the FabISPMini:

Below you can also find the PCB layout, with traces of 0.4mm and clearance of 0.4mm as design rules:

I exported SVG files from KiCad and edited them with INKSCAPE, in order to create a more size-friendly PNG, which also is better understood by fabmodules:

And both, the holes (in a separate file) and the cuts outline. This is done separately, first the holes and then the outline, so that the copper doesn’t move once cut and we loose reference:

Machining the board

Using similar settings to those in the Traces-width file, the board is machined on a Modela MDX-20. Some pictures of the process are shown below. A problem occured on a first iteration, breaking the 1/64” tool. This also gave me the opportunity to make the ISP shorter (74mm) - (note that the files above are all updated):

Some captures of the fab.modules are shown below:

And the traces it generated:

Soldering the components

A list of all the needed components, depending on the posibilities of the lab:

  • 1 x ATtiny44
  • 1 x MiniUSB header (or MicroUSB if you want)
  • 1 x 2x3 pin header (6-wire)
  • 2 x 100Ω resistors
  • 1 x 499Ω resistor + 1kΩ resistor
  • 1 x 499Ω resistor + 1kΩ resistor OR 1 x 1.5kΩ resistor
  • 1 x 10kΩ resistor
  • 2 x 3.3v zener diodes
  • 1 x 1uF capacitor
  • 2 x 0Ω resistors
  • 1 x 20MHz resonator
  • 1 x GREEN LED + 1 x RED LED

All these components are shown below. The soldering sequence, following others experience and advice:

  1. The mini USB header
  2. The ATtiny44
  3. All the other passive components
  4. the 2x3 pin header (which gets in the way of the rest)

And the hero shot!:

Programming the ISP

In order to program the ISP, I followed the instruction under this site. We will need to use another ISP and a power cable for it. My advice would be to have a look at the connections and shorts with a multimeter before plugging the board to the computer. A basic check is to set the multimeter in continuity mode, and verify if:

  • there is connection between Vcc and GND (top and bottom lines of the MiniUSB)
  • the diodes are lighting up when checking continuity from anode to cathode and not viceversa
  • all GND are connected: crystal, USB, ISP, ATtiny44…; same with Vcc
  • there continuity between traces before each component

If all this is succesful, if we plug it in to the computer and if using this design, one should see the RED LED lighting up. Leaving it connected, since the ISP will need power, one now should choose another ISP to program it. I chose the AVRISP2, available in the Fablab. Connect it to the board by verifying that GND and GND are properly connected (in my case black cable).

Now, we can download the firmware and the necessary software. The easiest way would be to use CrossPack (we need make, a gcc compiler and avrdude). Once we have it, we can open the terminal and verify the instalation (in MAC) by:

where avrdude

Then, we change directory to the firmware download folder and unzip it.

Firmware cd fabISP_mac.0.8.2_firmware
➜  fabISP_mac.0.8.2_firmware ls
Makefile    main.c      main.elf    main.hex    main.o      usbconfig.h usbdrv

We have to edit the Makefile in case of using a different ISP, rather than AVRISP.

cat Makefile
#AVRDUDE = avrdude -c usbtiny -p $(DEVICE) # edit this line for your programmer
AVRDUDE = avrdude -c avrisp2 -P usb -p $(DEVICE) # edit this line for your programmer

Then, we can proceed by cleaning the .hex file and regenerating it (even if we haven’t modified it, it’s a good idea, just in case):

➜  fabISP_mac.0.8.2_firmware make clean
rm -f main.hex main.lst main.obj main.cof main.list main.map main.eep.hex main.elf *.o usbdrv/*.o main.s usbdrv/oddebug.s usbdrv/usbdrv.s

Make the .hex file:

➜  fabISP_mac.0.8.2_firmware make hex
avr-gcc -Wall -Os -DF_CPU=20000000	 -Iusbdrv -I. -DDEBUG_LEVEL=0 -mmcu=attiny44 -c usbdrv/usbdrv.c -o usbdrv/usbdrv.o
avr-gcc -Wall -Os -DF_CPU=20000000	 -Iusbdrv -I. -DDEBUG_LEVEL=0 -mmcu=attiny44 -x assembler-with-cpp -c usbdrv/usbdrvasm.S -o usbdrv/usbdrvasm.o
avr-gcc -Wall -Os -DF_CPU=20000000	 -Iusbdrv -I. -DDEBUG_LEVEL=0 -mmcu=attiny44 -c usbdrv/oddebug.c -o usbdrv/oddebug.o
avr-gcc -Wall -Os -DF_CPU=20000000	 -Iusbdrv -I. -DDEBUG_LEVEL=0 -mmcu=attiny44 -c main.c -o main.o
main.c:88:13: warning: always_inline function might not be inlinable [-Wattributes]
 static void delay ( void )
avr-gcc -Wall -Os -DF_CPU=20000000	 -Iusbdrv -I. -DDEBUG_LEVEL=0 -mmcu=attiny44 -o main.elf usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o
rm -f main.hex main.eep.hex
avr-objcopy -j .text -j .data -O ihex main.elf main.hex
avr-size main.hex
   text	   data	    bss	    dec	    hex	filename
      0	   2002	      0	   2002	    7d2	main.hex

Set the fuses:

➜  fabISP_mac.0.8.2_firmware make fuse
avrdude -c avrisp2 -P usb -p attiny44  -U hfuse:w:0xDF:m -U lfuse:w:0xFF:m


avrdude: safemode: Fuses OK (H:FF, E:DF, L:FF)

avrdude done.  Thank you.

And finally program it:

➜  fabISP_mac.0.8.2_firmware make program
avrdude -c avrisp2 -P usb -p attiny44  -U flash:w:main.hex:i
avrdude: AVR device initialized and ready to accept instructions
avrdude: verifying ...
avrdude: 2002 bytes of flash verified

avrdude: safemode: Fuses OK (H:FF, E:DF, L:FF)
avrdude done.  Thank you.

avrdude -c avrisp2 -P usb -p attiny44  -U hfuse:w:0xDF:m -U lfuse:w:0xFF:m
avrdude: AVR device initialized and ready to accept instructions


avrdude: verifying ...
avrdude: 1 bytes of lfuse verified
avrdude: safemode: Fuses OK (H:FF, E:DF, L:FF)

avrdude done.  Thank you.

If you are using this version, you should see the GREEN LED lighting up sometimes during the process. Finally, if all this has been successful, one should see the following, under the About this MAC > System Report > Hardware > USB:


Using the ISP as a programmer

Finally, both 0Ω resistors can be removed, in order to use the ISP as a programmer: