Print this Post

Prime-ary Prototype: Complete!

For the last several weeks I’ve been hacking together a small prototype of a microcontroller (ATTiny2313)-powered prime number generator. I can finally say that it (the prototype) is complete, functional, and elegant [get the song I’m referencing while it’s up!]. The name says what it does, so I won’t waste time describing it. If you’re interested in how it does what it does, check out the other posts with the same category tag for a full (and I mean full as in “more than you ever wanted to know”) description. A schematic is soon to come. Code is below. For now, here’s a video of the completed project:

And the source code I used. I chose the ATTiny2313 because it was cheap (~$2) and has 18 IO pins to work with. I had to fight memory usage every step of the way. I’m limited to 2kb, and this program compiles within 1% of that! For future projects (more LEDs, more menus) I’ll use the 20-pin and/or 40-pin ATMega series. I’m thinking about having one be in charge of the display (multiplexing) leaving the other to think about generating prime numbers.

#define F_CPU 10240000
#include <avr/interrupt.h>
#include <util/delay.h>
#include <math.h>

// ~~~ PORT D ~~~
#define r1 0b00000100
#define r2 0b00000010
#define r3 0b00001000
#define r4 0b00100000
#define r5 0b00010000
#define f1 0b01000000
#define id 0b00000001
#define f0 0b10111111

// ~~~ PORT B ~~~
#define c1 0b00010000
#define c2 0b00000001
#define c3 0b00000010
#define c4 0b00000100
#define c5 0b00001000

char delay=1;
int redo=0;

char rows[] = {r1,r2,r3,r4,r5};
char cols[] = {c1,c2,c3,c4,c5};
char vals[] = {0,0,0,0,0};
char funcs=f1+id;
unsigned long showNum=5;//33554431;

void displayNum();
void incrimentNum();
void menu_pause();
void menuCheck();
char button();
char isPrime(unsigned long);
unsigned int twoTo(char);

int main(void) {
  DDRD = r1+r2+r3+r4+r5+f1+id;	
  DDRB = c1+c2+c3+c4+c5;	
  DDRB &= ~_BV(DDB7);
  PORTB = 0;	
  PORTD = 0;
  unsigned int i=0;
  int j;
  while (1) {
    if (isPrime(showNum)){
    for (j=0;j<redo;j++) {
    if (i%10==0){funcs^=r1;
      if (i%100==0){funcs^=r2;
        if (i%1000==0){funcs^=r3;i=0;       
  return 0;

char isPrime(unsigned long test){
  if (test%2==0) return 0;
  unsigned long div = 3;
    if (test%div==0) return 0;
  return 1;

void menu(){
  char j,but;
  but = button();
  if (but==0) return;
  else if (but==1){
    while (1) {
      if (PINB & _BV(PB7)) {
        for (j=0;j<200;j++){
          if (j%25==0) funcs^=r1;
      else {      
        if (redo==0) redo=200;
        else redo=0;

char button(){
  if (PINB & _BV(PB7)) return 0; // not pressed
  if (PINB & _BV(PB7)) return 1; // pressed
  return 2; // held down

void convertNum(){
  char col,row,rowcode;
  unsigned long msk=1;
  for (col=0;col<5;col++){
    for (row=0;row<5;row++){
      if (showNum&msk) rowcode+=rows[row];
      msk = msk < < 1;

void displayNum(){
  char i,j;
    PORTB = 0b0;
    PORTD = funcs; 
    for (i=0;i<5;i++){
      PORTD = vals[i];
      PORTB = cols[i];

About the author

Scott W Harden

Scott Harden has had a lifelong passion for computer programming and electrical engineering, and recently has become interested in its relationship with biomolecular sciences. He has run a personal website since he was 15, which has changed names from HardenTechnologies.com, to KnightHacker.com, to ScottIsHot.com, to its current SWHarden.com. Scott has been in college for 10 years, with 3 more years to go. He has an AA in Biology (Valencia College), BS in Cell Biology (Union University), MS in Molecular Biology and Microbiology (University of Central Florida), and is currently in a combined DMD (doctor of dental medicine) / PhD (neuroscience) program through the collaboration of the College of Dentistry and College of Medicine (Interdisciplinary Program in Biomedical Science, IDP) at the University of Florida in Gainesville, Florida. In his spare time Scott builds small electrical devices (with an emphasis on radio frequency) and enjoys writing cross-platform open-source software.

Permanent link to this article: http://www.SWHarden.com/blog/2009-06-10-primary-prototype-complete/


  1. Daniel Holth

    I’m not the only one eagerly awaiting the 4kb successor to the ATtiny2313.

    Most of your code size is probably from linking in math libraries. You might be able to change your algorithm slightly to avoid doing that.

  2. Yann Vernier

    Actually, the code doesn’t seem to use anything from math.h/libm (such as, for instance, sqrt). I would guess most of the code size comes from how it has been compiled; I tend to use avr-gcc -Os -fwhole-program. The costly calls in there are multiplication (the tiny2313 doesn’t have a multiplier), division and modulo (32-bit, no less), and, if you have an unfortunate combination of avr-libc and compiler settings, the delay calls themselves.
    A quick test at compiling that way yielded an 870 byte program. Leaving out -fwhole-program means it can’t eliminate or simplify any functions, and then I got sizes around 4.5k, easily twice as large as a 2313. Since that wouldn’t fit at all there’s probably some middle ground I’m missing.

  3. Yann Vernier

    Found the culprit. The delay functions are meant to be called with constant values, and delay was declared as a variable. With -fwhole-program, gcc could tell it was never written. Adding “const” to the declaration char delay=1; caused the code to drop to under 1k. Thus it really did generate floating point code, for a single constant 1, no less.

    1. Bill Morrison

      I hope you get this reply. I know it’s been over 2 years since you’ve last posted but I’d like to ask if you could look over a problem I’m having. I’ve compiled the above code for Scott’s Prime Number Generator. The way I’ve compiled this code is using the following from the command line:

      Compiling and Linking

      avr-gcc -g -Os -mmcu=attiny2313 -c Prime2313.c
      avr-gcc -g -mmcu=attiny2313 -o Prime2313.elf Prime2313.o

      Linker Map Files

      avr-gcc -g -mmcu=attiny2313 -Wl,-Map,Prime2313.map -o Prime2313.elf Prime2313.o

      Generating Intel Hex Files

      avr-objcopy -j .text -j .data -O ihex Prime2313.elf Prime2313.hex

      After all is done I get a HEX file that is over 2K in size. Could you tell me how you made your file smaller? Thanks for any help.

  4. Kenneth Finnegan

    Very nice, but as far as your display, I think you should invest a little time into learning how to use the timer interrupts on the AVRs. It makes for much easier coding, generally smaller code size (the function calls are implicit) and is one of the first steps towards low power consumption programming (replacing the idle loops with sleep calls). I wrote up a relatively simple example using this a few months ago: http://kennethfinnegan.blogspot.com/2010/03/attiny2313-four-digit-clock.html

  5. Bill Morrison

    Is it possible to get the hex file for your Prime Generator Program? I’m not that knowledgeable on how to compile code. I just want to put together this circuit more for show then anything else.

  6. no credit check loans uk

    Please let me know if you’re looking for a article writer for your blog. You have some really great articles and I feel I would be a good asset. If you ever want to take some of the load off, I’d really like to write some articles
    for your blog in exchange for a link back to mine. Please shoot me an
    e-mail if interested. Kudos!

  7. Hobbies For Men

    Hello great website! Does running a blog such as this take a
    lot of work? I’ve no understanding of programming however I
    was hoping to start my own blog soon. Anyways, should you have any ideas or techniques for new blog owners please share.
    I understand this is off topic but I simply needed to ask.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>