Tuesday, April 14, 2020

Seven Segment Display in mikroPascal

{**************************************************************
 * Project ..........: 3 Digit Seven Segment Display Example.
 * File name ........: SSD_Counter.mpas
 * File version .....: v1.0
 * Date .............: 17/12/2019
 * Author ...........: Indrit Bekteshi
 * Build SW .........: mikroPascal PRO for AVR v6.1.1
 * Description ......: Seven Segment Display Counter 0 to 999
 * Configuration ....: -
 *        MCU .......: Atmega8
 *        Oscillator : Int. 8.0000 MHz
 *        Datashet ..: https://tinyurl.com/yccl8mzu
**************************************************************}
Program SSD_Counter;
 
Var SSD_1_Dir        : sBit At DDRC.5;  Sfr;
Var SSD_2_Dir        : sBit At DDRC.4;  Sfr;
Var SSD_3_Dir        : sBit At DDRC.3;  Sfr;
 
Var SSD_1            : sBit At PORTC.5; Sfr;
Var SSD_2            : sBit At PORTC.4; Sfr;
Var SSD_3            : sBit At PORTC.3; Sfr;
 
Var SSD_Segments_Dir : Byte At DDRD;    Sfr;
Var SSD_Segments     : Byte At PORTD;   Sfr;
 
Const INIT_TIMER0    : Byte = (256 - 156);
 
(* Common Anode Segments *)
Const SEGMENT_DP     : Byte = $7F;
Const SSD_NUM_MASK   : Array[0..9] Of Byte = (
        $C0{ Number 0 }
        $F9{ Number 1 }
        $A4{ Number 2 }
        $B0{ Number 3 }
        $99{ Number 4 }
        $92{ Number 5 }
        $82{ Number 6 }
        $F8{ Number 7 }
        $80{ Number 8 }
        $90); { Number 9 }
         
Type TSSD_Numeric = Record
       Digit      : Byte;
       Dp         : Boolean;
     End;
 
Type TCounter     = Record
       SSD        : TSSD_Numeric;
       Counter    : Word;
       Timer_1    : Byte;
       Timer_2    : Byte;
     End;
      
Var Cnt           : TCounter;
 
Procedure SSD_Init();
Begin
(* PORT Configuration *)
  SSD_Segments_Dir := %11111111;
  SSD_Segments := %00000000;
  SSD_1_Dir := 1;
  SSD_2_Dir := 1;
  SSD_3_Dir := 1;
  SSD_1 := 0;
  SSD_2 := 0;
  SSD_3 := 0;
   
(* Switch on all segments for 1 sec. *)
  Delay_Ms(1000);
   
(* Switch off segments for 200 ms. *)
  //SSD_Segments := %11111111;
  SSD_1 := 1;
  SSD_2 := 1;
  SSD_3 := 1;
  Delay_Ms(200);
   
(* Variants / Declarations initialization *)
  Cnt.SSD.Digit := 0;
  Cnt.SSD.Dp := True;
  Cnt.Timer_1 := 0;
  Cnt.Timer_2 := 0;
  Cnt.Counter := 0;
   
(* Timer0 5ms Configuration *)
  TCCR0 := %00000100;
  TCNT0 := INIT_TIMER0;
   
(* Start Interrupts *)
  ASM SEI END;
   
(* Start the Timer0 *)
  SetBit(TIMSK, TOIE0);
End;
 
{**************************************************************
 * 3 Digit 7 Segment Display Multiplexing
 * Procedure Display numbers from 0 to 999
 **************************************************************}
Procedure SSD_Display_Number(Number : Word);
Const Fike = 1;  Ndeze = 0;
Const D1 = 0; D2 = 1; D3 = 2;
Begin
  //If (Number > 999) Then Number := 999;
  Case Cnt.SSD.Digit Of
    D1 : Begin (* Paraqit numrat tre shifrorë *)
           SSD_3         := Fike;
           SSD_Segments  := SSD_NUM_MASK[(Number Div 100) Mod 10];
           SSD_1         := Ndeze;
           Cnt.SSD.Digit := D2;
         End;
    D2 : Begin (* Paraqit numrat dy shifrorë *)
           SSD_1         := Fike;
           SSD_Segments  := SSD_NUM_MASK[(Number Div 10) Mod 10];
           SSD_2         := Ndeze;
           Cnt.SSD.Digit := D3;
         End;
    D3 : Begin (* Paraqit numrat një shifrorë *)
           SSD_2         := Fike;
           SSD_Segments  := SSD_NUM_MASK[Number Mod 10 ];
           If (Cnt.SSD.Dp) Then
             SSD_Segments:= SSD_Segments And SEGMENT_DP;
           SSD_3         := Ndeze;
           Cnt.SSD.Digit := D1;
         End;
  End;
End;
 
(* Timer0 Interrupt Rutine *)
Procedure T0_OVF_ISR(); iv IVT_ADDR_TIMER0_OVF;
Begin
  SSD_Display_Number(Cnt.Counter);
  Inc(Cnt.Timer_1);
  TCNT0 := INIT_TIMER0;
End;
 
(* Main Program Rutine *)
Begin
  SSD_Init();
   
  Repeat
    If (Cnt.Timer_1 >= 100) Then
    Begin
      Cnt.Timer_1 := 0;
      Inc(Cnt.Timer_2);
      If (Cnt.Timer_2 >= 2) Then
      Begin
        Inc(Cnt.Counter);
        Cnt.Timer_2 := 0;
      End;
      Cnt.SSD.Dp := Not Cnt.SSD.Dp;
    End;
    If (Cnt.Counter > 999) Then
      Cnt.Counter := 0;
  Until (0);
   
End.