/*
 * File:   main.c
 * Author: Zhuk
 *
 * Started on October 12, 2016, 8:50 PM
 */

#include <xc.h>
#include "pic16f628a.h"

// CONFIGURATIO WORD
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSC oscillator: CLKOUT function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

#pragma warning disable 752

#define _XTAL_FREQ 4000000

// Массив из символов индикатора 0...9, P, E, -, r
const unsigned char led[14] = {0b11000000, 0b11111001, 0b10100100, 0b10110000, 
                               0b10011001, 0b10010010, 0b10000010, 0b11111000, 
                               0b10000000, 0b10010000, 0b10001100, 0b10000110,
                               0b10111111, 0b10101111};
unsigned char i = 0;
unsigned char period; // Периодичность опроса АКПП.
bit at_read;  // Флаг чтения АКПП.

// Используемые функции.
void init(void);
void interrupt isr(void);

void main(void)
{
  init(); // Вызов подпрограммы настройки МК.
  GIE = 1;  // Разрешаем прерывания.
  at_read = 1; // Поднимаем флаг чтения АКПП.
  while (1) // Начало цикла.
  {
    if (at_read == 1) // Можно читать АКПП?
    {
      at_read = 0; // Очистка флага чтения АКПП
      switch (PORTA & 0x0F) // Проверка состояния пинов А3...А0
      {
        case 0b00001110: i = 1; break;  // 1
        case 0b00001101: i = 2; break;  // 2
        case 0b00001011: i = 3; break;  // 3
        case 0b00001001: i = 4; break;  // 4
        case 0b00001111: i = 13; break; // r
      }
// Таймер тикает каждые 256 мкс, до переполнения 65536 мкс.
// 65536*period(мкс)
      period = 12;
    }
// Вывод символа в порт В в зависимости от типа индикатора.
    if (RA4 == 1) PORTB = led[i];  // ОА
      else PORTB = ~led[i]; // ОК
  }
}

void interrupt isr()
{
  if ((T0IF) && (T0IE)) // Сработал Т0?
  {
    T0IF = 0; // Очистка флага.
    if (period > 0) period--; // Если счетчик не нудевой, то уменьшить его.
      else at_read = 1; // В случае нуля поднять флаг чтения АКПП.
  }
}

void init ()
{
  OPTION_REG = 0b10000111;    // Prescaler 1:256
  TMR0 = 0;
  INTCON = 0b00100000;    // GIE(7), T0IE(5)
  PORTA = 0;
  TRISA = 0b11111111; // Порт А целиком на вход.
  PORTB = 0;
  TRISB = 0b00000000; // Порт В целиком на выход.
  CMCON = 7;        // Отключение компаратора.
}
