//Credits: Optimus Digital
 
//Pinii digitali 4,7 și 8 sunt utilizați pentru a controla registrele de deplasare.
#define LATCH_DIO 4
#define CLK_DIO 7
#define DATA_DIO 8

//Pinul analog A0 este utilizat pentru a măsura rezistența potențiometrului.
#define Pot1 A0

/*
În vectorul SEGMENT_MAP vom reține fiecare cod specific (în binar) pentru a realiza o anumita cifra pe ecran. 
De exemplu, 0xC0 în zecimal înseamna 11000000, ultimii 7 biți reprezentând starea fiecărui segment în parte.
Dacă un bit este 0, înseamnă că segmentul este aprins și în caz contrar pentru un bit 1. Astfel, din exemplul de
mai sus aflăm că segmentul G este stins, iar restul sunt aprinse, formând astfel cifra 0.
Mai jos veți regăsi modul în care sunt marcate (de la A la G) cele 7 segmente ale unei cifre.

      A
   -------
  |       |
 F|       |B
  |   G   |
  |-------|
  |       |
 E|       |C
  |       |
   -------                 
      D 

De asemenea, fiecare cifră are și un punct. Pentru a aprinde acel punct trebuie sa setati primul bit ca fiind 0.
Exemplu: 0xC0 (in binar 11000000) realizează doar cifra zero pe când 0x40 (01000000)
Lista urmatoare reprezinta codul cifrelor cu punctul activat:
0 -> 0x40
1 -> 0x79
2 -> 0x24
3 -> 0x30
4 -> 0x19
5 -> 0x12
6 -> 0x02
7 -> 0x78
8 -> 0x00
9 -> 0x10

*/
const byte SEGMENT_MAP[] =

{0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0X80,0X90};


//In vectorul SEGMENT_SELECT vom retine 4 valori cu ajutorul căror vom selecta cifra pe care dorim sa o aprindem
// 0xF1 in binar reprezinta 11110001. Ultimul bit 1 reprezintă că vom aprinde prima cifra (de la stânga la dreapta)
// 0xF2 in binar reprezinta 11110010. Al 7-lea bit are valoare 1 si inseamna ca vom aprinde a doua (de la stânga la dreapta)
// 0xF4 -> 11110100
// 0xF8 -> 11111000
const byte SEGMENT_SELECT[] =
{0xF1,0xF2,0xF4,0xF8};



//functia Display are rolul de a afisa pe ecran o cifra, primind ca paremetru un variabile de tip byte
// cu ajutorul carora vom sti ce cifra sa aprindem dar si ce valoare sa afiseze.
void Display(byte Segment, byte Value)
{
digitalWrite(LATCH_DIO,LOW);
shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, SEGMENT_MAP[Value]);
shiftOut(DATA_DIO, CLK_DIO, MSBFIRST, SEGMENT_SELECT[Segment] );
digitalWrite(LATCH_DIO,HIGH);
}


void setup ()
{
//pornim interfata Seriala cu baud rate-ul de 9600.
Serial.begin(9600);

//Trebuie să inițializați pinii digitali utilizați de registrele de deplasare ca fiind de ieșire.
//Initializarea se realizeaza prin metoda pinMode( pin , OUTPUT);
pinMode(LATCH_DIO,OUTPUT);
pinMode(CLK_DIO,OUTPUT);
pinMode(DATA_DIO,OUTPUT);
}

void loop()
{

//in variabila de tip int PotValue vom reține valoarea citită pe pin-ul analog A0
//Valoarea stocata va fi cuprinsă între 0 și 1023. Această valoare este direct
//proportională cu tensiunea de referință(5 V).
int PotValue = analogRead(Pot1);

//in Serial Monitor vom afișa valoarea stocată in variabila PotValue
Serial.print("Potentiometer: ");
Serial.println(PotValue);

//Pentru a functiona corect, în cadrul functiei loop este ideal sa nu utilizam delay-uri
//astfel, ne vom folosi de millis() pentru a actualiza informația afisată pe ecran la un
//interval de 1 secunda
long t=millis();
while(millis()-t<1000)
  {
  //afisam pe ecran valoarea stocata in PotValue.

  //Cu ajutorul operatiei de impartire pe intregi (/) si operatiei mod(%)
  //putem sa spargem un numar de 4 cifre în cifre.
  //De exemplu: prin intermediul operatiei PotValue/1000 vom extrage prima cifra a 
  //numarului stocat in PotValue.
  //Prin intermediul (PotValue/100)%10 vom extrage cea de-a doua cifra a numarului.
  //Prin intermediul (PotValue/10)%10 vom extrage cea de-a treia cifra a numarului.
  //În cele din urmă, PotValue%10 va extrage ultima cifra a numarului.

  Display(0 ,PotValue/1000);
  Display(1 ,(PotValue/100)%10);
  Display(2 ,(PotValue/10)%10);
  Display(3 ,PotValue%10);;
  }
} 
