/*
 * Ultasonic echo locator
 * 20 December 2013
 * 
 * PORTE5 - OC3C - Trig
 * PORTE7 - INT7 - Echo
 * ATmega128 code
*/

#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <stdio.h>

typedef unsigned char  u8;
typedef unsigned short u16;
typedef unsigned long  u32;


char          disp[8];

#define BLEN 8
#define I2C_SEND_DATA_BUFFER_SIZE 	BLEN
#define I2C_RECEIVE_DATA_BUFFER_SIZE 	0

void
_delay_zs( int zs )
{
  zs *= 10;
  while ( zs-- )
    _delay_ms( 10 );
}

void
periphInit(void)
{
  DDRD = 0x60;  // enable green & orange LED
  DDRE = 0x20;	// bit 5 output triger
  OCR3A = 0xffff; // TOP value for Timer3
  OCR3C = 10; // approx 5 us pulse 
  TCCR3A = 0xb;	  // clear OC3C on match, mode F fast PWM
  TCCR3B = 0x1a;  // mode F fast PWM, divide clock by 8
  ETIMSK = 4;    // enable timer3 overflow
  EICRB = 0x40;	// any logical change on bit7
  EIMSK = 0x80; // enable INT4 interrupt
}

volatile u16 echo;

ISR( INT7_vect )
{
  static u16 tm;
  u16 cnt;

  cnt = TCNT3;
  if( PINE & 0x80 )
    tm = cnt;
  else
    echo = cnt - tm;
}

ISR( TIMER3_OVF_vect )
{
  PORTD ^= 0x20;
}

int
main( void )
{
  u16 v;

  wdt_enable( WDTO_2S );	// enable watchdog
  i2cInit(  );
  _delay_zs( 1 );
  if ( MCUCSR & _BV( WDRF ) )	// watchdog reset ? 
  {
    dprintf( "Idle" );
    MCUCSR &= ~_BV( WDRF );
  }
  else
  {
    dprintf( "Echo" );
    _delay_zs( 5 );
  }

  periphInit(  );
  sei();
  while ( 1 )			// wait for command
  {
    wdt_reset(  );
    cli( );
    v = echo;
    sei( );
    dprintf( "%d", v / 116 );
    _delay_zs(2);
    PORTD ^= 0x40;
  }
  return 0;
}
