00001
00010 #include <avr/io.h>
00011 #include <avr/interrupt.h>
00012 #include <avr/pgmspace.h>
00013 #include <util/delay.h>
00014
00015 #include "saa1064.h"
00016 #include "dcftime.h"
00017
00018 uint8_t byte[4] = { 2, 3, 1, 0 };
00019 uint8_t output[4];
00020 uint8_t outputOld[4];
00023 enum modes {
00024 timeasbinary,
00025 dateasbinary,
00026 timeasbcdhorizontal,
00027 dateasbcdhorizontal,
00028 timeasbcdvertical,
00029 dateasbcdvertical,
00030 timestamp
00031 };
00033 enum modes mode;
00034
00036 uint8_t demomode = 0;
00037
00038
00042 void setLeds(void) {
00043 uint8_t i;
00044 for (i = 0; i < 4; i++) {
00045 if (output[i] != outputOld[i]) {
00046 set_led_digit(byte[i], output[i]);
00047 outputOld[i] = output[i];
00048 }
00049 }
00050 }
00051
00056 void setOutput(dcf_datetime datetime) {
00057 uint8_t bcdlow, bcdhigh;
00058 const uint32_t TS01012000 = 946681200UL;
00059 const uint16_t monthstarts[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
00060 const uint32_t SECONDSINADAY = (60UL * 60 * 24);
00061 uint32_t ts;
00062
00063 switch (mode) {
00064 case timeasbinary:
00065
00066 output[0] = datetime.time.hour;
00067 output[1] = datetime.time.minute;
00068 output[2] = datetime.time.second;
00069 output[3] = 0;
00070 break;
00071 case dateasbinary:
00072
00073
00074 output[0] = datetime.date.dayofmonth;
00075 output[1] = datetime.date.month;
00076 output[2] = datetime.date.year;
00077 output[3] = datetime.date.dayofweek;
00078 break;
00079 case timeasbcdhorizontal:
00080
00081
00082 bcdlow = datetime.time.hour % 10;
00083 bcdhigh = datetime.time.hour / 10;
00084 output[0] = (bcdhigh << 4) | bcdlow;
00085 bcdlow = datetime.time.minute % 10;
00086 bcdhigh = datetime.time.minute / 10;
00087 output[1] = (bcdhigh << 4) | bcdlow;
00088 bcdlow = datetime.time.second % 10;
00089 bcdhigh = datetime.time.second / 10;
00090 output[2] = (bcdhigh << 4) | bcdlow;
00091 output[3] = 0;
00092 break;
00093 case dateasbcdhorizontal:
00094
00095
00096 bcdlow = datetime.date.dayofmonth % 10;
00097 bcdhigh = datetime.date.dayofmonth / 10;
00098 output[0] = (bcdhigh << 4) | bcdlow;
00099 bcdlow = datetime.date.month % 10;
00100 bcdhigh = datetime.date.month / 10;
00101 output[1] = (bcdhigh << 4) | bcdlow;
00102 bcdlow = datetime.date.year % 10;
00103 bcdhigh = datetime.date.year / 10;
00104 output[2] = (bcdhigh << 4) | bcdlow;
00105 bcdlow = datetime.date.dayofweek;
00106 bcdhigh = 0;
00107 output[3] = (bcdhigh << 4) | bcdlow;
00108 break;
00109 case timeasbcdvertical:
00110
00111
00112 output[0] = 0;
00113 output[1] = 0;
00114 output[2] = 0;
00115 output[3] = 0;
00116 bcdlow = datetime.time.hour % 10;
00117 bcdhigh = datetime.time.hour / 10;
00118 output[0] |= ((bcdhigh & 8) << 4) | ((bcdlow & 8) << 3);
00119 output[1] |= ((bcdhigh & 4) << 5) | ((bcdlow & 4) << 4);
00120 output[2] |= ((bcdhigh & 2) << 6) | ((bcdlow & 2) << 5);
00121 output[3] |= ((bcdhigh & 1) << 7) | ((bcdlow & 1) << 6);
00122 bcdlow = datetime.time.minute % 10;
00123 bcdhigh = datetime.time.minute / 10;
00124 output[0] |= ((bcdhigh & 8) << 1) | ((bcdlow & 8) << 0);
00125 output[1] |= ((bcdhigh & 4) << 2) | ((bcdlow & 4) << 1);
00126 output[2] |= ((bcdhigh & 2) << 3) | ((bcdlow & 2) << 2);
00127 output[3] |= ((bcdhigh & 1) << 4) | ((bcdlow & 1) << 3);
00128 bcdlow = datetime.time.second % 10;
00129 bcdhigh = datetime.time.second / 10;
00130 output[0] |= ((bcdhigh & 8) >> 2) | ((bcdlow & 8) >> 3);
00131 output[1] |= ((bcdhigh & 4) >> 1) | ((bcdlow & 4) >> 2);
00132 output[2] |= ((bcdhigh & 2) << 0) | ((bcdlow & 2) >> 1);
00133 output[3] |= ((bcdhigh & 1) << 1) | ((bcdlow & 1) << 0);
00134 break;
00135 case dateasbcdvertical:
00136
00137
00138 output[0] = 0;
00139 output[1] = 0;
00140 output[2] = 0;
00141 output[3] = 0;
00142 bcdlow = datetime.date.dayofmonth % 10;
00143 bcdhigh = datetime.date.dayofmonth / 10;
00144 output[0] |= ((bcdhigh & 8) << 4) | ((bcdlow & 8) << 3);
00145 output[1] |= ((bcdhigh & 4) << 5) | ((bcdlow & 4) << 4);
00146 output[2] |= ((bcdhigh & 2) << 6) | ((bcdlow & 2) << 5);
00147 output[3] |= ((bcdhigh & 1) << 7) | ((bcdlow & 1) << 6);
00148 bcdlow = datetime.date.month % 10;
00149 bcdhigh = datetime.date.month / 10;
00150 output[0] |= ((bcdhigh & 8) << 1) | ((bcdlow & 8) << 0);
00151 output[1] |= ((bcdhigh & 4) << 2) | ((bcdlow & 4) << 1);
00152 output[2] |= ((bcdhigh & 2) << 3) | ((bcdlow & 2) << 2);
00153 output[3] |= ((bcdhigh & 1) << 4) | ((bcdlow & 1) << 3);
00154 bcdlow = datetime.date.year % 10;
00155 bcdhigh = datetime.date.year / 10;
00156 output[0] |= ((bcdhigh & 8) >> 2) | ((bcdlow & 8) >> 3);
00157 output[1] |= ((bcdhigh & 4) >> 1) | ((bcdlow & 4) >> 2);
00158 output[2] |= ((bcdhigh & 2) << 0) | ((bcdlow & 2) >> 1);
00159 output[3] |= ((bcdhigh & 1) << 1) | ((bcdlow & 1) << 0);
00160 break;
00161 case timestamp:
00162
00163 ts = TS01012000 + SECONDSINADAY;
00164 ts += SECONDSINADAY * datetime.date.year * 365;
00165
00166 ts += SECONDSINADAY * ((datetime.date.year - 1) / 4);
00167 ts += SECONDSINADAY * monthstarts[datetime.date.month - 1];
00168 if (((datetime.date.year % 4) == 0) && (datetime.date.month > 2)) {
00169
00170 ts += SECONDSINADAY;
00171 }
00172 ts += SECONDSINADAY * (datetime.date.dayofmonth - 1);
00173 ts += 3600UL * datetime.time.hour;
00174 ts += 60 * datetime.time.minute;
00175 ts += datetime.time.second;
00176
00177 output[0] = (ts >> 24);
00178 output[1] = (ts >> 16);
00179 output[2] = (ts >> 8);
00180 output[3] = (ts >> 0);
00181 break;
00182 default:
00183 break;
00184 }
00185 }
00186
00191 void setWaiting(void) {
00192 static uint8_t position = 0;
00193 output[0] = 0;
00194 output[1] = 0;
00195 output[2] = 0;
00196 output[3] = 0;
00197 if (position < 8) {
00198 output[0] = (1 << position);
00199 } else if (position == 8) {
00200 output[1] = 128;
00201 } else if (position == 9) {
00202 output[2] = 128;
00203 } else if (position == 18) {
00204 output[2] = 1;
00205 } else if (position == 19) {
00206 output[1] = 1;
00207 } else {
00208 output[3] = (128 >> (position - 10));
00209 }
00210 position++;
00211 if (position > 19) {
00212 position = 0;
00213 }
00214 }
00215
00220 void timerInterrupt(void) {
00221 dcf_datetime datetime;
00222 static uint8_t tickcounter;
00223 static uint8_t keycounter = 0;
00224 static uint8_t demomodecounter = 0;
00225 static uint8_t modeswitched = 0;
00227 tickcounter++;
00228
00229
00230 if (tickcounter % 2) {
00231 if ((PINC & (1 << PINC0))) {
00232
00233 dcf_signal(True);
00234 PORTC |= (1 << PINC1);
00235 } else {
00236
00237 dcf_signal(False);
00238 PORTC &= ~(1 << PINC1);
00239 }
00240 }
00241
00242
00243
00244 if (tickcounter % 32 == 0) {
00245 if (!(PINC & (1 << PINC2))) {
00246
00247 keycounter++;
00248 if (keycounter > 2) {
00249
00250 keycounter = 0;
00251 mode++;
00252 if (mode > timestamp) {
00253 mode = timeasbinary;
00254 }
00255 modeswitched = 5;
00256 }
00257 demomodecounter++;
00258 if (demomodecounter > 75) {
00259
00260 if (demomode == 0) {
00261 demomode = 1;
00262 mode = timeasbinary;
00263 output[0] = 255;
00264 output[1] = 255;
00265 output[2] = 255;
00266 output[3] = 255;
00267 } else {
00268 demomode = 0;
00269 mode = timeasbinary;
00270 output[0] = 255;
00271 output[1] = 129;
00272 output[2] = 129;
00273 output[3] = 255;
00274 }
00275 setLeds();
00276 demomodecounter = 0;
00277 }
00278 } else {
00279
00280 keycounter = 0;
00281 demomodecounter = 0;
00282 }
00283 }
00284
00285
00286
00287 if (tickcounter % 128 == 0) {
00288 if (demomode == 1) {
00289
00290
00291 datetime.is_valid = 1;
00292 datetime.time.hour = 23;
00293 datetime.time.minute = 49;
00294 datetime.time.second = 57;
00295 datetime.date.dayofmonth = 31;
00296 datetime.date.month = 12;
00297 datetime.date.year = 6;
00298 datetime.date.dayofweek = 7;
00299 } else {
00300 datetime = dcf_current_datetime();
00301 }
00302 if (modeswitched > 0) {
00303 output[0] = mode + 1;
00304 output[1] = mode + 1;
00305 output[2] = mode + 1;
00306 output[3] = mode + 1;
00307 modeswitched--;
00308 } else if (datetime.is_valid) {
00309 setOutput(datetime);
00310 } else {
00311 setWaiting();
00312 }
00313
00314 setLeds();
00315 }
00316 }
00317
00323 int main(void) {
00324 uint8_t i;
00325
00326
00327 mode = timeasbinary;
00328
00329
00330 DDRC = (1 << DDC1);
00331 PORTC = (1 << PC1) | (1 << PC2);
00332
00333
00334 led_init();
00335 set_led_brightness(1);
00336 for (i = 0; i <= 3; i++) {
00337 set_led_digit(i, 0);
00338 }
00339
00340
00341 dcf_init();
00342
00343
00344 TCCR0 = (0 << CS02) | (1 << CS01) | (0 << CS00);
00345
00346
00347
00348 sei();
00349
00350 while (1) {
00351 if (TIFR & (1 << TOV0)) {
00352 TIFR |= 1 << TOV0;
00353 timerInterrupt();
00354 }
00355 }
00356 return 0;
00357 }