/*****************************************************
This program was produced by the
CodeWizardAVR V1.24.8d Professional
Automatic Program Generator
© Copyright 1998-2006 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : 
Version : 
Date    : 13.11.2006
Author  : F4CG                            
Company : F4CG                            
Comments: 


Chip type           : ATtiny2313
Clock frequency     : 8,000000 MHz
Memory model        : Tiny
External SRAM size  : 0
Data Stack size     : 32
*****************************************************/

#include <tiny2313.h>

// 1 Wire Bus functions
#asm
   .equ __w1_port=0x12 ;PORTD
   .equ __w1_bit=6
#endasm
#include <1wire.h>
#include <delay.h>



#define    TRUE    (!FALSE)
#define    FALSE   0
#define    BYTE    unsigned char
#define    WORD    unsigned short int
#define    BOOLEAN char
                       
#define LED_delay 150    

//#define Cathode
#define Anode
     
BYTE byDisplay[4];        // буфер данных, для вывода на экран

BYTE T;
BYTE Fr;
BYTE Ff;
BOOLEAN Updating;


BYTE byCharacter[12] = {0xFA,     //0
                0x82,   //1
 	              0xB9,   //2
	              0xAB,	  //3 
	              0xC3,   //4 
	              0x6B,   //5 
	              0x7B,   //6
                0xA2,   //7 
                0xFB,   //8
                0xEB,   //9 
                0x00,   //blank   
                0x01    //-
                }; 



/************************************************************************\
  Преобразование скорости мотора и количества лопастей
  в данные экранного буфера
      Вход:  wRpm - обороты ротора, byBladeCnt - количество лопастей
      Выход: -
\************************************************************************/
void PrepareRpmData()
{
    BYTE i;
    BYTE R;                    
    BYTE T1;    
    BOOLEAN Minus;   
    R = T; 
    T1 = T;
    Fr = Ff; 
           
    Minus = FALSE;           
    if (R & 0b10000000) 
    { 
      Fr = ~Fr;   
      Minus = TRUE;
      R = ~R;            
      R = R & 0b01111111;
      T1 = R;
      if (!Fr)
      {
        R++;
        T1++;
      }   
               
    }   
        
    Fr = Fr & 0b00001111;
    byDisplay[3] = (Fr * 10 / 16) % 10;

    for(i=0; i<3; i++)
      {
         byDisplay[2-i] = T1 % 10;
         T1 /= 10;
      }    
    
    if (R < 10)
    {
      byDisplay[0] = 10;
      byDisplay[1] = 10;

      goto exit;
    }   
    if ((R >= 10) & (R <100))
    {
      byDisplay[0] = 10;
      goto exit;
    }
                    
exit:  
  if (Minus)
   {
     byDisplay[0] = 11;  
   }
    
}

/************************************************************************\
  Вывод экранного буфера на дисплей.
      Вход:  -
      Выход: -
\************************************************************************/
void ShowDisplayData(void)
{                      
 
#ifdef Cathode
  PORTB = byCharacter[byDisplay[0]];
  PORTD.5 = 0;
  delay_us(LED_delay);
  PORTD.5 = 1;    
     
  PORTB = byCharacter[byDisplay[1]];
  PORTD.1 = 0;
  delay_us(LED_delay);
  PORTD.1 = 1;
      
  PORTB = byCharacter[byDisplay[2]] | 0b00000100;
  PORTD.0 = 0;
  delay_us(LED_delay);
  PORTD.0 = 1;
      
  PORTB = byCharacter[byDisplay[3]];
  PORTD.4 = 0;
  delay_us(LED_delay);
  PORTD.4 = 1;
#endif

#ifdef Anode
  PORTB = ~byCharacter[byDisplay[0]];
  PORTD.5 = 1;
  delay_us(LED_delay);
  PORTD.5 = 0;    
     
  PORTB = ~byCharacter[byDisplay[1]];
  PORTD.1 = 1;
  delay_us(LED_delay);
  PORTD.1 = 0;
      
  PORTB = ~byCharacter[byDisplay[2]] & 0b11111011;
  PORTD.0 = 1;
  delay_us(LED_delay);
  PORTD.0 = 0;
      
  PORTB = ~byCharacter[byDisplay[3]];
  PORTD.4 = 1;
  delay_us(LED_delay);
  PORTD.4 = 0;
#endif
 
  
  }


/************************************************************************\
  Обновление дисплея.
      Вход:  -
      Выход: -
\************************************************************************/
void RefreshDisplay(void)
{                                
    //Updating = TRUE;  
    PrepareRpmData();      
    ShowDisplayData();
    //Updating = FALSE;
}

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{                
// Reinitialize Timer 0 value
TCNT0=0x0F;
// Place your code here
}

// Timer 1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
  BYTE t1;
  BYTE t2;
  BYTE i;
// Reinitialize Timer 1 value
TCNT1H=0x8F;
TCNT1L=0xD1;
// Place your code here 
w1_init();   
for (i=0; i<11; i++)
  {
    RefreshDisplay();
  }
w1_write(0xCC);               
for (i=0; i<11; i++)
  {
    RefreshDisplay();
  }
Updating = !Updating;
if (Updating)
{
  w1_write(0xBE);  
  for (i=0; i<11; i++)
  {
    RefreshDisplay();
  }
  t1=w1_read();   //LSB
  for (i=0; i<11; i++)
  {
    RefreshDisplay();
  }
  t2=w1_read();   //MSB
  Ff = (t1 & 0x0F);
  t2 = t2 << 4; 
  t1 = t1 >> 4;
  T = (t2 & 0xF0) | (t1 & 0x0F);
}
else
{
  w1_write(0x44);  
}  
}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

        //Разряд DDRx - определяет направление передачи данных (0 - вход, 1 - выход).
        //Разряд PORTx - если вывод определен выходом (DDRx = 1), то:
        //         если установлена 1 - то на выводе устанавливается лог. 1
        //         если установлена 0 - то на выводе устанавливается лог. 0
        //    если вывод определен входом (DDRx = 0), то PORTx - определяет состояние подтягивающего резистора (при PORTx = 1 резистор подключен)
        //Разряд PINx - доступен только для чтения и содержит физическое значение вывода порта
        
        PORTA=0b00000011;
        DDRA= 0b00000011;
        
        PORTB=0b00000000;
        DDRB= 0b11111111;
        
        #ifdef CathodeOld  
          PORTD=0b01111111;
          DDRD= 0b00101011;
        #endif  
          
        #ifdef Cathode  
          PORTD=0b01111111;
          DDRD= 0b00110011;
        #endif
        
        #ifdef Anode  
          PORTD=0b01001100;
          DDRD= 0b00110011;
        #endif



// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 8000,000 kHz
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x02;
TCNT0=0x0F;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x04;
TCNT1H=0x03;
TCNT1L=0xD1;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
GIMSK=0x00;
MCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x82;

// Universal Serial Interface initialization
// Mode: Disabled
// Clock source: Register & Counter=no clk.
// USI Counter Overflow Interrupt: Off
USICR=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;

// 1 Wire Bus initialization
w1_init();
w1_write(0xCC);
w1_write(0x44);

// Global enable interrupts
#asm("sei")

while (1)
      {
      // Place your code here
      #asm("cli");
      // Place your code here
      RefreshDisplay();
      #asm("sei");
      };
}
