#include <tiny2313.h>
#define True 0x01
#define False 0x00
#define SetBit(x) |= (1<<x)
#define ClrBit(x) &= ~(1<<x)
#define InvBit(x) ^= (1<<x)
#define IsBit(x) & (1<<x)
typedef unsigned char byte;
typedef unsigned int word;
#define MaxHrs 23
#define MaxMin 59
#define MaxSec 59
#define PulseRatio 5
#define Kpr (PulseRatio - 1)
#define RealColCnt 120
#define ColCnt (RealColCnt * PulseRatio)
#define LapCnt 49
#define _OCIE1A 6
#define _INT1 7
flash const byte CharMap[12, 6] = {{0x7C, 0x82, 0x82, 0x82, 0x7C, 0x00},
{0x00, 0x42, 0xFE, 0x02, 0x00, 0x00},
{0x4E, 0x92, 0x92, 0x92, 0x62, 0x00},
{0x44, 0x82, 0x92, 0x92, 0x6C, 0x00},
{0xF0, 0x10, 0x10, 0x10, 0xFE, 0x00},
{0xE4, 0xA2, 0xA2, 0xA2, 0x9C, 0x00},
{0x7C, 0x92, 0x92, 0x92, 0x4C, 0x00},
{0x80, 0x80, 0x8E, 0x90, 0xE0, 0x00},
{0x6C, 0x92, 0x92, 0x92, 0x6C, 0x00},
{0x64, 0x92, 0x92, 0x92, 0x7C, 0x00},
{0x00, 0x00, 0x28, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
struct TTimeRec
{
byte Sec, Min, Hrs;
byte Htens, Hunits, Mtens, Munits;
} TimeRec;
word Delta;
byte ColNum;
byte CharNum;
bit Additive;
bit DisplayOn;
bit PointsOn;
bit PointsStop;
byte DotOff;
byte EventsFlag;
byte IR_HalfPeriodCounter;
word IR_Interval;
word IR_Command;
bit IR_Detect, IR_Error;
byte SetTimePos;
#define RC5Standby 12
#define RC5VolumePlus 16
#define RC5VolumeMinus 17
#define IR_Pin PIND.3
#define RC5FullPeriodNom 398
#define RC5FullPeriodErr (RC5FullPeriodNom / 4)
#define RC5HalfPeriodNom (RC5FullPeriodNom / 2)
#define RC5HalfPeriodErr (RC5FullPeriodNom / 8)
#define RC5Timeout 18295
#define RC5FullPeriodMax (RC5FullPeriodNom + RC5FullPeriodErr)
#define RC5FullPeriodMin (RC5FullPeriodNom - RC5FullPeriodErr)
#define RC5HalfPeriodMax (RC5HalfPeriodNom + RC5HalfPeriodErr)
#define RC5HalfPeriodMin (RC5HalfPeriodNom - RC5HalfPeriodErr)
#define LoByte(x) (*(byte*)&x)
#define ExternalInterrupt1_Enable GIMSK SetBit(_INT1)
#define ExternalInterrupt1_Disable GIMSK ClrBit(_INT1)
#define Is_ExternalInterrupt1_Enable GIMSK IsBit(_INT1)
#define Set_External_Interrupt0_Flag EventsFlag SetBit(0)
#define Clr_External_Interrupt0_Flag EventsFlag ClrBit(0)
#define Is_External_Interrupt0_Flag EventsFlag IsBit(0)
#define Set_Timer0_Overflow_Flag EventsFlag SetBit(1)
#define Clr_Timer0_Overflow_Flag EventsFlag ClrBit(1)
#define Is_Timer0_Overflow_Flag EventsFlag IsBit(1)
#define Set_External_Interrupt1_Flag EventsFlag SetBit(3)
#define Clr_External_Interrupt1_Flag EventsFlag ClrBit(3)
#define Is_External_Interrupt1_Flag EventsFlag IsBit(3)
byte TensAndUnitsToByte(byte Tens, byte Units)
{
byte Tmp, i;
i = 0;
Tmp = 0;
while (i < Tens)
{
Tmp += 10;
i++;
};
Tmp += Units;
return Tmp;
}
void ByteToTensAndUnits(byte *Arg, byte *Tens, byte *Units)
{
*Units = *Arg;
*Tens = 0;
while (*Units > 9)
{
(*Tens)++;
*Units -= 10;
};
}
void Extract(void)
{
ByteToTensAndUnits(&TimeRec.Hrs, &TimeRec.Htens, &TimeRec.Hunits);
ByteToTensAndUnits(&TimeRec.Min, &TimeRec.Mtens, &TimeRec.Munits);
}
void Time(void)
{
TimeRec.Sec++;
if (TimeRec.Sec > MaxSec)
{
TimeRec.Sec = 0;
TimeRec.Min++;
if (TimeRec.Min > MaxMin)
{
TimeRec.Min = 0;
TimeRec.Hrs++;
if (TimeRec.Hrs > MaxHrs) TimeRec.Hrs = 0;
};
};
Extract();
}
void Display(void)
{
byte Num, Tmp, Flag;
Flag = 0;
if (SetTimePos == (CharNum + 1)) Flag = 1;
DotOff++;
if (DotOff > Kpr) DotOff = 0;
if (DotOff)
{
if (!Flag)
PORTB = 0xFF;
else
PORTB = 0xFE;
return;
};
switch (CharNum)
{
case 0: Num = TimeRec.Htens; break;
case 1: Num = TimeRec.Hunits; break;
case 2: if (PointsStop) Num = 10; else {if (PointsOn) Num = 10; else Num = 11;} break;
case 3: Num = TimeRec.Mtens; break;
case 4: Num = TimeRec.Munits; break;
};
if (SetTimePos == (CharNum + 1)) Flag = 1;
Tmp = ~(CharMap[Num, ColNum]);
if (Flag && (ColNum < 5)) Tmp ClrBit(0);
PORTB = Tmp;
ColNum++;
if (ColNum > 5)
{
ColNum = 0;
CharNum++;
if (CharNum > 4)
{
CharNum = 0;
DisplayOn = False;
};
}
}
void SetHours(byte Hours)
{
if (Hours <= MaxHrs) TimeRec.Hrs = Hours;
}
void SetMinutes(byte Minutes)
{
if (Minutes <= MaxMin) TimeRec.Min = Minutes;
}
void SetTime(void)
{
byte Command, Tmp;
Command = LoByte(IR_Command);
if (Command == RC5VolumePlus)
{
if (SetTimePos < 5) SetTimePos++; else SetTimePos = 0;
if (SetTimePos == 3) PointsStop = True; else PointsStop = False;
} else
if (Command == RC5VolumeMinus)
{
if (SetTimePos > 0) SetTimePos--; else SetTimePos = 5;
if (SetTimePos == 3) PointsStop = True; else PointsStop = False;
} else
if (Command == RC5Standby)
{
if (SetTimePos == 3) TimeRec.Sec = 0;
PointsStop = False;
} else
if (Command <= 9)
{
if (SetTimePos == 1)
{
Tmp = TensAndUnitsToByte(Command, TimeRec.Hunits);
SetHours(Tmp);
} else
if (SetTimePos == 2)
{
Tmp = TensAndUnitsToByte(TimeRec.Htens, Command);
SetHours(Tmp);
} else
if (SetTimePos == 4)
{
Tmp = TensAndUnitsToByte(Command, TimeRec.Munits);
SetMinutes(Tmp);
} else
if (SetTimePos == 5)
{
Tmp = TensAndUnitsToByte(TimeRec.Mtens, Command);
SetMinutes(Tmp);
};
Extract();
};
}
void IR_Cancel(void)
{
ExternalInterrupt1_Disable;
IR_Interval = TCNT1;
IR_HalfPeriodCounter = 0;
IR_Command = 0;
IR_Detect = False;
IR_Error = True;
}
void IR_Process(void)
{
byte Tmp;
Tmp = IR_Command;
if ((IR_Interval >= RC5HalfPeriodMin) && (IR_Interval <= RC5HalfPeriodMax))
IR_HalfPeriodCounter++;
else
if ((IR_Interval >= RC5FullPeriodMin) && (IR_Interval <= RC5FullPeriodMax))
{
if ((IR_HalfPeriodCounter & 0x01) == 0)
{
IR_HalfPeriodCounter += 2;
Tmp = ~Tmp;
} else goto ERR;
} else goto ERR;
if ((IR_HalfPeriodCounter & 0x01) == 0) IR_Command = (IR_Command << 1) | (Tmp & 0x01);
if ((IR_HalfPeriodCounter == 2) && (IR_Command = 0x00)) goto ERR;
if (IR_HalfPeriodCounter >= 26)
{
IR_Command = ~IR_Command & 0b00111111;
SetTime();
IR_Detect = False;
IR_Error = False;
};
return;
ERR:
IR_Cancel();
}
void OnOverflowTimer0(void)
{
static byte Tick;
Tick++;
if (Tick > 58)
{
Time();
Tick = 0;
}
if (!PointsStop)
{
if (Tick > 29)
PointsOn = True;
else
PointsOn = False;
};
}
void OnExternalInterrupt0(void)
{
static word Last;
static word Total;
static word Latch;
static byte Lap;
Latch = TCNT1;
Total = Latch - Last;
Last = Latch;
Lap++;
if (Lap > LapCnt)
{
Delta = Total / ColCnt;
Lap = 0;
};
ColNum = 0;
CharNum = 0;
DotOff = Kpr;
OCR1A = Latch + Delta;
DisplayOn = True;
Additive = False;
}
void OnExternalInterrupt1(void)
{
static word Last;
static word Latch;
Latch = TCNT1;
IR_Interval = Latch - Last;
Last = Latch;
if (!IR_Detect)
{
if (IR_Pin == 0)
{
IR_Detect = True;
IR_Command = 0;
IR_HalfPeriodCounter = 0;
} else
{
IR_Cancel();
};
} else
{
IR_Process();
};
}
interrupt [EXT_INT0] void ext_int0_isr(void)
{
Set_External_Interrupt0_Flag;
}
interrupt [EXT_INT1] void ext_int1_isr(void)
{
Set_External_Interrupt1_Flag;
}
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0 = 0x13;
Set_Timer0_Overflow_Flag;
}
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
if (!DisplayOn) return;
Additive = !Additive;
OCR1A = TCNT1 + Delta + Additive;
Display();
}
void Initialization(void)
{
PORTA=0x07;
DDRA=0x00;
DDRB=0xFF;
PORTB=0xFF;
PORTD=0x7F;
DDRD=0x00;
GIMSK=0xC0;
MCUCR=0x06;
TCCR0A=0x00;
TCCR0B=0x05;
TCNT0=0x13;
OCR0A=0x00;
OCR0B=0x00;
TCCR1A=0x00;
TCCR1B=0x03;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
TIMSK=0x42;
#asm("sei");
}
void main(void)
{
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
Initialization();
while (1)
{
if (Is_External_Interrupt0_Flag)
{
OnExternalInterrupt0();
Clr_External_Interrupt0_Flag;
};
if (Is_Timer0_Overflow_Flag)
{
OnOverflowTimer0();
Clr_Timer0_Overflow_Flag;
};
if (Is_External_Interrupt1_Flag)
{
OnExternalInterrupt1();
Clr_External_Interrupt1_Flag;
};
if (IR_Error) …
{
if ((TCNT1 - IR_Interval) > RC5Timeout)
{
IR_Error = False;
EIFR = 0xC0;
ExternalInterrupt1_Enable;
};
};
};
}
|