/* Lab 03 - Cronometro digital programable
Laboratorio de sistemas digitales y microprocesadores
Nomar Sánchez, ID: 1104168*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
volatile uint8_t display1_data;
volatile uint8_t BUTTON=5;
uint8_t n1 = 0, n2 = 0, n3 = 0, n4 = 0;
uint16_t num1 = 0, num2 = 1, suma = 0;
int Status=0;
int Reset=1, Pause=0, Add=0, Subtract=0, Increase=0, Set=0 ;
int Number=0, Digit=0;
void Decoder0(uint8_t num) {
switch (num) {
case 0:
display1_data = 0x01;
break;
case 1:
display1_data = 0x4F;
break;
case 2:
display1_data = 0x12;
break;
case 3:
display1_data = 0x06;
break;
case 4:
display1_data = 0x4C;
break;
case 5:
display1_data = 0x24;
break;
case 6:
display1_data = 0x20;
break;
case 7:
display1_data = 0x0F;
break;
case 8:
display1_data = 0x00;
break;
case 9:
display1_data = 0x0C;
break;
default:
display1_data = 0xFF; // Invalid number, display nothing
break;
}
}
void Multiplexacion_Displays() {
// Display 1
Decoder0(n4);
PORTB = 0x00;
PORTD = display1_data;
PORTD |= (1 << PORTD7);
PORTB = 0x01;
Delay1ms();
// Display 2
Decoder0(n3);
PORTB = 0x00;
PORTD = display1_data;
PORTD |= (0 << PORTD7);
PORTB = 0x02;
Delay1ms();
// Display 3
Decoder0(n2);
PORTB = 0x00;
PORTD = display1_data;
PORTD |= (1 << PORTD7);
PORTB = 0x04;
Delay1ms();
// Display 4
Decoder0(n1);
PORTB = 0x00;
PORTD = display1_data;
PORTD |= (1 << PORTD7);
PORTB = 0x08;
Delay1ms();
}
void Delay500ms() {
// Initialize Timer1
TCCR1A = 0x00;
TCCR1B = (1 << CS10) | (1 << CS12); // Prescaler = 1024
TCNT1 = 65535 - 7812; // Count for 0.1 second
while ((TIFR1 & (1 << TOV1)) == 0); // Wait for overflow
TIFR1 |= (1 << TOV1); // Clear the overflow flag
TCCR1B = 0x00; // Stop the timer
}
void Delay100ms() {
// Initialize Timer1
TCCR1A = 0x00;
TCCR1B = (1 << CS10) | (1 << CS12); // Prescaler = 1024
TCNT1 = 65535 - 1563; // Count for 2 ms
while ((TIFR1 & (1 << TOV1)) == 0) // Wait for overflow
{
Multiplexacion_Displays();
}
TIFR1 |= (1 << TOV1); // Clear the overflow flag
TCCR1B = 0x00; // Stop the timer
}
void Delay16ms() {
// Initialize Timer0
TCCR0A = 0x00;
TCCR0B = (1 << CS00) | (1 << CS02); // Prescaler = 64
TCNT0 = 256 - 250; // Count for 3 ms
while ((TIFR0 & (1 << TOV0)) == 0); // Wait for overflow
TIFR0 |= (1 << TOV0); // Clear the overflow flag
TCCR0B = 0x00; // Stop the timer
}
void Delay4ms() {
// Initialize Timer0
TCCR0A = 0x00;
TCCR0B = (1 << CS00) | (1 << CS02); // Prescaler = 1024
TCNT0 = 256 - 150; // Count for 4 ms
while ((TIFR0 & (1 << TOV0)) == 0); // Wait for overflow
TIFR0 |= (1 << TOV0); // Clear the overflow flag
TCCR0B = 0x00; // Stop the timer
}
void Delay1ms() {
// Initialize Timer0
TCCR0A = 0x00;
TCCR0B = (1 << CS00) | (1 << CS01); // Prescaler = 64
TCNT0 = 256 - 250; // Count for 4 ms
while ((TIFR0 & (1 << TOV0)) == 0); // Wait for overflow
TIFR0 |= (1 << TOV0); // Clear the overflow flag
TCCR0B = 0x00; // Stop the timer
}
ISR(PCINT1_vect) {
if (PINC & (1 << PC2)) { // Button 2
Increase=1;
Reset=0; Pause=0; Add=0; Subtract=0;
Number++;
if (Number==10)
{
Number=0;
}
}
if (PINC & (1 << PC1)) { // Button 1
Set=1;
Reset=0; Pause=0; Add=0; Subtract=0; Increase=0; Number=0;
if (PINC & (1 << PC1))
{
Digit++;
}
if (Digit==5)
{
Digit=1;
}
}
if (PINC & (1 << PC3))
{ // Button 3
Reset=1;
Pause=0; Add=0; Subtract=0; Increase=0; Set=0; Digit=0; Number=0;
}
if (PINC & (1 << PC0)) { // Button 0
Reset=0; Increase=0; Set=0; Digit=0; Number=0; Subtract=0;
if (Status==0)
{
Add=1;
n1 = 0, n2 = 0, n3 = 0, n4 = 0;
num1 = 0, num2 = 1, suma = 0;
}
if (Status==1 or Status==3)
{
Pause++;
}
if (Pause==2)
{
Pause=0;
}
if (Status==2 or Status==3)
{
Subtract=1;
num1 = 9, num2 = 1, suma = 0;
Pause=0; Add=0; Increase=0; Set=0; Digit=0; Number=0;
}
}
}
void setear_numeros()
{
if(Digit==1)
{
// Display 3
n4=Number;
Decoder0(n4);
PORTB = 0x00;
PORTD = display1_data;
PORTD |= (1 << PORTD7);
PORTB = 0x01;
Delay500ms();
PORTB = 0x00;
Delay500ms();
}
if(Digit==2)
{
// Display 3
n3=Number;
Decoder0(n3);
PORTB = 0x00;
PORTD = display1_data;
PORTD &= ~(1 << PORTD7);
PORTB = 0x02;
Delay500ms();
PORTB = 0x00;
Delay500ms();
}
if(Digit==3)
{
// Display 2
n2=Number;
Decoder0(n2);
PORTB = 0x00;
PORTD = display1_data;
PORTD |= (1 << PORTD7);
PORTB = 0x04;
Delay500ms();
PORTB = 0x00;
Delay500ms();
}
if(Digit==4)
{
// Display 1
n1=Number;
Decoder0(n1);
PORTB = 0x00;
PORTD = display1_data;
PORTD |= (1 << PORTD7);
PORTB = 0x08;
Delay500ms();
PORTB = 0x00;
Delay500ms();
}
}
void Suma ()
{
Multiplexacion_Displays();
Delay100ms();
// Ingreso de números (valores de 0 a 9999)
num1 = (n1 * 1000) + (n2 * 100) + (n3 * 10) + n4;
// Realizar la suma (asumiendo que también tienes valores para n1, n2, n3, y n4)
suma = num1 + num2;
// Descomponer la suma en n1, n2, n3 y n4
n1 = suma / 1000;
suma %= 1000;
n2 = suma / 100;
suma %= 100;
n3 = suma / 10;
n4 = suma % 10;
}
void Resta ()
{
Multiplexacion_Displays();
Delay100ms();
// Ingreso de números (valores de 0 a 9999)
num1 = (n1 * 1000) + (n2 * 100) + (n3 * 10) + n4;
// Realizar la suma (asumiendo que también tienes valores para n1, n2, n3, y n4)
suma = num1 - num2;
// Descomponer la suma en n1, n2, n3 y n4
n1 = suma / 1000;
suma %= 1000;
n2 = suma / 100;
suma %= 100;
n3 = suma / 10;
n4 = suma % 10;
}
int main() {
// Setup ports and pins
DDRD = 0xFF; // Port D as output
DDRB = 0xFF; // Port B as output
DDRC = 0x00; // Port C as input
// Enable Pin Change Interrupts on PC0, PC1, PC2, and PC3
PCMSK1 = 0x0F;
PCICR = (1 << PCIE1);
sei(); // Enable global interrupts
while (1) {
if (Add==1)
{
Status=1;
Suma();
while (Pause==1)
{
Multiplexacion_Displays();
}
if (n1==9 and n2==9 and n3==9 and n4==9)
{
Reset=1;
Add=0;
Status=0;
}
}
if (Set==1)
{
Status=2;
setear_numeros();
}
if (Subtract==1)
{
Status=3;
Resta();
while (Pause==1)
{
Multiplexacion_Displays();
}
if (n1==0 and n2==0 and n3==0 and n4==0)
{
Reset=1;
Subtract=0;
Status=0;
}
}
if (Reset==1)
{
n1 = 0, n2 = 0, n3 = 0, n4 = 0;
num1 = 0, num2 = 0, suma = 0;
Status=0;
Multiplexacion_Displays();
}
}
return 0;
}