#define F_CPU 7372800UL

#include <avr/io.h>

#include <avr/interrupt.h>

#include <util/delay.h>

#include "bcd_7segment.h"


uint8_t position = 4;

uint8_t myValue = 0;


ISR(TIMER0_OVF_vect) {

   PORTH ^= _BV(PH1);

   position--;

   load_digit_paterns(position % 4, myTable[myValue % 4]);

   myValue++;

}


int main(void)

{

   init_7_segment();

   timer0_init();

   sei();

   

// used for LED7

   DDRH = _BV(PH1);        

   float myFloat = 0.001;

   display_7_segment(myFloat, 4);

   while(1)

   {

       myFloat = myFloat + 0.001;

// prepare array

       display_7_segment(myFloat, 4);

       _delay_ms(300);

   }

}


#include <avr/io.h>

#include <stdio.h>

#include "bcd_7segment.h"


const uint8_t patterns[] =  {

   0xfc, 0x60, 0xda, 0xf2, 0x66, 0xb6, 0xbe, 0xe0,

   0xfe, 0xf6, 0xee, 0x3e, 0x9c, 0x7a, 0x9e, 0x8e };



void load_shift_register(uint8_t pattern) {

   uint8_t value;

   uint8_t count = 8;

   do {

       value = pattern;

       value = value & 0b00000001;

       if(value == 0) {

           PORTB &= ~(1 << DS);

       }

       else {

           PORTB |= 1 << DS;

       }

       pattern = pattern >> 1;

       // pulse SHCP

       PORTB |= 1 << SHCP;

       asm("nop");

       asm("nop");

       PORTB &= ~(1 << SHCP);

       // 8 bits

       count--;                    

   } while (count > 0);

}



void load_digit_paterns(uint8_t digit, uint8_t pattern) {

   load_shift_register(pattern);

   PORTL = 0x00;

// strobe storage register

   PORTK |= 1 << STCP;            

   asm("nop");

   asm("nop");

   PORTK &= ~(1 << STCP);

   digit = digit % 4;

   PORTL |= 1 << digit;

}



// snprintf: flags for linker:

// -Wl,-u,vfprintf -lprintf_flt -lm

void display_7_segment(float value, uint8_t no_of_decimals) {

   char myStrTable[20];

   // convert from float to string

   snprintf(myStrTable, 20, "%f", value);

   uint8_t j;

   uint8_t k = 0;

   static uint8_t myPointer;

   static uint8_t myValue;


   for (j = 0; j < 5; j++) {

       // is it a dot?

       if (myStrTable[j] == 0x2e) {

           // take the previous digit

           j--;

           k--;

           myPointer = myStrTable[j] - 0x30;

           myValue = patterns[myPointer];

           // add a dot (DP is LSB)

           myTable[k] = myValue + 1;

           j++;

           k++;

       }

       else {

           // 0x30: from ascii to decimal

           myPointer = myStrTable[j] - 0x30;

           myValue = patterns[myPointer];

           // update the BCD-table

           myTable[k] = myValue;

           k++;

       }

   }

}



void timer0_init() {

   // turns on the interrupts

   TIMSK0 = (1 << TOIE0);

   TIFR0 |= (1 << TOV0);

   TCNT0 = 0x0000;

   

   // start timer0 with /256 prescaler (p. 161)

   TCCR0B |= (1 << CS02);

   TCCR0B &= ~(1 << CS01);

   TCCR0B &= ~(1 << CS00);

}



void init_7_segment() {

   DDRB = (1 << SHCP) | (1 << DS) | (1 << MR);

   DDRK = 1 << STCP;

   DDRL = (1 << A) | (1 << B) | (1 << C) | (1 << D);

   

   // reset 74595

   PORTB &= ~(1 << MR);

   asm("nop");

   asm("nop");

   asm("nop");

   PORTB |= 1 << MR;

}