summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@diac24.net>2012-04-01 00:22:16 +0200
committerDavid Lamparter <equinox@diac24.net>2012-04-01 00:22:16 +0200
commit0a60a76afcf938c6885395fb16b6c168179921e5 (patch)
tree868d844830a6e7e588dde90faf144b78366b50c8
parent75a61c57fb0402f777bfa828dd71818a97ed54a4 (diff)
adapted to ATtiny26 / sublab setup
-rw-r--r--.gitignore3
-rw-r--r--Makefile19
-rw-r--r--clock.c27
-rw-r--r--clock.h4
-rw-r--r--lcd.c69
-rw-r--r--lcd.h16
-rw-r--r--main.c266
-rw-r--r--main.h15
-rw-r--r--max7219.c133
-rw-r--r--max7219.h51
-rw-r--r--timebase.c16
-rw-r--r--types.h7
12 files changed, 371 insertions, 255 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5ea87e6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.o
+*.elf
+*.*hex
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..38b4e72
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,19 @@
+.PHONY: love flash
+love: sublab77.ihex
+
+CFLAGS=-Wall -Wextra -pedantic -std=c99 -Os -DF_CPU=1000000 -mmcu=attiny26
+
+%.o: %.c
+ avr-gcc $(CFLAGS) -c -o $@ $<
+ifdef WHOPR
+sublab77.elf: main.c
+ avr-gcc $(CFLAGS) -DWHOPR -o $@ $^
+ avr-size $@
+else
+sublab77.elf: clock.o dcf77.o lcd.o main.o timebase.o
+ avr-gcc -Os -mmcu=attiny26 -o $@ $^
+ avr-size $@
+endif
+
+sublab77.ihex: sublab77.elf
+ objcopy -Oihex $^ $@
diff --git a/clock.c b/clock.c
index e6fba14..f40c6aa 100644
--- a/clock.c
+++ b/clock.c
@@ -9,39 +9,12 @@
#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 };
diff --git a/clock.h b/clock.h
index 35eaa5a..51a7a59 100644
--- a/clock.h
+++ b/clock.h
@@ -1,3 +1,5 @@
+#ifndef _CLOCK_H
+#define _CLOCK_H
struct time {
u8 second;
@@ -14,3 +16,5 @@ extern struct time time;
void display_date(void);
void display_time(void);
void clock( void );
+
+#endif /* _CLOCK_H */
diff --git a/lcd.c b/lcd.c
new file mode 100644
index 0000000..927b90f
--- /dev/null
+++ b/lcd.c
@@ -0,0 +1,69 @@
+#include "lcd.h"
+
+#include <avr/io.h>
+#include <util/delay.h>
+
+#define B_SRCLK PB0
+#define B_LCDE PB3
+#define B_SRD_LCDRS PB4
+
+static void lcd_pin(bool value)
+{
+ /* cheat, put the clock in front.
+ * result:
+ * clk, d0 | clk, d1 | clk... d7 | clk, rs.
+ * ^- first clk ignored ^- last clk from setting R/S
+ */
+ PORTB |= (1 << B_SRCLK);
+ PORTB &= ~(1 << B_SRCLK);
+
+ if (value)
+ PORTB |= (1 << B_SRD_LCDRS);
+ else
+ PORTB &= ~(1 << B_SRD_LCDRS);
+}
+
+void lcd_command(uint8_t cmd, bool isdata)
+{
+ uint8_t i;
+
+ for (i = 1; i; i <<= 2)
+ lcd_pin(cmd & i);
+ for (i = 1 << 7; i; i >>= 2)
+ lcd_pin(cmd & i);
+
+ lcd_pin(isdata);
+ __asm__ ("nop\n");
+ PORTB |= (1 << B_LCDE);
+ __asm__ ("nop\n");
+ PORTB &= ~(1 << B_LCDE);
+ __asm__ ("nop\n");
+ if (!isdata)
+ _delay_us(50);
+}
+
+void lcd_puts(const char * PROGMEM ptr, uint8_t cnt)
+{
+ while (cnt--) {
+ uint8_t ch = __LPM(ptr++);
+ lcd_put(ch);
+ }
+}
+
+const char PROGMEM boot[] = "boot";
+
+void lcd_init(void)
+{
+ PORTB &= ~((1 << B_SRCLK) | (1 << B_LCDE) | (1 << B_SRD_LCDRS));
+ DDRB |= (1 << B_SRCLK) | (1 << B_LCDE) | (1 << B_SRD_LCDRS);
+ _delay_ms(15);
+
+ lcd_command(0x38, 0);
+ lcd_command(0x0c, 0);
+ lcd_command(0x06, 0);
+ lcd_command(0x02, 0);
+ _delay_ms(2);
+
+ lcd_line1();
+ lcd_puts(boot, sizeof(boot) - 1);
+}
diff --git a/lcd.h b/lcd.h
new file mode 100644
index 0000000..333856d
--- /dev/null
+++ b/lcd.h
@@ -0,0 +1,16 @@
+#ifndef _LCD_H
+#define _LCD_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/pgmspace.h>
+
+extern void lcd_init(void);
+extern void lcd_command(uint8_t cmd, bool isdata);
+extern void lcd_puts(const char * PROGMEM ptr, uint8_t cnt);
+
+#define lcd_put(ch) lcd_command(ch, 1)
+#define lcd_line1() lcd_command(0x80, 0)
+#define lcd_line2() lcd_command(0xc0, 0)
+
+#endif /* _LCD_H */
diff --git a/main.c b/main.c
index f130906..cd9666a 100644
--- a/main.c
+++ b/main.c
@@ -1,46 +1,260 @@
#include "main.h"
-#include "max7219.h"
#include "clock.h"
#include "timebase.h"
#include "dcf77.h"
+#include "lcd.h"
+#include <avr/sleep.h>
+#include <avr/eeprom.h>
+#include <util/delay.h>
+
+#ifdef WHOPR
+#include "clock.c"
+#include "timebase.c"
+#include "dcf77.c"
+#include "lcd.c"
+#endif
+
+#define B_SW_BACK PINB5
+#define B_SW_FRWD PINB6
+
+#define A_OCPL_A PA5
+#define A_OCPL_B PA6
+
+#define EE_HOUR 0
+#define EE_MINUTE 1
+#define EE_CKSUM 2
+#define EE_BOOTC 4
+
+static uint8_t ext_hour, ext_minute;
+static uint16_t bootcount;
+
+#define WAIT 64
+uint8_t waitctr = 0;
+enum stepstate {
+ STEP_INACTIVE = 0,
+ STEP_ACTIVE,
+} stepstate = STEP_INACTIVE;
+
+const char PROGMEM disp[2] = {'_', '+'};
+const char PROGMEM status[24] = "normalsync adj + adj - ";
+const char PROGMEM cksumfail[] = "cksum fail";
+
+static void puttwo(uint8_t arg)
+{
+ uint8_t b = '0', a = '0' + arg;
+ while (a > '9')
+ b++, a -= 10;
+ lcd_put(b);
+ lcd_put(a);
+}
+
+static void puttime(void)
+{
+ const char * PROGMEM msg;
+
+ lcd_line1();
+ puttwo(time.year);
+ puttwo(time.month);
+ puttwo(time.day);
+ lcd_put(' ');
+ puttwo(time.hour);
+ puttwo(time.minute);
+ puttwo(time.second);
+
+ lcd_line2();
+ msg = &status[0];
+ if (time.year <= 10)
+ msg = &status[6];
+ if (~PINB & (1 << B_SW_FRWD))
+ msg = &status[12];
+ if (~PINB & (1 << B_SW_BACK))
+ msg = &status[18];
+
+ lcd_puts(msg, 6);
+ lcd_put(__LPM(&disp[stepstate]));
+ puttwo(ext_hour);
+ puttwo(ext_minute);
+ lcd_put(' ');
+ puttwo(bootcount / 100);
+ puttwo(bootcount % 100);
+}
+
+static uint8_t setaccel;
+
+static void countfwd(void)
+{
+ cli();
+ ext_minute++;
+ if (ext_minute == 60) {
+ ext_minute = 0;
+ ext_hour++;
+ if (ext_hour == 12)
+ ext_hour = 0;
+ }
+ sei();
+}
+
+static void step_set(void)
+{
+ if (ext_minute & 1) {
+ PORTA &= ~(1 << A_OCPL_A);
+ } else {
+ PORTA &= ~(1 << A_OCPL_B);
+ }
+}
+
+static void step_end(void)
+{
+ PORTA |= (1 << A_OCPL_A);
+ PORTA |= (1 << A_OCPL_B);
+}
+
+static void perform(void)
+{
+ if (waitctr)
+ return;
+
+ step_end();
+
+ if (~PINB & (1 << B_SW_BACK)) {
+ waitctr = setaccel;
+ if (setaccel > 3)
+ setaccel--;
+ cli();
+ if (ext_minute)
+ ext_minute--;
+ else {
+ ext_minute = 59;
+ if (ext_hour)
+ ext_hour--;
+ else
+ ext_hour = 11;
+ }
+ sei();
+ return;
+ }
+ if (~PINB & (1 << B_SW_FRWD)) {
+ waitctr = setaccel;
+ if (setaccel > 3)
+ setaccel--;
+ countfwd();
+ return;
+ }
+ setaccel = WAIT;
+
+ if (time.year <= 10)
+ return;
+
+ PORTA &= ~(1 << PA2);
+
+ uint8_t hbuf, mbuf, hdelta;
+
+ cli();
+ hbuf = time.hour;
+ mbuf = time.minute;
+ sei();
+
+ if (hbuf >= 12)
+ hbuf -= 12;
+
+ switch (stepstate) {
+ case STEP_INACTIVE:
+ if (hbuf == ext_hour && mbuf <= ext_minute)
+ break;
+ hdelta = 11 + ext_hour - hbuf;
+ while (hdelta >= 12)
+ hdelta -=12;
+ if (hdelta < 3)
+ break;
+ countfwd();
+
+ step_set();
+ stepstate = STEP_ACTIVE;
+ waitctr = WAIT;
+ break;
+ case STEP_ACTIVE:
+ stepstate = STEP_INACTIVE;
+ waitctr = WAIT;
+ break;
+ }
+}
+
+extern void __vectors(void) __attribute__((noreturn));
+__attribute__ ((noreturn))
+SIGNAL (SIG_ANA_COMP)
+{
+ PORTA = 0xff;
+
+ eeprom_write_byte((void *)EE_HOUR, ext_hour);
+ eeprom_write_byte((void *)EE_MINUTE, ext_minute);
+ eeprom_write_byte((void *)EE_CKSUM, ext_hour ^ ext_minute ^ 0xff);
+
+ do
+ _delay_ms(100);
+ while (ACSR & (1 << ACO));
+ __vectors();
+}
int main( void )
{
+
PORTA = 0xFF; // enable pull ups
PORTB = 0xFF;
- DDRA |= 1<<PA4;
- display_init();
- display_off();
+ DDRA |= (1 << PA4) | (1 << PA3) | (1 << PA2) | (1 << A_OCPL_A) | (1 << A_OCPL_B);
+
+ MCUCR = 0;
+ ACSR = (1 << ACBG) | (1 << ACIS1) | (1 << ACIS0) | (1 << ACIE);
+ _delay_ms(1);
+ ACSR |= (1 << ACI);
+
timebase_init();
+ lcd_init();
+
+ ext_hour = eeprom_read_byte((void *)EE_HOUR);
+ ext_minute = eeprom_read_byte((void *)EE_MINUTE);
+ uint8_t ec = eeprom_read_byte((void *)EE_CKSUM);
+
+ if ((ec ^ ext_hour ^ ext_minute) != 0xff) {
+ lcd_puts(cksumfail, sizeof(cksumfail) - 1);
+ while (1)
+ ;
+ }
+
+ bootcount = eeprom_read_word((void *)EE_BOOTC);
+ eeprom_write_word((void *)EE_BOOTC, ++bootcount);
+
+ /* last pulse may not have been long enough */
+ step_set();
+ _delay_ms(1000);
+ step_end();
+
sei();
+
for(;;){
+ bool do_puttime = false;
+
scan_dcf77();
#if 1
if( DCF77_PIN & 1<<DCF77 )
- PORTA |= 1<< PA4;
+ PORTA |= 1<< PA3;
else
- PORTA &= ~(1<<PA4);
+ PORTA &= ~(1<<PA3);
#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();
- }
+ if( timeflags & 1<<ONE_SECOND ){
+ timeflags = 0;
+ clock();
+ do_puttime = true;
+ }
+
+ if (!waitctr) {
+ perform();
+ do_puttime = true;
+ }
+
+ if (do_puttime)
+ puttime();
+/* sleep_enable();
+ sleep_cpu(); */
}
}
diff --git a/main.h b/main.h
index 28167f0..0fdba17 100644
--- a/main.h
+++ b/main.h
@@ -1,20 +1,13 @@
-#include <io.h>
-#include <interrupt.h>
-#include <signal.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
#include "types.h"
-#define XTAL 12000000L
+#define XTAL 1000000L
// 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
+#define DCF77 PA1
diff --git a/max7219.c b/max7219.c
deleted file mode 100644
index a1e0da3..0000000
--- a/max7219.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/************************************************************************/
-/* */
-/* 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
deleted file mode 100644
index cfbb846..0000000
--- a/max7219.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/************** 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
index 3b97e2b..ee58bf1 100644
--- a/timebase.c
+++ b/timebase.c
@@ -24,6 +24,7 @@ void timebase_init( void )
TIMSK = 1<<TOIE0; // interrupt enable
}
+extern uint8_t waitctr;
SIGNAL (SIG_OVERFLOW0)
{
@@ -31,7 +32,7 @@ SIGNAL (SIG_OVERFLOW0)
// DCF77 receive
if( dcf77_time != 0xFF ) // stop on 0xFF
dcf77_time++; // count ticks
- if( (DCF77_PIN ^ old_dcf77) & 1<<DCF77 ){ // pin changed ?
+ 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
@@ -40,16 +41,19 @@ SIGNAL (SIG_OVERFLOW0)
dcf77_pulse = dcf77_time; // store ticks of pulse
}
}
+
+ if (waitctr)
+ waitctr--;
// 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;
+ } else {
+ 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
}
- 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
}
diff --git a/types.h b/types.h
index a18a03b..eb9fb05 100644
--- a/types.h
+++ b/types.h
@@ -1,4 +1,7 @@
-#include<pgmspace.h>
+#ifndef _TYPES_H
+#define _TYPES_H
+
+#include <avr/pgmspace.h>
typedef unsigned char u8;
typedef signed char s8;
@@ -21,3 +24,5 @@ typedef signed long s32;
#define xdata
#define bit uchar
+
+#endif /* _TYPES_H */