/* Многоканальный измеритель
 * - усреднение по 256 выборкам
 * - выборки каналов "пачками" по 256
 * 
 * Author unknown
 * Modified by Kavka (http://radiokot.ru)
 */

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdint.h>


void wr_reg(uint8_t cData)
{
	uint8_t i;
	uint8_t temp;
	temp = cData;
    for(i=0; i<8; i++)
    {
        if (temp & 0x80) {
			PORTB |= _BV(1);
		} else {
			PORTB &= ~_BV(1);
		}
        asm("nop");
		PORTB |= _BV(0);
        asm("nop");        
		PORTB &= ~_BV(0);
        temp = temp << 1;
    }
}

void latch_reg()
{
    asm("nop");
	PORTB |= _BV(2);
    asm("nop");         
	PORTB &= ~_BV(2);
}

uint8_t const PROGMEM cSeg[]={
	0b00111111, // 0
	0b00000110, // 1
	0b01011011, // 2
	0b01001111, // 3
	0b01100110, // 4
	0b01101101, // 5
	0b01111101, // 6
	0b00000111, // 7
	0b01111111, // 8
	0b01101111  // 9
};

uint8_t cDec = 0;
uint8_t cDigitValue[8];

uint8_t PROGMEM const cDigitBus[8] = {
	0b00000001,0b00000010,0b00000100,0b00001000,
	0b00010000,0b00100000,0b01000000,0b10000000
};

SIGNAL (TIM0_COMPA_vect)
{
    wr_reg(pgm_read_byte_near(&cDigitBus[cDec]));
    wr_reg(cDigitValue[cDec]);
    //wr_reg(~cSeg[cDec]);
    latch_reg();
    cDec += 1;

	cDec &= 7;
//    if( cDec > 7 )
//        cDec = 0; 
        
    TCNT0 = 0;
}

#define FIRST_ADC_INPUT 2
#define SECOND_ADC_INPUT 3
#define ADC_VREF_TYPE 0x00

 typedef struct ADC_ch_struct {
	uint8_t mux;
/*	uint8_t count; */
	uint32_t sum;
	uint8_t digit_offset;
} ADC_ch_type;

ADC_ch_type ADC_data[2] = {{(FIRST_ADC_INPUT  | (ADC_VREF_TYPE & 0xff)), 0, 0},
	                       {(SECOND_ADC_INPUT | (ADC_VREF_TYPE & 0xff)), 0, 4}};

uint8_t count;
uint8_t input_index = 0;

// ADC interrupt service routine
// with auto input scanning
SIGNAL (ADC_vect)
{
	uint8_t i;
	uint16_t tmp_sum;

//	ADC_data[input_index].sum += 5000UL*ADCW/1024;
	ADC_data[input_index].sum += (1250UL*ADCW)>>8;
	count++;

	if ( count == 0 ) {

		tmp_sum = ADC_data[input_index].sum>>8;
		i = 4;
		while (i > 0) {
			i--;
			cDigitValue[ADC_data[input_index].digit_offset+i] = ~pgm_read_byte_near(&cSeg[tmp_sum % 10]);
			tmp_sum /= 10;
		}

		ADC_data[input_index].sum = 0;

		input_index = (input_index+1) % (sizeof(ADC_data)/sizeof(ADC_ch_type));
		ADMUX = ADC_data[input_index].mux;

	}

	// Start the AD conversion
	ADCSRA|=0x40;

}


void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
CLKPR=0x80;
CLKPR=0x00;

// Input/Output Ports initialization
// Port B initialization
// Func5=In Func4=In Func3=In Func2=In Func1=In Func0=Out 
// State5=T State4=T State3=T State2=T State1=T State0=0 
PORTB=0x00;
DDRB=0x07;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 9400,000 kHz
// Mode: Normal top=0xFF
// OC0A output: Clear on compare match
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x05;
TCNT0=0x00;
OCR0A=0x20;
OCR0B=0x00;

// External Interrupt(s) initialization
// INT0: Off
// Interrupt on any change on pins PCINT0-5: Off
GIMSK=0x00;
MCUCR=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x04;

// Analog Comparator initialization
// Analog Comparator: Off
ACSR=0x80;
ADCSRB=0x00;
DIDR0=0x00;

// ADC initialization
// ADC Clock frequency: 73,438 kHz
// ADC Bandgap Voltage Reference: Off
// ADC Auto Trigger Source: ADC Stopped
// Digital input buffers on ADC0: Off, ADC1: Off, ADC2: On, ADC3: On
DIDR0&=0x03;
DIDR0|=0x24;
ADMUX=FIRST_ADC_INPUT | (ADC_VREF_TYPE & 0xff);
ADCSRA=0xCF;

sei();

   while(1)
   {
   }
}
