#include "millis.h"
#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>

#define DATA 0
#define CLOCK 1
#define LATCH 2

int awaitingEcho;
unsigned long start;
unsigned long duration;
unsigned long interval;

const int DIGITS [10] = {
    0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110,
    0b01101101, 0b01111101, 0b00000111, 0b01111111, 0b01101111
};

ISR(INT1_vect) 
{
  if (PIND >> 3 & 1)
  {
    start = millis() * 1000;
  }
  else
  {
    duration = (millis() * 1000) - start;
    awaitingEcho = 0;
  }
}

void show_distance(int distance)
{
    int index_1 = distance / 100;
    int index_2 = (distance / 10) % 10;
    int index_3 = distance % 10;

    int digits[3] = { 
      DIGITS[index_1],
      DIGITS[index_2],
      DIGITS[index_3]
    };
    
    digits[0] = index_1 == 0 ? 0 : digits[0];
    digits[1] = index_1 == 0 && index_2 == 0 ? 0 : digits[1];

    for (int i = 2; i >= 0; --i)
    {
      int j = 7;
      for (int k = 0; k < 8; ++k)
      {
          if ((digits[i] >> j) & 1)
          {
            PORTB &= ~(1 << DATA);
          }
          else
          {
            PORTB |= 1 << DATA;
          }

          _delay_us(10);
          PORTB |= 1 << CLOCK;
          _delay_us(10);
          PORTB &= ~(1 << CLOCK);
          _delay_us(10);
          j -= 1;
      }
    }

    _delay_us(10);
    PORTB |= 1 << LATCH;
    _delay_us(10);
    PORTB &= ~(1 << LATCH);
    _delay_us(10);
}

int main()
{
  EICRA |= 1 << 2;
  EIMSK |= 1 << 1;
  DDRD |= 1 << 4;
  DDRB |= 1 << DATA;
  DDRB |= 1 << CLOCK;
  DDRB |= 1 << LATCH;
  init_millis(16000000UL);
  sei();

  while(1)
  {
    unsigned long now = millis();
    if (now - interval > 100 && !awaitingEcho)
    {
      show_distance(duration * 0.034 / 2.0);
      PORTD |= 1 << 4;
      _delay_us(10);
      PORTD &= ~(1 << 4);
      awaitingEcho = 1;
      interval = now;
    }
  }
}
74HC595
74HC595
74HC595