summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ac.bat25
-rw-r--r--clock.c88
-rw-r--r--clock.h16
-rw-r--r--dcf77.c100
-rw-r--r--dcf77.h5
-rw-r--r--main.c46
-rw-r--r--main.h20
-rw-r--r--max7219.c133
-rw-r--r--max7219.h51
-rw-r--r--timebase.c61
-rw-r--r--timebase.h13
-rw-r--r--types.h23
12 files changed, 581 insertions, 0 deletions
diff --git a/ac.bat b/ac.bat
new file mode 100644
index 0000000..122be97
--- /dev/null
+++ b/ac.bat
@@ -0,0 +1,25 @@
+@echo off
+set platz=
+set platz1=
+
+:set mcu=90s2313
+set mcu=tiny26
+:set mcu=mega8
+set main=test
+
+set ac=c:\avr\winavr
+path %ac%\bin;%path%
+avr-gcc.exe -xc -Os -mmcu=at%mcu% -Wall -g -o main.out *.c >l
+if not exist main.out goto end
+cmd /c avr-objdump.exe -t -h -S main.out >%main%.lst
+cmd /c avr-objcopy.exe -O ihex main.out %main%.hex
+avr-size.exe -B main.out
+del main.out
+goto end
+
+::pause
+call pf.bat %main%
+::if errorlevel 1 goto end
+::pause
+::l -b19200 -i- -c1
+:end
diff --git a/clock.c b/clock.c
new file mode 100644
index 0000000..e6fba14
--- /dev/null
+++ b/clock.c
@@ -0,0 +1,88 @@
+/************************************************************************/
+/* */
+/* Clock / Calendar */
+/* */
+/* Author: Peter Dannegger */
+/* danni@specs.de */
+/* */
+/************************************************************************/
+
+#include "main.h"
+#include "clock.h"
+#include "max7219.h"
+#include "timebase.h"
+#include "dcf77.h"
+
+struct time data time;
+
+
+void display_date( void )
+{
+ displaymem[7] = time.day / 10;
+ displaymem[6] = time.day % 10 | ATTRIB_DP;
+ displaymem[5] = time.month / 10;
+ displaymem[4] = time.month % 10 | ATTRIB_DP;
+ displaymem[3] = 2;
+ displaymem[2] = 0;
+ displaymem[1] = time.year / 10;
+ displaymem[0] = time.year % 10;
+}
+
+
+void display_time(void)
+{
+ displaymem[7] = time.hour / 10;
+ displaymem[6] = time.hour % 10;
+
+ displaymem[4] = time.minute / 10;
+ displaymem[3] = time.minute % 10;
+
+ displaymem[1] = time.second / 10;
+ displaymem[0] = time.second % 10;
+}
+
+
+u8 code MDAYS[] = {
+ 29, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+
+void clock(void)
+{
+ u8 i;
+
+ time.second++;
+ if( time.second == 60 ){
+ time.second = 0;
+ timeflags = 1<<ONE_MINUTE; // to correct deviation per minute
+ time.minute++;
+ if( time.minute == 60 ){
+ time.minute = 0;
+ time.hour++;
+ switch( time.hour ){
+ case 24:
+ time.hour = 0;
+ time.day++;
+ time.wday++;
+ if( time.wday == 8 )
+ time.wday = 1;
+ i = time.month;
+ if( i == 2 && (time.year & 3) == 0 ) // leap year
+ i = 0;
+ if( LPM(MDAYS+1) == time.day ){
+ time.day = 1;
+ time.month++;
+ if( time.month == 13 ){
+ time.month = 1;
+ time.year++;
+ if( time.year == 100 )
+ time.year = 0; // next century
+ }
+ }
+ break;
+// case 2:
+// case 3: summertime(); break;
+ }
+ }
+ }
+}
+
diff --git a/clock.h b/clock.h
new file mode 100644
index 0000000..35eaa5a
--- /dev/null
+++ b/clock.h
@@ -0,0 +1,16 @@
+
+struct time {
+ u8 second;
+ u8 minute;
+ u8 hour;
+ u8 day;
+ u8 wday;
+ u8 month;
+ u8 year;
+};
+
+extern struct time time;
+
+void display_date(void);
+void display_time(void);
+void clock( void );
diff --git a/dcf77.c b/dcf77.c
new file mode 100644
index 0000000..91ae618
--- /dev/null
+++ b/dcf77.c
@@ -0,0 +1,100 @@
+/************************************************************************/
+/* */
+/* Decode DCF77 Time Information */
+/* */
+/* Author: Peter Dannegger */
+/* danni@specs.de */
+/* */
+/************************************************************************/
+
+
+#include "main.h"
+#include "clock.h"
+#include "timebase.h"
+#include "dcf77.h"
+
+
+ u8 code BITNO[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // minute
+ 0xFF, // parity
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, // hour
+ 0xFF, // parity
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, // day
+ 0x30, 0x31, 0x32, // weekday
+ 0x40, 0x41, 0x42, 0x43, 0x44, // month
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, // year
+ 0xFF }; // parity
+ u8 code BMASK[] = { 1, 2, 4, 8, 10, 20, 40, 80 };
+
+
+struct time newtime;
+
+u8 dcf77error = 0;
+u8 synchronize = 0; // successful recieved
+
+
+void decode_dcf77( u8 pulse )
+{
+ static u8 parity = 0;
+ u8 i;
+ u8 *d;
+
+ i = newtime.second - 21;
+ if( i >= sizeof( BITNO )) // only bit 21 ... 58
+ return;
+ parity ^= pulse; // calculate parity
+ i = LPM(&BITNO[i]);
+ if( i == 0xFF ){ // test parity
+ if( parity )
+ dcf77error = 1;
+ parity = 0;
+ return;
+ }
+ d = (u8 *)&newtime.minute + (i >> 4); // byte address
+ i &= 0x0F; // bit number
+ if( i == 0 )
+ *d = 0; // clear all, if lsb
+ if( pulse )
+ *d += LPM(&BMASK[i]); // set bit
+}
+
+
+void scan_dcf77( void )
+{
+ if( dcf77_pulse ){
+ if( dcf77_pulse > 3 && dcf77_pulse < 8 ){
+ decode_dcf77( 0 );
+ }else{
+ if( dcf77_pulse > 10 && dcf77_pulse < 14 ){
+ decode_dcf77( 1 );
+ }else{
+ dcf77error = 1;
+ }
+ }
+ dcf77_pulse = 0;
+ }
+
+ if( dcf77_period ){
+ if( newtime.second < 60 )
+ newtime.second++;
+ if( dcf77_period > 120 && dcf77_period < 140 ){
+ if( dcf77error == 0 && newtime.second == 59 ){
+ synchronize = 0xFF;
+ sync_sec();
+ time.second = 0;
+ time.minute = newtime.minute;
+ time.hour = newtime.hour;
+ time.wday = newtime.wday;
+ time.day = newtime.day;
+ time.month = newtime.month;
+ time.year = newtime.year;
+ }
+ newtime.second = 0;
+ dcf77error = 0;
+ }else{
+ if( dcf77_period < 60 || dcf77_period > 70 )
+ dcf77error = 1;
+ }
+ dcf77_period = 0;
+ }
+}
diff --git a/dcf77.h b/dcf77.h
new file mode 100644
index 0000000..79c859f
--- /dev/null
+++ b/dcf77.h
@@ -0,0 +1,5 @@
+extern u8 dcf77error;
+extern u8 synchronize;
+
+
+void scan_dcf77( void );
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..f130906
--- /dev/null
+++ b/main.c
@@ -0,0 +1,46 @@
+#include "main.h"
+#include "max7219.h"
+#include "clock.h"
+#include "timebase.h"
+#include "dcf77.h"
+
+
+int main( void )
+{
+ PORTA = 0xFF; // enable pull ups
+ PORTB = 0xFF;
+ DDRA |= 1<<PA4;
+ display_init();
+ display_off();
+ timebase_init();
+ sei();
+ for(;;){
+ scan_dcf77();
+#if 1
+ if( DCF77_PIN & 1<<DCF77 )
+ PORTA |= 1<< PA4;
+ else
+ PORTA &= ~(1<<PA4);
+#endif
+ if( timeflags & 1<<ONE_SECOND ){
+ timeflags = 0;
+ clock();
+ if( synchronize == 0 )
+ continue;
+ if( synchronize == 1 && time.hour == 3 ){
+ if( time.minute == 20 )
+ display_off();
+ if( time.minute == 28 )
+ synchronize = 2;
+ continue;
+ }
+ if( time.hour == 4 )
+ synchronize = 1;
+
+ DDRA &= ~(1<<PA4);
+ display_clear();
+ display_time();
+ display_out();
+ }
+ }
+}
diff --git a/main.h b/main.h
new file mode 100644
index 0000000..28167f0
--- /dev/null
+++ b/main.h
@@ -0,0 +1,20 @@
+#include <io.h>
+#include <interrupt.h>
+#include <signal.h>
+#include "types.h"
+
+#define XTAL 12000000L
+
+
+// Hardware Definitions
+
+#define MAX7219_DDR DDRB
+#define MAX7219_PORT PORTB
+#define MAX7219_SCK PB2
+#define MAX7219_DO PB1
+#define MAX7219_STB PB3
+
+#define DCF77_PIN PINA
+#define DCF77_PORT PORTA
+#define DCF77_DDR DDRA
+#define DCF77 PA7
diff --git a/max7219.c b/max7219.c
new file mode 100644
index 0000000..a1e0da3
--- /dev/null
+++ b/max7219.c
@@ -0,0 +1,133 @@
+/************************************************************************/
+/* */
+/* 7 Segment Driver MAX7219 */
+/* Common Anode Display */
+/* */
+/* Author: Peter Dannegger */
+/* danni@specs.de */
+/* */
+/************************************************************************/
+
+#include "main.h"
+#include "max7219.h"
+
+u8 brightness = 5;
+
+u8 code digits[] = { DIGITS };
+
+u8 displaymem[8] = { CHAR_SPACE, // 8 digits, msb first
+ CHAR_SPACE,
+ CHAR_SPACE,
+ CHAR_SPACE,
+ CHAR_SPACE,
+ CHAR_SPACE,
+ CHAR_SPACE,
+ CHAR_SPACE };
+
+u8 code charset[] = { // Definition Character Set
+ _A+_B+_C+_D+_E+_F , // CHAR_0
+ _B+_C , // CHAR_1
+ _A+_B+ _D+_E+ _G, // CHAR_2
+ _A+_B+_C+_D+ _G, // CHAR_3
+ _B+_C+ _F+_G, // CHAR_4
+ _A+ _C+_D+ _F+_G, // CHAR_5
+ _A+ _C+_D+_E+_F+_G, // CHAR_6
+ _A+_B+_C , // CHAR_7
+ _A+_B+_C+_D+_E+_F+_G, // CHAR_8
+ _A+_B+_C+_D +_F+_G, // CHAR_9
+ _A+_B+_C+ _E+_F+_G, // CHAR_A
+ _C+_D+_E+_F+_G, // CHAR_b
+ _D+_E+ _G, // CHAR_c ;'c'
+ _B+_C+_D+_E+ _G, // CHAR_d
+ _A+ _D+_E+_F+_G, // CHAR_E
+ _A+ _E+_F+_G, // CHAR_F
+ 0 , // 16 = SPACE
+ _G, // 17 = MINUS
+ _A+_B+ _F+_G, // 18 = GRAD
+ _A+ _D+_E+_F , // 19 = CHAR_C2 ;'C'
+ _E+ _G, // 20 = CHAR_r
+ _C+_D+_E+ _G, // 21 = CHAR_o
+ _B+_C+ _E+_F+_G, // 22 = H
+ _D+_E+_F , // 23 = L
+ _D , // 24 = _
+ _A , // 25 = upper "-"
+ _A+_B+ _E+_F+_G, // CHAR_P
+ _B+_C+_D+_E+_F , // CHAR_U
+ _A+_B+_C+ _E+_F // CHAR_M
+ };
+
+
+void display_write( u16 dc )
+{
+ u8 i;
+
+ MAX7219_DDR |= 1<<MAX7219_DO;
+ MAX7219_DDR |= 1<<MAX7219_SCK;
+ MAX7219_DDR |= 1<<MAX7219_STB;
+ MAX7219_PORT &= ~(1<<MAX7219_STB);
+
+ for( i = 12; i; i-- ){
+ MAX7219_PORT &= ~(1<<MAX7219_SCK);
+ MAX7219_PORT |= 1<<MAX7219_DO;
+ if( (dc & 0x0800) == 0 )
+ MAX7219_PORT &= ~(1<<MAX7219_DO);
+ dc <<= 1;
+ MAX7219_PORT |= 1<<MAX7219_SCK;
+ }
+
+ MAX7219_PORT |= 1<<MAX7219_STB;
+}
+
+
+void display_out( void )
+{
+ u8 * dptr;
+ u8 i, j, byte;
+
+ display_write( 0xC01 );
+
+ dptr = displaymem;
+ for( i = 8; i; i-- ){
+ j = LPM(charset + (*dptr & 0x3F)); // convert to 7-segment
+ if( *dptr & 0x80 )
+ j |= _DP; // set decimal point
+ *dptr++ = j;
+ }
+
+ for( i = 8; i; i-- ){ // for all segments
+ dptr = displaymem;
+ byte = 0;
+ for( j = 8; j; j-- ){ // collect all digits
+ if( *dptr & 1 )
+ byte |= LPM(digits+j-1); // digit order mask
+ *dptr >>= 1; // next segment
+ dptr++;
+ }
+ display_write( byte + i * 256); // output same segments
+ }
+}
+
+
+void display_clear( void )
+{
+ u8 i;
+
+ for( i = 8; i; i--)
+ displaymem[i-1] = CHAR_SPACE;
+}
+
+
+void display_init( void )
+{
+ display_write( 0xF00 ); // Testmode off
+ display_write( 0x900 ); // Decode off
+ display_write( 0xB07 ); // 8 Digits
+ display_write( 0xC01 ); // Display on
+ display_write( 0xA00 | brightness ); // Brightness
+}
+
+
+void display_off( void )
+{
+ display_write( 0xC00 );
+}
diff --git a/max7219.h b/max7219.h
new file mode 100644
index 0000000..cfbb846
--- /dev/null
+++ b/max7219.h
@@ -0,0 +1,51 @@
+/************** Ansteuerung des 7-Segment-Treibers MAX7219 **************/
+
+#define BRIGHT 4 // 0 ... 15
+
+// Definitionen
+// 1. Display type
+#define COMMON_CATHODE
+//#define COMMON_ANODE // not implemented
+
+// 2. Pin-Deklaration
+//sbit DISCLK = 0x97; //BIT P1.7
+//sbit DISDAT = 0x95; //BIT P1.5
+//sbit DISSTB = 0x94; //BIT P1.4
+
+// 3. Segment-Order
+#define _A 0x01 // - A -
+#define _B 0x40 // | |
+#define _C 0x02 // F B
+#define _D 0x80 // | |
+#define _E 0x08 // - G -
+#define _F 0x04 // | |
+#define _G 0x10 // E C
+#define _DP 0x20 // | |
+ // - D - P
+#define DPBIT 7
+
+// 4. Digit-Order
+#define DIGITS 8, 128, 4, 16, 1, 32, 2, 64
+
+#define CHAR_SPACE 16
+#define CHAR_MINUS 17
+#define CHAR_GRAD 18
+#define CHAR_C2 19
+#define CHAR_R 20
+#define CHAR_O 21
+#define CHAR_H 22
+#define CHAR_L 23
+#define CHAR__ 24
+#define CHAR_S1 25 // upper "-"
+
+
+#define ATTRIB_DP 0x80 // decimal point attribute, must be ored
+#define ATTRIB_FLASH 0x40 // flash attribute, must be ored
+
+
+void display_init(void);
+void display_out(void);
+void display_clear(void);
+void display_off(void);
+
+extern u8 displaymem[];
diff --git a/timebase.c b/timebase.c
new file mode 100644
index 0000000..3b97e2b
--- /dev/null
+++ b/timebase.c
@@ -0,0 +1,61 @@
+#include "main.h"
+#include "timebase.h"
+
+ // at 12MHz:
+#define T0COUNT (XTAL / 1024 / 64) // 183
+#define T0SECERR (XTAL - 1024L * 64 * T0COUNT) // 6912
+#define T0COUNTSEC (T0COUNT + T0SECERR / 1024) // 189
+#define T0MINERR (XTAL - 1024 * (63 * T0COUNT + T0COUNTSEC)) // 768
+#define T0COUNTMIN (T0COUNTSEC + (T0MINERR * 60 + 512) / 1024) // 234
+
+// 234 = 12000000 Hz
+// 233 = 12000017 Hz = 4s/month
+
+
+u8 timeflags;
+u8 dcf77_period;
+u8 dcf77_pulse;
+u8 ct_64Hz; // 64 Hz counter (4sec)
+
+
+void timebase_init( void )
+{
+ TCCR0 = 1<<CS02^1<<CS00; // prescale = 1024
+ TIMSK = 1<<TOIE0; // interrupt enable
+}
+
+
+SIGNAL (SIG_OVERFLOW0)
+{
+ static u8 dcf77_time, old_dcf77;
+ // DCF77 receive
+ if( dcf77_time != 0xFF ) // stop on 0xFF
+ dcf77_time++; // count ticks
+ if( (DCF77_PIN ^ old_dcf77) & 1<<DCF77 ){ // pin changed ?
+ old_dcf77 ^= 0xFF; // change old flag
+ if( old_dcf77 & 1<<DCF77 ){
+ dcf77_period = dcf77_time; // store ticks of period
+ dcf77_time = 0; // count next period
+ }else{
+ dcf77_pulse = dcf77_time; // store ticks of pulse
+ }
+ }
+ // time base 1 second
+ TCNT0 = (u16)(256 - T0COUNT); // reload per tick: -183
+ if( ++ct_64Hz & 0x3F ){ // 64 ticks = one second
+ timeflags = 1<<ONE_TICK; // one tick over
+ return;
+ }
+ TCNT0 = (u16)(256 - T0COUNTSEC); // reload per second: -189
+ if( timeflags & (1<< ONE_MINUTE ))
+ TCNT0 = (u16)(256 - T0COUNTMIN); // reload per minute: -234
+ timeflags = 1<<ONE_SECOND^1<<ONE_TICK; // one tick, one second over
+}
+
+
+void sync_sec( void ) // synchronize by DCF77
+{
+ TCNT0 = (u16)(256 - T0COUNTMIN);
+ ct_64Hz = 0;
+ timeflags = 0;
+}
diff --git a/timebase.h b/timebase.h
new file mode 100644
index 0000000..2525b0c
--- /dev/null
+++ b/timebase.h
@@ -0,0 +1,13 @@
+#define ONE_TICK 0
+#define ONE_SECOND 1
+#define ONE_MINUTE 2
+
+
+extern u8 timeflags;
+extern u8 dcf77_period;
+extern u8 dcf77_pulse;
+extern u8 ct_64Hz;
+
+
+void timebase_init( void );
+void sync_sec( void );
diff --git a/types.h b/types.h
new file mode 100644
index 0000000..a18a03b
--- /dev/null
+++ b/types.h
@@ -0,0 +1,23 @@
+#include<pgmspace.h>
+
+typedef unsigned char u8;
+typedef signed char s8;
+typedef unsigned short u16;
+typedef signed short s16;
+typedef unsigned long u32;
+typedef signed long s32;
+
+#define uchar unsigned char
+#define uint unsigned int
+
+
+// 8051 compatibility:
+
+#define code PROGMEM
+#define LPM(i) (__LPM_classic__(i))
+#define data
+#define idata
+#define pdata
+#define xdata
+
+#define bit uchar