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;
  //convertNum();
  //showNum=5;
  while (1) {

    showNum+=1;

    if (isPrime(showNum)){
      convertNum();
    }


    for (j=0;j<redo;j++) {
      displayNum();
      menu();
      }
    if (i%10==0){funcs^=r1;
      funcs^=id;
      if (i%100==0){funcs^=r2;
        if (i%1000==0){funcs^=r3;i=0;
        }
      }
    }
    i++;
  }
  return 0;
}

char isPrime(unsigned long test){
  if (test%2==0) return 0;
  unsigned long div = 3;
  while(div*div<test+1){
    if (test%div==0) return 0;
    div+=2;
    displayNum();
  }
  return 1;
}

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


char button(){
  PORTD=id;
  if (PINB & _BV(PB7)) return 0; // not pressed
  _delay_ms(1000);
  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++){
    rowcode=0;
    for (row=0;row<5;row++){
      if (showNum&msk) rowcode+=rows[row];
      msk = msk < < 1;
    }
    vals[col]=rowcode;
  }
  return;
}

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

     

Leave a Comment