//***************************************************************************
//
//  Author(s)...: Pashgan    http://ChipEnable.Ru   
//
//  Target(s)...: AVR
//
//  Compiler....: любой
//
//  Description.: драйвер семисегментного 4-ех разрядного индикатора 
//
//  Data........: 15.04.10 
//
//***************************************************************************
#include "indicator.h"

#define AMOUNT_NUM 4

//эту часть можно настроить под другой индикатор
#define LightOutAll()  PORT_TR &= ~((1<<NUM1)|(1<<NUM2)|(1<<NUM3)|(1<<NUM4))
#define BurnDigit(port, digit) port |= (1<<digit)  
#define ValueBuf() buf[count]

//программный буфер
volatile unsigned char buf[AMOUNT_NUM];

unsigned char number[] = 
{
  (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(0<<SEG_G), //0
  (0<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(0<<SEG_D)|(0<<SEG_E)|(0<<SEG_F)|(0<<SEG_G), //1
  (1<<SEG_A)|(1<<SEG_B)|(0<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(0<<SEG_F)|(1<<SEG_G), //2
  (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(0<<SEG_E)|(0<<SEG_F)|(1<<SEG_G), //3   
  (0<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(0<<SEG_D)|(0<<SEG_E)|(1<<SEG_F)|(1<<SEG_G), //4
  (1<<SEG_A)|(0<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(0<<SEG_E)|(1<<SEG_F)|(1<<SEG_G), //5 
  (1<<SEG_A)|(0<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G), //6
  (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(0<<SEG_D)|(0<<SEG_E)|(0<<SEG_F)|(0<<SEG_G), //7   
  (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(1<<SEG_E)|(1<<SEG_F)|(1<<SEG_G), //8
  (1<<SEG_A)|(1<<SEG_B)|(1<<SEG_C)|(1<<SEG_D)|(0<<SEG_E)|(1<<SEG_F)|(1<<SEG_G)  //9    
};

//******************************************************************************
void IND_Init(void)
{
  PORT_IND = 0xff;
  DDR_IND = 0xff;
  
  PORT_TR |= (1<<NUM1)|(1<<NUM2)|(1<<NUM3)|(1<<NUM4);
  DDR_TR |= (1<<NUM1)|(1<<NUM2)|(1<<NUM3)|(1<<NUM4);

  for(unsigned char i = 0; i < AMOUNT_NUM; i++) buf[i] = 0;
}

//******************************************************************************
void IND_Output(unsigned int value, unsigned char comma)
{
  unsigned char tmp;
  for(unsigned char i = 0; i < AMOUNT_NUM; i++){
    tmp = value % 10;
    buf[i] = number[tmp];
    value = value/10;
  }

  if (comma < AMOUNT_NUM) {
    buf[comma] |= 1<<(SEG_DP);
  }
    
}

//*****************************************************************************
void IND_Update(void)
{
  static unsigned char count = 0;
  
  //гасим все разряды
  PORT_IND = 0;
  LightOutAll();
  
  //зажигаем нужный разряд 
  if (count == 0) BurnDigit(PORT_TR, NUM1);
  else if (count == 1) BurnDigit(PORT_TR, NUM2);
  else if (count == 2) BurnDigit(PORT_TR, NUM3);
  else BurnDigit(PORT_TR, NUM4);
  
  //выводим в порт код цифры
  PORT_IND = ValueBuf();
  
  count++;
  if (count == AMOUNT_NUM) count = 0;
}