//
// steppad.44
//
// Controller for Scratch programming environment using step response
//
// Kreg Hanning
// 11/8/16
//
// Adapted from:
// Neil Gershenfeld
// 12/8/10
// -and-
// Matt Blackshaw
// 11/8/10
//
// (c) Massachusetts Institute of Technology 2016
// This work may be reproduced, modified, distributed,
// performed, and displayed for any purpose. Copyright is
// retained and must be preserved. The work is provided
// as is; no warranty is provided, and users accept all
// liability.
//

#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>

#include "steppad.44.h"

void put_char(volatile unsigned char *port, unsigned char pin, char txchar) {
  static int i;

  // start bit
  clear(*port,pin);
  bit_delay();

  // loop to write data bits
  for (i=0; i<8; i++) {
    if bit_test(txchar,i)
      set(*port,pin);
    else
      clear(*port,pin);
    bit_delay();
  }
  bit_delay();

  // stop bit
  set(*port,pin);
  bit_delay();

  // char delay
  bit_delay();
}

void put_string(volatile unsigned char *port, unsigned char pin, char *str) {
   static int index;
   index = 0;
   do {
      put_char(port, pin, str[index]);
      ++index;
      } while (str[index] != 0);
   }

void check_pin(unsigned char pin) {
	unsigned char up_lo,up_hi,down_lo,down_hi;

	// set the A/D pin
	ADMUX = ref | pin;

  //
  // settle, charge, and wait 1
  //
  settle_delay();
  set(charge_port, charge_pin);
  charge_delay_1();
  //
  // initiate conversion
  //
  ADCSRA |= (1 << ADSC);
  //
  // wait for completion
  //
  while (ADCSRA & (1 << ADSC))
     ;
  //
  // save result
  //
  up_lo = ADCL;
  up_hi = ADCH;
  //
  // settle, discharge, and wait 1
  //
  settle_delay();
  clear(charge_port, charge_pin);
  charge_delay_1();
  //
  // initiate conversion
  //
  ADCSRA |= (1 << ADSC);
  //
  // wait for completion
  //
  while (ADCSRA & (1 << ADSC))
     ;
  //
  // save result
  //
  down_lo = ADCL;
  down_hi = ADCH;
  //
  // send result
  //
  put_char(&serial_port, serial_pin_out, up_lo);
  char_delay();
  put_char(&serial_port, serial_pin_out, up_hi);
  char_delay();
  put_char(&serial_port, serial_pin_out, down_lo);
  char_delay();
  put_char(&serial_port, serial_pin_out, down_hi);
  char_delay();
}

int main(void) {
  // set clock divider to /1
  CLKPR = (1 << CLKPCE);
  CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);

  // initialize output pins
  set(serial_port, serial_pin_out);
  output(serial_direction, serial_pin_out);
  clear(charge_port, charge_pin);
  output(charge_direction, charge_pin);

  ADMUX = (0 << REFS1) | (0 << REFS0) // Vcc ref
      | (0 << ADLAR) // right adjust
      | (0 << MUX3) | (1 << MUX2) | (1 << MUX1) | (1 << MUX0); // PB7
	ADCSRA = (1 << ADEN) // enable
	| (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // prescaler /128

	//
	// main loop
	//
	ADMUX = ref | sense1;
  while (1) {
    //put_string(&serial_port, serial_pin_out, "hello.ftdi.44.echo.c: you typed \"");
    //put_char(&serial_port, serial_pin_out, '\"');
    //
    // send framing
    //
    put_char(&serial_port, serial_pin_out, 1);
    char_delay();
    put_char(&serial_port, serial_pin_out, 2);
    char_delay();
    put_char(&serial_port, serial_pin_out, 3);
    char_delay();
    put_char(&serial_port, serial_pin_out, 4);
    char_delay();

    check_pin(sense0);
    check_pin(sense1);
    check_pin(sense2);
    check_pin(sense3);
    check_pin(sense4);
    check_pin(sense5);
    check_pin(sense6);
    check_pin(sense7);
  }

  /*static unsigned char up_lo,up_hi,down_lo,down_hi;
	while (1) {
		//
		// send framing
		//
		put_char(&serial_port, serial_pin_out, 1);
		char_delay();
		put_char(&serial_port, serial_pin_out, 2);
		char_delay();
		put_char(&serial_port, serial_pin_out, 3);
		char_delay();
		put_char(&serial_port, serial_pin_out, 4);
		//
		// settle, charge, and wait 1
		//
		settle_delay();
		set(charge_port, charge_pin);
		charge_delay_1();
		//
		// initiate conversion
		//
		ADCSRA |= (1 << ADSC);
		//
		// wait for completion
		//
		while (ADCSRA & (1 << ADSC))
			 ;
		//
		// save result
		//
		up_lo = ADCL;
		up_hi = ADCH;
		//
		// settle, discharge, and wait 1
		//
		settle_delay();
		clear(charge_port, charge_pin);
		charge_delay_1();
		//
		// initiate conversion
		//
		ADCSRA |= (1 << ADSC);
		//
		// wait for completion
		//
		while (ADCSRA & (1 << ADSC))
			 ;
		//
		// save result
		//
		down_lo = ADCL;
		down_hi = ADCH;
		//
		// send result
		//
		put_char(&serial_port, serial_pin_out, up_lo);
		char_delay();
		put_char(&serial_port, serial_pin_out, up_hi);
		char_delay();
		put_char(&serial_port, serial_pin_out, down_lo);
		char_delay();
		put_char(&serial_port, serial_pin_out, down_hi);
		char_delay();
	}*/
}
