
#include "stm8s.h"
#include "mit_lib.h"
// pro přehlednost tabulka zapojení 7segment displej se společnou anodou
// Anody (číslice):
// A1 - D6 
// A2 - D5
// A3 - D4
// A4 - A3
// Katody (segmenty):
// A - C5
// B - B5
// C - C6
// D - C7
// E - C3
// F - B4
// G - C4
// Program pro řízení 4 místného 7 segmentového displeje se společnou anodou
// tuhle část modifikujte podle aktuálního zapojení segmentů a anod
#define A1_GPIO GPIOD
#define A1_PIN GPIO_PIN_6
#define A2_GPIO GPIOD
#define A2_PIN GPIO_PIN_5
#define A3_GPIO GPIOD
#define A3_PIN GPIO_PIN_4
#define A4_GPIO GPIOA
#define A4_PIN GPIO_PIN_3

#define SEGA_GPIO GPIOC
#define SEGA_PIN GPIO_PIN_5
#define SEGB_GPIO GPIOB
#define SEGB_PIN GPIO_PIN_5
#define SEGC_GPIO GPIOC
#define SEGC_PIN GPIO_PIN_6
#define SEGD_GPIO GPIOC
#define SEGD_PIN GPIO_PIN_7
#define SEGE_GPIO GPIOC
#define SEGE_PIN GPIO_PIN_3
#define SEGF_GPIO GPIOB
#define SEGF_PIN GPIO_PIN_4
#define SEGG_GPIO GPIOC
#define SEGG_PIN GPIO_PIN_4

#define PERIODA 39 // perioda přepínání cifer t=1024*PERIODA/16000000
// konec části která se má upravovat

// funkce pro aktivování a dektivování anod (číslic) a katod (segmentů) - do nich nehrabat
#define A1_ON  (GPIO_WriteLow(A1_GPIO,A1_PIN))
#define A1_OFF  (GPIO_WriteHigh(A1_GPIO,A1_PIN))
#define A2_ON  (GPIO_WriteLow(A2_GPIO,A2_PIN))
#define A2_OFF  (GPIO_WriteHigh(A2_GPIO,A2_PIN))
#define A3_ON  (GPIO_WriteLow(A3_GPIO,A3_PIN))
#define A3_OFF  (GPIO_WriteHigh(A3_GPIO,A3_PIN))
#define A4_ON  (GPIO_WriteLow(A4_GPIO,A4_PIN))
#define A4_OFF  (GPIO_WriteHigh(A4_GPIO,A4_PIN))
#define SEGA_ON    (GPIO_WriteLow(SEGA_GPIO,SEGA_PIN))
#define SEGA_OFF    (GPIO_WriteHigh(SEGA_GPIO,SEGA_PIN))
#define SEGB_ON    (GPIO_WriteLow(SEGB_GPIO,SEGB_PIN))
#define SEGB_OFF    (GPIO_WriteHigh(SEGB_GPIO,SEGB_PIN))
#define SEGC_ON    (GPIO_WriteLow(SEGC_GPIO,SEGC_PIN))
#define SEGC_OFF    (GPIO_WriteHigh(SEGC_GPIO,SEGC_PIN))
#define SEGD_ON    (GPIO_WriteLow(SEGD_GPIO,SEGD_PIN))
#define SEGD_OFF    (GPIO_WriteHigh(SEGD_GPIO,SEGD_PIN))
#define SEGE_ON    (GPIO_WriteLow(SEGE_GPIO,SEGE_PIN))
#define SEGE_OFF    (GPIO_WriteHigh(SEGE_GPIO,SEGE_PIN))
#define SEGF_ON    (GPIO_WriteLow(SEGF_GPIO,SEGF_PIN))
#define SEGF_OFF    (GPIO_WriteHigh(SEGF_GPIO,SEGF_PIN))
#define SEGG_ON    (GPIO_WriteLow(SEGG_GPIO,SEGG_PIN))
#define SEGG_OFF    (GPIO_WriteHigh(SEGG_GPIO,SEGG_PIN))

// znaková sada (může obsahovat i další znaky krom číslic. např. symboly jako "-" atd.))
// bitový formát abcdefg (a-g jsou segmenty)
const uint8_t charset[10]={
0b1111110, // 0 (svítí všechny segmenty krom g)
0b0110000, // 1 (svítí jen segmenty b,c)
0b1101101, // 2
0b1111001, // 3
0b0110011, // 4
0b1011011, // 5
0b1011111, // 6
0b1110000, // 7
0b1111111, // 8
0b1111011, // 9
};

// deklarace použitých funkcí
void init_7seg(void);
void zobraz(uint8_t digit, uint8_t znak);

// deklarace proměnných
volatile uint8_t cisla[4]={0,1,2,3}; // pole se zobrazovanými čísly/znaky

main(){
 clock_16MHz(); // taktujeme čip na 16MHz (z naší knihovny mit_lib.h)
 init_7seg(); // nastavíme I/O jako výstupy
 // -------- začátek kouzelné formule --------
 TIM2_TimeBaseInit(TIM2_PRESCALER_1024,PERIODA); // nastavím periodu (čas) časovače
 TIM2_ITConfig(TIM2_IT_UPDATE,ENABLE); // povolíme přerušení od přetečení (tedy až vyprší čas)
 enableInterrupts(); // povolíme přerušení globálně
 TIM2_Cmd(ENABLE); // spustíme časovač
 // -------- konec kouzelné formule --------
 
 while (1){
  // tady může náš program dělat nějakou další užitečnou činnost
 }
}

// rutina přerušení - kouzelná funkce, která se zavolá každých 2.5ms (nebo s jinou periodou pokud ji změníte)
INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13){
 static uint8_t pozice=0; // tady si budeme pamatovat kterou cifru zrovna zobrazujeme
 
// -------- začátek kouzelné formule --------
 TIM2_ClearFlag(TIM2_FLAG_UPDATE); // vyčistím vlajku časovače 
// -------- konec kouzelné formule --------

 if(pozice<3){pozice++;}else{pozice=0;} // procházím všechny cifry/digity/číslice
 zobraz(pozice,cisla[pozice]); // zobrazím příslušnou číslici
 }
 

// funkce zobrazí vybraný znak ze znakové sady na vybrané pozici
// "znak" - hodnota 0 až 9 (případně více pokud máte znakovou sadu rozšířenou o další znaky)
// "digit" - aktivuje vybranou číslici (digit), čísluje se od nuly (0-3)
void zobraz(uint8_t digit, uint8_t znak){
if(znak>sizeof(charset)){return;} // zkontroluje jestli "znak" není mimo rozsah znakové sady, pokud ano, ukončí funkci
 // deaktivujeme všechny číslice/digity/pozice/anody 
 A1_OFF; 
 A2_OFF;
 A3_OFF;
 A4_OFF;
 // aktivujeme vybrané segmenty (dle znakové sady)
 if(charset[znak] & 0b1<<0){SEGG_ON;}else{SEGG_OFF;} 
 if(charset[znak] & 0b1<<1){SEGF_ON;}else{SEGF_OFF;}
 if(charset[znak] & 0b1<<2){SEGE_ON;}else{SEGE_OFF;}
 if(charset[znak] & 0b1<<3){SEGD_ON;}else{SEGD_OFF;}
 if(charset[znak] & 0b1<<4){SEGC_ON;}else{SEGC_OFF;}
 if(charset[znak] & 0b1<<5){SEGB_ON;}else{SEGB_OFF;}
 if(charset[znak] & 0b1<<6){SEGA_ON;}else{SEGA_OFF;}
 // aktigujeme vybranou číslici/digit/pozici/anodu
 if(digit==0){A1_ON;}
 else if(digit==1){A2_ON;}
 else if(digit==2){A3_ON;}
 else if(digit==3){A4_ON;}
} 

// nastavíme všechny piny segmentového displeje jako výstupy
// a dáme je do log.1 (tím se všechny segmenty zhasnou a anody/digity/číslice deaktivují)
void init_7seg(void){
GPIO_Init(A1_GPIO,A1_PIN,GPIO_MODE_OUT_PP_HIGH_SLOW);
GPIO_Init(A2_GPIO,A2_PIN,GPIO_MODE_OUT_PP_HIGH_SLOW);
GPIO_Init(A3_GPIO,A3_PIN,GPIO_MODE_OUT_PP_HIGH_SLOW);
GPIO_Init(A4_GPIO,A4_PIN,GPIO_MODE_OUT_PP_HIGH_SLOW);

GPIO_Init(SEGA_GPIO,SEGA_PIN,GPIO_MODE_OUT_PP_HIGH_SLOW);
GPIO_Init(SEGB_GPIO,SEGB_PIN,GPIO_MODE_OUT_PP_HIGH_SLOW);
GPIO_Init(SEGC_GPIO,SEGC_PIN,GPIO_MODE_OUT_PP_HIGH_SLOW);
GPIO_Init(SEGD_GPIO,SEGD_PIN,GPIO_MODE_OUT_PP_HIGH_SLOW);
GPIO_Init(SEGE_GPIO,SEGE_PIN,GPIO_MODE_OUT_PP_HIGH_SLOW);
GPIO_Init(SEGF_GPIO,SEGF_PIN,GPIO_MODE_OUT_PP_HIGH_SLOW);
GPIO_Init(SEGG_GPIO,SEGG_PIN,GPIO_MODE_OUT_PP_HIGH_SLOW);
}


