diff options
Diffstat (limited to 'software')
-rw-r--r-- | software/.clang-format | 5 | ||||
-rw-r--r-- | software/.ycm_extra_conf.py | 26 | ||||
-rw-r--r-- | software/Makefile | 17 | ||||
-rwxr-xr-x | software/inc/int/dcf77.c | 123 | ||||
-rwxr-xr-x | software/inc/int/dcf77.h | 68 | ||||
-rw-r--r-- | software/main.c | 129 |
6 files changed, 368 insertions, 0 deletions
diff --git a/software/.clang-format b/software/.clang-format new file mode 100644 index 0000000..b8ecd2e --- /dev/null +++ b/software/.clang-format | |||
@@ -0,0 +1,5 @@ | |||
1 | BasedOnStyle: Webkit | ||
2 | IndentWidth: 2 | ||
3 | BreakBeforeBraces: Allman | ||
4 | AllowShortIfStatementsOnASingleLine: false | ||
5 | ColumnLimit: 120 | ||
diff --git a/software/.ycm_extra_conf.py b/software/.ycm_extra_conf.py new file mode 100644 index 0000000..42834fb --- /dev/null +++ b/software/.ycm_extra_conf.py | |||
@@ -0,0 +1,26 @@ | |||
1 | import os | ||
2 | import ycm_core | ||
3 | |||
4 | def FlagsForFile( filename, **kwargs ): | ||
5 | return { | ||
6 | 'flags': [ | ||
7 | '-Wall', | ||
8 | '-Wextra', | ||
9 | '-Werror', | ||
10 | '-Wno-long-long', | ||
11 | '-Wno-variadic-macros', | ||
12 | '-fexceptions', | ||
13 | '-ferror-limit=10000', | ||
14 | '-DNDEBUG', | ||
15 | '-std=c99', | ||
16 | '-x', 'c', | ||
17 | '-D_GNU_SOURCE', | ||
18 | '-D__AVR_ATtiny85__', | ||
19 | '-D__AVR__', | ||
20 | '-I.', | ||
21 | '-I', '/usr/avr/include/' | ||
22 | ], | ||
23 | 'do_cache': True, | ||
24 | } | ||
25 | |||
26 | # vim:set et sw=2 ts=2 tw=120: | ||
diff --git a/software/Makefile b/software/Makefile new file mode 100644 index 0000000..e81f5a1 --- /dev/null +++ b/software/Makefile | |||
@@ -0,0 +1,17 @@ | |||
1 | FLAGS=-Wall -O5 -Werror | ||
2 | FLAGS+=-mmcu=attiny85 | ||
3 | FLAGS+=-D__AVR_ATtiny85__=1 | ||
4 | # FLAGS+=-DF_CPU=120000UL | ||
5 | # FLAGS+=-DF_CPU=960000UL | ||
6 | FLAGS+=-DF_CPU=800000UL | ||
7 | FLAGS+=-I inc/int/ | ||
8 | FLAGS+=-I/usr/lib/gcc/avr/6.3.0/plugin/include/ | ||
9 | FLAGS+=-I/usr/avr/include | ||
10 | |||
11 | program: all | ||
12 | avrdude -V -B100 -p t85 -c avrisp2 -P usb -U flash:w:main.hex | ||
13 | |||
14 | all: | ||
15 | avr-gcc $(FLAGS) -o main.elf main.c inc/int/dcf77.c | ||
16 | avr-objcopy -j .text -j .data -O ihex main.elf main.hex | ||
17 | |||
diff --git a/software/inc/int/dcf77.c b/software/inc/int/dcf77.c new file mode 100755 index 0000000..31f1663 --- /dev/null +++ b/software/inc/int/dcf77.c | |||
@@ -0,0 +1,123 @@ | |||
1 | // vim:set et sw=2 ts=2 tw=120: | ||
2 | #include "dcf77.h" | ||
3 | |||
4 | // 7372800/a=10000 | ||
5 | // 115200 / a * x = 10000 | ||
6 | // 7372800/8/150 | ||
7 | |||
8 | // returns -1 on error | ||
9 | unsigned char getBits(const DCF start, const char len) | ||
10 | { | ||
11 | static const unsigned char mult[] = {1, 2, 4, 8, 10, 20, 40, 80}; | ||
12 | /// unsigned char p = 1; //parity | ||
13 | unsigned char r = 0; // retval | ||
14 | unsigned char i; | ||
15 | for(i=0; i<len; i++) | ||
16 | r += dcf77[start+i].bit * mult[i]; | ||
17 | /// if(dcf77[start+i].bit) | ||
18 | /// p ^= 1; | ||
19 | return r; | ||
20 | } | ||
21 | |||
22 | // interrupt service routine (ISR) for timer 0 A compare match | ||
23 | ISR(TIMER0_COMPB_vect) | ||
24 | { | ||
25 | |||
26 | } | ||
27 | |||
28 | // ISR(TIMER0A_COMP_vect) | ||
29 | ISR(TIMER0_COMPA_vect) | ||
30 | { | ||
31 | interval++; | ||
32 | if (++t_current.ms >= 1000) // one second | ||
33 | { | ||
34 | t_current.ms = 0; // restart | ||
35 | if (++t_current.s > 59) // one minute | ||
36 | { | ||
37 | t_current.s = 0; // restart | ||
38 | if (++t_current.m > 59) // one hour | ||
39 | { | ||
40 | t_current.m = 0; // restart | ||
41 | if (++t_current.h > 23) // one day | ||
42 | { | ||
43 | t_current.h = 0; // restart | ||
44 | t_current.dd++; | ||
45 | } | ||
46 | } | ||
47 | } | ||
48 | } | ||
49 | } | ||
50 | |||
51 | ISR(INT0_vect) | ||
52 | { | ||
53 | } | ||
54 | |||
55 | ISR(PCINT0_vect) | ||
56 | { | ||
57 | // if(INT0_CONTROL == INT0_RISING_EDGE) | ||
58 | // if(MCUCR & (1<<ISC00)) | ||
59 | // { | ||
60 | if (interval > 1000 && interval < 2000) // 59th second - no rising edge at the beginning | ||
61 | { | ||
62 | if(dcf77_bit == 59) // check if every bit has been transfered | ||
63 | { | ||
64 | t_current.m = getBits(DCF_MIN, 7); | ||
65 | t_current.h = getBits(DCF_HOUR, 6); | ||
66 | t_current.dd = getBits(DCF_DAY, 6); | ||
67 | t_current.wd = getBits(DCF_WEEKDAY, 3); | ||
68 | t_current.mm = getBits(DCF_MONTH, 5); | ||
69 | t_current.yy = getBits(DCF_YEAR, 8); | ||
70 | } | ||
71 | |||
72 | // 59th second: synchronize with receiver... | ||
73 | dcf77_bit = 0; | ||
74 | t_current.s = 0; | ||
75 | t_current.ms = 0; | ||
76 | |||
77 | // falling edge causes interrupt... | ||
78 | // INT0_CONTROL = INT0_FALLING_EDGE; | ||
79 | } | ||
80 | else // INT0_FALLING_EDGE | ||
81 | { | ||
82 | if(interval > 50 && interval < 150) | ||
83 | dcf77[dcf77_bit++].bit = 0; | ||
84 | else if(interval > 150 && interval < 250) | ||
85 | dcf77[dcf77_bit++].bit = 1; | ||
86 | |||
87 | // rising edge causes interrupt... | ||
88 | // INT0_CONTROL = INT0_RISING_EDGE; | ||
89 | } | ||
90 | |||
91 | TCNT0 = 0; | ||
92 | interval = 0; | ||
93 | } | ||
94 | |||
95 | /* | ||
96 | void timer_init() | ||
97 | { | ||
98 | // 7372800/8 | ||
99 | // >>>>>> DDRD &= ~((1<<PD2) | (1<<PD3)); // make INT0 and INT1 input-pins | ||
100 | |||
101 | // Prescaler... | ||
102 | // output compare... | ||
103 | |||
104 | //OCR0 = 152 - 1; | ||
105 | //TCCR0 |= (0<<WGM01) | (1<<WGM01); | ||
106 | |||
107 | // ICNC1 (Input Capture Noise Canceler (4 CKs) Timer/Counter 1 | ||
108 | // ICES1 (Input Capture Edge Select Timer/Counter 1) - 1:increasing 0:falling | ||
109 | // CSx: set prescaler (010 means 8) | ||
110 | /// TCCR1B = (1<<ICNC1) | (1<<ICES1) | (0<<CS12) | (1<<CS11) | (0<<CS10); | ||
111 | // OCIE0: Output Compare Match Interrupt Enable | ||
112 | // TICIE: Timer/Counter Input Capture Interrupt Enable | ||
113 | |||
114 | // interrupts_init... | ||
115 | // General Interrupt Mask Register (enables interrupts) | ||
116 | GIMSK |= (1<<INT0); | ||
117 | // GICR |= (1<<INT0); | ||
118 | // MCU Control Register (controls CPU-behaviours like interrupts & sleepmode) | ||
119 | MCUCR |= (1<<ISC01) | (1<<ISC00); // any logical change generates interrupt | ||
120 | INT0_CONTROL = INT0_RISING_EDGE; // going to toggle int0-behaviour | ||
121 | /// loworhigh.bit = 0; | ||
122 | } | ||
123 | */ | ||
diff --git a/software/inc/int/dcf77.h b/software/inc/int/dcf77.h new file mode 100755 index 0000000..2d79cdd --- /dev/null +++ b/software/inc/int/dcf77.h | |||
@@ -0,0 +1,68 @@ | |||
1 | #ifndef CLOCK_H | ||
2 | #define CLOCK_H | ||
3 | /* this dcf77-module relies on a accuarate clock (crystal) for receiving | ||
4 | * the dcf-signal. therefor the clock is going to work as expected, | ||
5 | * even with no dcf77-signal available. | ||
6 | * receivement is automatically turned on, if the avr is connected to the | ||
7 | * signal via INT0. if there is no signal the clock will not be set (K.I.S.S.) | ||
8 | * | ||
9 | */ | ||
10 | #include <avr/io.h> | ||
11 | #include <avr/interrupt.h> | ||
12 | #include <stdint.h> | ||
13 | |||
14 | #define INT0_CONTROL MCUCR | ||
15 | // #define INT0_FALLING_EDGE 0x02 | ||
16 | // #define INT0_RISING_EDGE 0x03 | ||
17 | #define INT0_FALLING_EDGE (1<<ISC01) | ||
18 | #define INT0_RISING_EDGE (1<<ISC01 | 1<<ISC00) | ||
19 | #define INT0_EDGE_ANY (1<<ISC00) | ||
20 | |||
21 | typedef struct | ||
22 | { | ||
23 | volatile unsigned char bit : 1; | ||
24 | } Bit; | ||
25 | |||
26 | typedef struct | ||
27 | { | ||
28 | uint16_t h; // hour | ||
29 | uint16_t m; // minute | ||
30 | uint16_t s; // second | ||
31 | uint16_t ms; // milli second | ||
32 | uint8_t yy; // year | ||
33 | uint8_t mm; // month | ||
34 | uint8_t dd; // day | ||
35 | uint8_t wd; // weekday | ||
36 | } Time; | ||
37 | |||
38 | typedef enum | ||
39 | { | ||
40 | DCF_FIRST = 0, // start of a new minute (note: always 0) | ||
41 | DCF_WEATHER = 14, // proprietary :-( | ||
42 | DCF_ANTENNA = 15, // 0: normal, 1: replacement | ||
43 | DCF_DST = 16, // daylight saving time: this hour new time... | ||
44 | DCF_MEZ = 17, // 'summer-time' | ||
45 | DCF_MESZ = 18, // 'winter-time' | ||
46 | DCF_DBLSEC = 19, // one extra second gonna be inserted | ||
47 | DCF_START = 20, // begin of time-info (note: always 1) | ||
48 | DCF_MIN = 21, // 7 bit | ||
49 | DCF_MINP = 28, // parity bit for minutes | ||
50 | DCF_HOUR = 29, // 6 bit | ||
51 | DCF_HOURP = 35, // parity bit for hours | ||
52 | DCF_DAY = 36, // 6 bit | ||
53 | DCF_WEEKDAY = 42, // 3 bit | ||
54 | DCF_MONTH = 45, // 5 bit | ||
55 | DCF_YEAR = 50, // 8 bit | ||
56 | DCF_DATEP = 58 // parity bit for date | ||
57 | } DCF; | ||
58 | |||
59 | volatile Bit dcf77[60]; | ||
60 | volatile uint8_t dcf77_bit; | ||
61 | volatile Time t_current; | ||
62 | volatile uint16_t interval; | ||
63 | |||
64 | /// void getBits(volatile unsigned char* target, const DCF start, const char len, const DCF parity); | ||
65 | /// void set_dcf_value(); | ||
66 | /// void interrupts_init(); | ||
67 | |||
68 | #endif | ||
diff --git a/software/main.c b/software/main.c new file mode 100644 index 0000000..9e2cb5d --- /dev/null +++ b/software/main.c | |||
@@ -0,0 +1,129 @@ | |||
1 | // vim:set et sw=2 ts=2 tw=120: | ||
2 | #include <stdint.h> | ||
3 | #include <avr/io.h> | ||
4 | #include <avr/interrupt.h> | ||
5 | #include <util/delay.h> | ||
6 | |||
7 | #include "inc/int/dcf77.h" | ||
8 | |||
9 | #define CTC_MATCH_OVERFLOW ((F_CPU / 1000) / 8) | ||
10 | |||
11 | // set bit | ||
12 | static inline void BIT_SET(volatile uint8_t* target, uint8_t bit) __attribute__((always_inline)); | ||
13 | static inline void BIT_SET(volatile uint8_t* target, uint8_t bit) { *target |= (1 << bit); }; | ||
14 | |||
15 | // set clear | ||
16 | static inline void BIT_CLEAR(volatile uint8_t* target, uint8_t bit) __attribute__((always_inline)); | ||
17 | static inline void BIT_CLEAR(volatile uint8_t* target, uint8_t bit) { *target &= ~(1 << bit); }; | ||
18 | |||
19 | |||
20 | /* | ||
21 | * | ||
22 | * PB2 : connected to ShiftClock on Port 11 | ||
23 | * PB3 : connected to MemoryClock on Port 12 (shows content of memory) | ||
24 | * PB4 (PIN3) : connected to SERIAL_IN on pin 14 | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | void print_data(uint16_t data) | ||
29 | { | ||
30 | BIT_CLEAR(&PORTB, PB3); | ||
31 | for (char i = 0; i < 16; i++) | ||
32 | { | ||
33 | data & 0x1 << i | ||
34 | ? BIT_SET(&PORTB, PB4) | ||
35 | : BIT_CLEAR(&PORTB, PB4); | ||
36 | // pulse sck... | ||
37 | BIT_SET(&PORTB, PB2); | ||
38 | BIT_CLEAR(&PORTB, PB2); | ||
39 | } | ||
40 | BIT_SET(&PORTB, PB3); | ||
41 | } | ||
42 | |||
43 | int main(void) | ||
44 | { | ||
45 | |||
46 | BIT_CLEAR(&PORTB, PB5); | ||
47 | _delay_ms(20); | ||
48 | BIT_SET(&PORTB, PB5); | ||
49 | BIT_CLEAR(&PORTB, PB5); | ||
50 | _delay_ms(20); | ||
51 | BIT_SET(&PORTB, PB5); | ||
52 | |||
53 | |||
54 | |||
55 | // make all pins output pins... | ||
56 | // DDRB = 0xFF; | ||
57 | DDRB = 0b11111110; | ||
58 | PORTB |= 1<<PB0; // activate pullup | ||
59 | PORTB |= 1<<PB1; // activate receiver | ||
60 | PORTB &= ~(1<<PB1); | ||
61 | |||
62 | // DDRB &= ~(1 << PB0); // makes PB0 an input pin (INT0) | ||
63 | // PORTB |= (1 << PB0); // activate input resistor | ||
64 | |||
65 | // activate dcf77-receiver... | ||
66 | // PORTB &= (1 << PB1); // sets PB1 to low | ||
67 | // _delay_ms(20); | ||
68 | // PORTB &= ~(1 << PB1); // sets PB1 to low | ||
69 | |||
70 | |||
71 | cli(); | ||
72 | |||
73 | GIMSK |= (1<<INT0); // External Interrupt Request 0 Enable | ||
74 | GIMSK |= (1<<PCIE); // Pin Change Interrupt Enable | ||
75 | |||
76 | // MCU Control Register (controls CPU-behaviours like interrupts & sleepmode) | ||
77 | // MCUCR |= ~(1<<ISC01) | (1<<ISC00); // any logical change generates interrupt | ||
78 | PCMSK |= (1<<PCINT0); | ||
79 | // INT0_CONTROL = INT0_RISING_EDGE; // going to toggle int0-behaviour | ||
80 | |||
81 | TCCR0A |= (1 << WGM01); // CTC mode | ||
82 | // TCCR0B |= (1 << CS00); | ||
83 | TCCR0B |= (1 << CS01); // Prescaler 8 | ||
84 | // TCCR0B |= (1 << CS02); // Prescaler 256 | ||
85 | // OCR0A |= (1 << WGM01); // CTC mode | ||
86 | |||
87 | // OCR0A = 149; | ||
88 | OCR0A = 125; | ||
89 | // OCR0A = CTC_MATCH_OVERFLOW; | ||
90 | TIMSK |= (1 << OCIE0A); // if you want interrupt | ||
91 | |||
92 | sei(); | ||
93 | |||
94 | for(uint8_t i=0; i<16; i++) | ||
95 | { | ||
96 | print_data(3<<i); | ||
97 | _delay_ms(5); | ||
98 | } | ||
99 | |||
100 | while (1) | ||
101 | { | ||
102 | //print_data(lastinterval<<1 | (PINB & PB0)); | ||
103 | |||
104 | print_data( | ||
105 | (uint16_t) 0 | ||
106 | | ((uint16_t) (PINB & 0x0001))<<15 | ||
107 | | t_current.h<<8 | ||
108 | | t_current.m | ||
109 | ); | ||
110 | // print_data(interval | ((PINB & PB0) == 1 ? 2 : 0)); | ||
111 | //print_data(PINB); | ||
112 | } | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | |||
117 | /* | ||
118 | for(uint16_t hour=0; hour<24; hour++) | ||
119 | for(uint16_t minute=0; minute<60; minute++) | ||
120 | for (uint16_t second = 1; second < 60; second++) | ||
121 | { | ||
122 | // clear register (reset) | ||
123 | // print_data(hour<< 12 | minute << 6 | second); | ||
124 | // print_data((int64_t) dcf77); | ||
125 | // dcf77[dcf77_bit].bit == 1 | ||
126 | // ? print_data(0xFFFF) | ||
127 | // : print_data(0x0000); | ||
128 | }A | ||
129 | */ | ||