Skip to content

Instantly share code, notes, and snippets.

@Nemweb
Last active September 3, 2018 23:04
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nemweb/27eda928de2323e0ec19c828e803a52b to your computer and use it in GitHub Desktop.
Save Nemweb/27eda928de2323e0ec19c828e803a52b to your computer and use it in GitHub Desktop.
// PIC16F628A Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSC oscillator: I/O 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 = ON // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = ON // Brown-out Detect Enable bit (BOD enabled)
#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)
#include <xc.h>
#define _XTAL_FREQ 4000000
#define SEL PORTAbits.RA3
#define MOVE PORTAbits.RA4
//declara as variáveis necessariamente globais
unsigned char verde[3][3], vermelho[3][3], cursor[3][3], linha, conta, cor;
bit pisca;
//rotina da interrupção
void interrupt ISR()
{
//confere se a interrupção é devido a overflow no Timer0
if(T0IF)
{
//zera o PORTB pra evitar "sombras" nos LEDs
PORTB = 0;
//ativa o pino do PORTA correspondente a cada linha
if(linha == 0)
PORTA = 1;
else if(linha == 1)
PORTA = 2;
else if(linha == 2)
PORTA = 4;
//Lógica para acender cada LED
PORTBbits.RB0 = vermelho[linha][0] | (cursor[linha][0] & pisca & cor);
PORTBbits.RB1 = vermelho[linha][1] | (cursor[linha][1] & pisca & cor);
PORTBbits.RB2 = vermelho[linha][2] | (cursor[linha][2] & pisca & cor);
PORTBbits.RB3 = verde[linha][0] | (cursor[linha][0] & pisca & !cor);
PORTBbits.RB4 = verde[linha][1] | (cursor[linha][1] & pisca & !cor);
PORTBbits.RB5 = verde[linha][2] | (cursor[linha][2] & pisca & !cor);
//incrementa a variável linha para que na próxima interrupção a
//próxima linha seja ativada
linha++;
if(linha == 3)
linha = 0;
//incrementa a variável conta para contar o tempo e fazer o
//cursor piscar.
conta++;
if(conta == 100)
{
conta = 0;
pisca = !pisca;
}
//reseta os parâmetros do Timer0 para a interrupção ocorrer novamente
T0IF = 0;
TMR0 = 131;
}
}
//rotina para verificar se houve uma combinação válida em alguma matriz
unsigned char testa_ganhou(unsigned char teste[3][3])
{
//verifica se existe alguma coluna completa
if(teste[0][0] && teste[1][0] && teste[2][0])
return 1;
if(teste[0][1] && teste[1][1] && teste[2][1])
return 1;
if(teste[0][2] && teste[1][2] && teste[2][2])
return 1;
//verifica se existe alguma linha completa
if(teste[0][0] && teste[0][1] && teste[0][2])
return 1;
if(teste[1][0] && teste[1][1] && teste[1][2])
return 1;
if(teste[2][0] && teste[2][1] && teste[2][2])
return 1;
//verifica as duas diagonais
if(teste[0][0] && teste[1][1] && teste[2][2])
return 1;
if(teste[0][2] && teste[1][1] && teste[2][0])
return 1;
//retorna zero se não há combinação válida
return 0;
}
//rotina para verificar se "deu velha"
//(todas as posições marcadas e ninguém ganhou)
unsigned char testa_velha(unsigned char teste1[3][3], unsigned char teste2[3][3])
{
unsigned char i, j, soma;
soma = 0;
//soma o valor de todas as posições das duas matrizes
//se todas as 9 posições estiverem completas, o valor dá nove,
//indicando que deu velha
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
soma += teste1[i][j] + teste2[i][j];
}
if(soma == 9)
return 1;
else
return 0;
}
//zera todas as posições na matriz
void limpa_matriz(unsigned char matriz[3][3])
{
unsigned char i, j;
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
matriz[i][j] = 0;
}
}
void main(void)
{
//cria as variáveis locais
unsigned char i, j, posicao, MOVE_Old, SEL_Old, pontuacao_vermelho, pontuacao_verde;
//inicializa as matrizes e variáveis
limpa_matriz(verde);
limpa_matriz(vermelho);
limpa_matriz(cursor);
pisca = 1;
linha = 0;
posicao = 0;
MOVE_Old = 1;
SEL_Old = 1;
cursor[0][0] = 1;
cor = 0;
pontuacao_vermelho = 0;
pontuacao_verde = 0;
//configura o PIC
CMCON = 0xFF;
VRCON = 0;
TRISA = 0x18;
TRISB = 0x00;
PORTA = 1;
PORTB = 0;
OPTION_REG = 0xC2;
TMR0 = 131;
INTCON = 0xA0;
T0IF = 0;
while(1)
{
//testa se o botão que move o cursor está pressionado agora
//mas não estava antes. Isso impede que ele se mova várias vezes em uma
//unica pressionada. Se for verdade, muda a posição
//e limpa a posição anterior.
if(MOVE == 0 && MOVE_Old == 1)
{
cursor[posicao/3][posicao%3] = 0;
posicao++;
if(posicao == 9)
posicao = 0;
cursor[posicao/3][posicao%3] = 1;
MOVE_Old = 0;
}
//verifica se o jogador soltou o botão
if(MOVE == 1 && MOVE_Old == 0)
MOVE_Old = 1;
//Marca na matriz correspondente a posição da jogada
//caso o jogador tenha pressionado o botão de jogada
if(SEL == 0 && SEL_Old == 1)
{
if(cor == 0 && vermelho[posicao/3][posicao%3] == 0 && verde[posicao/3][posicao%3] == 0)
{
verde[posicao/3][posicao%3] = 1;
cor = 1;
}
else if(cor == 1 && verde[posicao/3][posicao%3] == 0 && vermelho[posicao/3][posicao%3] == 0 )
{
vermelho[posicao/3][posicao%3] = 1;
cor = 0;
}
cursor[posicao/3][posicao%3] = 0;
posicao++;
if(posicao == 9)
posicao = 0;
cursor[posicao/3][posicao%3] = 1;
SEL_Old = 0;
}
//verifica se o jogador soltou o botão
if(SEL == 1 && SEL_Old == 0)
SEL_Old = 1;
//confere se o jogador da cor verde ganhou
//se sim, mostra a pontuação com efeito,
//reseta as matrizes e as variáveis de controle
if(testa_ganhou(verde))
{
limpa_matriz(vermelho);
limpa_matriz(verde);
limpa_matriz(cursor);
pontuacao_verde++;
cor = 0;
for(i = 0; i < pontuacao_verde; i++)
{
verde[i/3][i%3] = 1;
__delay_ms(200);
}
__delay_ms(1000);
if(pontuacao_verde == 9)
{
for(i = pontuacao_verde+1; i > 0; i--)
{
verde[(i-1)/3][(i-1)%3] = 0;
__delay_ms(100);
}
pontuacao_vermelho = 0;
pontuacao_verde = 0;
}
__delay_ms(500);
limpa_matriz(verde);
linha = 0;
posicao = 0;
cursor[0][0] = 1;
cor = 1;
}
//confere se o jogador da cor vermelha ganhou
//se sim, mostra a pontuação com efeito,
//reseta as matrizes e as variáveis de controle
if(testa_ganhou(vermelho))
{
limpa_matriz(vermelho);
limpa_matriz(verde);
limpa_matriz(cursor);
pontuacao_vermelho++;
cor = 1;
for(i = 0; i < pontuacao_vermelho; i++)
{
vermelho[i/3][i%3] = 1;
__delay_ms(200);
}
__delay_ms(1000);
if(pontuacao_vermelho == 9)
{
for(i = pontuacao_vermelho+1; i > 0; i--)
{
vermelho[(i-1)/3][(i-1)%3] = 0;
__delay_ms(100);
}
pontuacao_vermelho = 0;
pontuacao_verde = 0;
}
__delay_ms(500);
limpa_matriz(vermelho);
linha = 0;
posicao = 0;
cursor[0][0] = 1;
cor = 0;
}
//confere se deu velha
//se sim, apaga a matriz por um segundo,
//reseta as matrizes e as variáveis de controle
if(testa_velha(verde, vermelho))
{
limpa_matriz(verde);
limpa_matriz(vermelho);
limpa_matriz(cursor);
__delay_ms(1000);
linha = 0;
posicao = 0;
cursor[0][0] = 1;
cor = 0;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment