// 2008.09.02 18:05 -> 2008.09.23 22:39 // Fuse bits: div8 disabled #include <avr/io.h> #include <avr/pgmspace.h> #include <avr/interrupt.h> #define F_CPU 8000000UL // 8 MHz #include <util/delay.h> #define countStart 9 // manually adjusted after one week #define typeCount 3 volatile unsigned char sec, keys, oldkeys, colSet, type, automatic = 0xff; volatile unsigned int time; typedef struct bitfield{ unsigned char point:1; unsigned char settings:1; unsigned char blink:1; }bitfield; bitfield flag; volatile char col = 0; #define C3 PD2 #define C5 PD3 #define C4 PD4 #define C1 PD5 #define C2 PD6 unsigned char c[5] = { (1<<C1), (1<<C2), (1<<C3), (1<<C4), (1<<C5) }; #define R2 PB7 #define R4 PB6 #define R1 PB5 #define R3 PB4 #define R7 PB3 #define R5 PB2 #define R8 PB1 #define R6 PB0 unsigned char r[8] = { (1<<R1), (1<<R2), (1<<R3), (1<<R4), (1<<R5), (1<<R6), (1<<R7), (1<<R8) }; #define CC ((1<<C1)|(1<<C2)|(1<<C3)|(1<<C4)|(1<<C5)) #define B0 PD0 #define B1 PD1 unsigned char display[5]; unsigned char clock[4]; //**************** // Time calculation and visualisation //**************** ISR (TIMER0_OVF_vect) { TCNT0 = countStart; time ++; col++; if (col == 5) col = 0; PORTD |= CC; PORTD &= ~c[col]; PORTB = display[col]; if (time == 2000) { time = 0; if (flag.point) // half second { flag.point = 0; if (colSet>1) sec++; if (sec == 60) { sec = 0; clock[0]++; if (clock[0] == 10) { clock[0] = 0; clock[1]++; if (clock[1] == 6) { clock[1] = 0; clock[2]++; if ((clock[2] == 4)&&(clock[3] == 2)) { clock[2] = 0; clock[3] = 0; if (automatic) type++; } if (clock[2] == 10) { clock[2] = 0; clock[3]++; } } } } } else { flag.point = 1; } } } //**************** // Init section //**************** void Init (void) { ACSR = (1<<ACD); //Turn Off ANA_COMP //clock[3] = 1; //clock[2] = 2; //clock[1] = 0; //clock[0] = 0; //type = 1; //flag.settings = 0; //flag.blink = 0; colSet = 4; oldkeys = 0b11; //DDRA = 0; //PORTA = 0xFF; DDRD = ~((1<<0)|(1<<1)); PORTD = 0b11; DDRB = 0xFF; TCCR0B = (1<<CS01); // presc. 8 TCNT0 = countStart; // 256-8 = 250; 8*250/8 000 000 = 0.00025 TIMSK = (1<<TOIE0); sei(); } //**************** // Keyboard and time setup //**************** void CheckKeyboard (void) { keys = PIND&0b11; if (keys != 0b11) { _delay_ms(5); if (((PIND&0b11) == keys)&&(keys!=0b11)) { oldkeys = keys; } } else if (oldkeys != 0b11) { if (oldkeys == 0b10) { if ((flag.settings == 0)&&(flag.blink == 0)) { flag.blink = 1; } else if (flag.blink) { flag.blink = 0; flag.settings = 1; colSet = 0; } else if (flag.settings) { if (colSet == 4) { colSet = 0; } else if (colSet == 2) { colSet=4; flag.settings = 0; } else { colSet++; } } } else if (oldkeys == 0b01) { if (flag.blink) { flag.blink = 0; automatic = ~automatic; } else if (flag.settings) { clock[colSet]++; if (colSet < 2) sec = 0; if ((colSet==0)&&(clock[0]==10)) { clock[0] = 0; } else if ((colSet==1)&&(clock[1]==6)) { clock[1] = 0; } else if ((colSet==2)&&(clock[2]==10)) { clock[2]=0; clock[3]++; } else if (((colSet==2)&&(clock[3]==2))&&(clock[2]==4)) { clock[2]=0; clock[3]=0; } } else { type ++; } } oldkeys = 0b11; } } //**************** // Service functions //**************** unsigned char bcd (unsigned char a) { return (((a / 10) << 4)|(a%10)); } unsigned char transform (unsigned char a) { unsigned char temp, i; temp = 0; for (i = 0; i<8; i++) if (a & (1<<i)) temp |= r[i]; return ~temp; } //**************** // BCD Visualisation //**************** void DigitalCode(void) { display[4] = transform(bcd(sec)); if ((colSet == 0)&&(flag.point)) { display [3] = 0xf0; } else if ((colSet == 1)&&(flag.point)) { display [3] = 0x0f; } else if ((flag.point)&&(flag.blink)) display[3] = 0xFF; else display[3] = 0; display[2] = transform((clock[1]<<4)|(clock[0])); if ((colSet == 2)&&(flag.point)) display[1] = 0xFF; else if ((flag.point)&&(flag.blink)) display[1] = 0xFF; else display[1] = 0; display[0] = transform((clock[3]<<4)|(clock[2])); } //**************** // Analog clocks //**************** unsigned char hours [12][3] PROGMEM = { {(1<<6)|(1<<5)|(0<<4)|(1<<3)|(1<<2), (1<<6)|(0<<5)|(0<<4)|(0<<3)|(1<<2), (1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)}, {(1<<6)|(1<<5)|(1<<4)|(0<<3)|(1<<2), (1<<6)|(0<<5)|(0<<4)|(0<<3)|(1<<2), (1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)}, {(1<<6)|(1<<5)|(1<<4)|(1<<3)|(0<<2), (1<<6)|(0<<5)|(0<<4)|(0<<3)|(1<<2), (1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)}, {(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2), (1<<6)|(0<<5)|(0<<4)|(0<<3)|(0<<2), (1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)}, {(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2), (1<<6)|(0<<5)|(0<<4)|(0<<3)|(1<<2), (1<<6)|(1<<5)|(1<<4)|(1<<3)|(0<<2)}, {(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2), (1<<6)|(0<<5)|(0<<4)|(0<<3)|(1<<2), (1<<6)|(1<<5)|(1<<4)|(0<<3)|(1<<2)}, {(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2), (1<<6)|(0<<5)|(0<<4)|(0<<3)|(1<<2), (1<<6)|(1<<5)|(0<<4)|(1<<3)|(1<<2)}, {(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2), (1<<6)|(0<<5)|(0<<4)|(0<<3)|(1<<2), (1<<6)|(0<<5)|(1<<4)|(1<<3)|(1<<2)}, {(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2), (1<<6)|(0<<5)|(0<<4)|(0<<3)|(1<<2), (0<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)}, {(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2), (0<<6)|(0<<5)|(0<<4)|(0<<3)|(1<<2), (1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)}, {(0<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2), (1<<6)|(0<<5)|(0<<4)|(0<<3)|(1<<2), (1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)}, {(1<<6)|(0<<5)|(1<<4)|(1<<3)|(1<<2), (1<<6)|(0<<5)|(0<<4)|(0<<3)|(1<<2), (1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)} }; unsigned char mins [20][2] = { {0, (1<<4)}, {0, (1<<3)}, {0, (1<<2)}, {0, (1<<1)}, {1, (1<<1)}, {2, (1<<1)}, {3, (1<<1)}, {4, (1<<1)}, {4, (1<<1)}, {4, (1<<3)}, {4, (1<<4)}, {4, (1<<5)}, {4, (1<<6)}, {4, (1<<7)}, {3, (1<<7)}, {2, (1<<7)}, {1, (1<<7)}, {0, (1<<7)}, {0, (1<<6)}, {0, (1<<5)} }; unsigned char mmins[3] = { 0, (1<<4), (1<<5)|(1<<3) }; unsigned char anal (unsigned char line) { unsigned char res, min, mmin, hr; res = 0; if (((sec / 12) == (4 - line))&&flag.point) res = 1; if (flag.settings) res = 0; if (flag.point) if (flag.blink) res = 1; else if ((colSet == 0)&&(line > 1)) res = 1; else if ((colSet == 1)&&(line % 4)) res = 1; else if ((colSet == 2)&&(line <3)) res = 1; min = (clock[1]*10+clock[0]); mmin = min % 3; min = min / 3; hr = (clock[3]*10+clock[2]) % 12; if (mins[min][0] == line) res |= mins[min][1]; switch (line) { case 1: { res |= pgm_read_byte(&(hours[hr][0])); break; } case 2: { res |= mmins[mmin]; res |= pgm_read_byte(&(hours[hr][1])); break; } case 3: { res |= pgm_read_byte(&(hours[hr][2])); break; } } return transform(res); } void AnalogCode(void) { display[0] = anal(0); display[1] = anal(1); display[2] = anal(2); display[3] = anal(3); display[4] = anal(4); } //**************** // Morse Visualisation //**************** unsigned char morseArray[5][10] PROGMEM= { {0, 0, 0, 0, 0, 1, 1, 1, 1, 1}, {0, 0, 0, 0, 1, 1, 1, 1, 1, 0}, {0, 0, 0, 1, 1, 1, 1, 1, 0, 0}, {0, 0, 1, 1, 1, 1, 1, 0, 0, 0}, {0, 1, 1, 1, 1, 1, 0, 0, 0, 0} }; unsigned char morse(unsigned char line) { unsigned char res, temp, temp1; temp = bcd(sec); temp1 = ((temp & 0xf0)>>4); temp &= 0x0f; res = (pgm_read_byte(&(morseArray[line][temp]))<<0)|(pgm_read_byte(&(morseArray[line][temp1]))<<1); res |= (pgm_read_byte(&(morseArray[line][clock[0]]))<<3)|(pgm_read_byte(&(morseArray[line][clock[1]]))<<4); res |= (pgm_read_byte(&(morseArray[line][clock[2]]))<<6)|(pgm_read_byte(&(morseArray[line][clock[3]]))<<7); if (flag.point) if (flag.blink) res |= (1<<2)|(1<<5); else if (colSet == 2) res |= (1<<5); else if (((colSet == 0)&&(line>1))||((colSet == 1)&&(line<3))) res |= (1<<2); return transform(res); } void MorseCode(void) { display[0] = morse(0); display[1] = morse(1); display[2] = morse(2); display[3] = morse(3); display[4] = morse(4); } //**************** // Type selection //**************** void PrintPrepare (void) { // Prepare display[]; if (type == typeCount) type = 0; switch (type) { case 1: { DigitalCode(); break; } case 2: { AnalogCode(); break; } case 0: { MorseCode(); break; } } if ((flag.blink)&&automatic) if (flag.point) display[0] &= ~((1<<R8)|(1<<R7)); else display[0] |= ((1<<R8)|(1<<R7)); } void main(void) { Init(); for (;;) { CheckKeyboard(); PrintPrepare(); } }
Source: https://habr.com/ru/post/364715/
All Articles