Imported initial code by Doug Jackson (slightly modified by Admar).

This commit is contained in:
Paul van Tilburg 2011-10-30 22:27:58 +01:00
commit ffb1770e28
8 changed files with 2116 additions and 0 deletions

273
libraries/ds1302/DS1302.cpp Normal file
View File

@ -0,0 +1,273 @@
#include "WProgram.h"
#include "DS1302.h"
/*** Time definitions ***/
Time::Time(uint16_t yr, uint8_t mon, uint8_t date,
uint8_t hr, uint8_t min, uint8_t sec,
uint8_t day)
{
this->yr = yr;
this->mon = mon;
this->date = date;
this->hr = hr;
this->min = min;
this->sec = sec;
this->day = day;
}
Time::Time()
{
Time(2000, 1, 1, 0, 0, 0, 7);
}
/*** DS1302 definitions ***/
DS1302::DS1302(uint8_t ce_pin, uint8_t io_pin, uint8_t sclk_pin)
{
_ce_pin = ce_pin;
_io_pin = io_pin;
_sclk_pin = sclk_pin;
pinMode(ce_pin, OUTPUT);
pinMode(sclk_pin, OUTPUT);
}
void DS1302::_write_out(uint8_t value)
{
pinMode(_io_pin, OUTPUT);
shiftOut(_io_pin, _sclk_pin, LSBFIRST, value);
}
uint8_t DS1302::_read_in()
{
uint8_t input_value = 0;
uint8_t bit = 0;
pinMode(_io_pin, INPUT);
for (int i = 0; i < 8; ++i) {
bit = digitalRead(_io_pin);
input_value |= (bit << i);
digitalWrite(_sclk_pin, HIGH);
delayMicroseconds(1);
digitalWrite(_sclk_pin, LOW);
}
return input_value;
}
uint8_t DS1302::_register_bcd_to_dec(reg_t reg, uint8_t high_bit)
{
uint8_t val = read_register(reg);
uint8_t mask = (1 << (high_bit + 1)) - 1;
val &= mask;
val = (val & 15) + 10 * ((val & (15 << 4)) >> 4);
return val;
}
uint8_t DS1302::_register_bcd_to_dec(reg_t reg)
{
return _register_bcd_to_dec(reg, 7);
}
void DS1302::_register_dec_to_bcd(reg_t reg, uint8_t value, uint8_t high_bit)
{
uint8_t regv = read_register(reg);
uint8_t mask = (1 << (high_bit + 1)) - 1;
/* convert value to bcd in place */
uint8_t tvalue = value / 10;
value = value % 10;
value |= (tvalue << 4);
/* replace high bits of value if needed */
value &= mask;
value |= (regv &= ~mask);
write_register(reg, value);
}
void DS1302::_register_dec_to_bcd(reg_t reg, uint8_t value)
{
_register_dec_to_bcd(reg, value, 7);
}
uint8_t DS1302::read_register(reg_t reg)
{
uint8_t cmd_byte = 129; /* 1000 0001 */
uint8_t reg_value;
cmd_byte |= (reg << 1);
digitalWrite(_sclk_pin, LOW);
digitalWrite(_ce_pin, HIGH);
_write_out(cmd_byte);
reg_value = _read_in();
digitalWrite(_ce_pin, LOW);
return reg_value;
}
void DS1302::write_register(reg_t reg, uint8_t value)
{
uint8_t cmd_byte = (128 | (reg << 1));
digitalWrite(_sclk_pin, LOW);
digitalWrite(_ce_pin, HIGH);
_write_out(cmd_byte);
_write_out(value);
digitalWrite(_ce_pin, LOW);
}
void DS1302::write_protect(bool enable)
{
write_register(WP_REG, (enable << 7));
}
void DS1302::halt(bool enable)
{
uint8_t sec = read_register(SEC_REG);
sec &= ~(1 << 7);
sec |= (enable << 7);
write_register(SEC_REG, sec);
}
/*** Get time ***/
uint8_t DS1302::seconds()
{
return _register_bcd_to_dec(SEC_REG, 6);
}
uint8_t DS1302::minutes()
{
return _register_bcd_to_dec(MIN_REG);
}
uint8_t DS1302::hour()
{
uint8_t hr = read_register(HR_REG);
uint8_t adj;
if (hr & 128) /* 12-hour mode */
adj = 12 * ((hr & 32) >> 5);
else /* 24-hour mode */
adj = 10 * ((hr & (32 + 16)) >> 4);
hr = (hr & 15) + adj;
return hr;
}
uint8_t DS1302::date()
{
return _register_bcd_to_dec(DATE_REG, 5);
}
uint8_t DS1302::month()
{
return _register_bcd_to_dec(MON_REG, 4);
}
uint8_t DS1302::day()
{
return _register_bcd_to_dec(DAY_REG, 2);
}
uint16_t DS1302::year()
{
return 2000 + _register_bcd_to_dec(YR_REG);
}
Time DS1302::time()
{
Time t;
t.sec = seconds();
t.min = minutes();
t.hr = hour();
t.date = date();
t.mon = month();
t.day = day();
t.yr = year();
return t;
}
/*** Set time ***/
void DS1302::seconds(uint8_t sec)
{
_register_dec_to_bcd(SEC_REG, sec, 6);
}
void DS1302::minutes(uint8_t min)
{
_register_dec_to_bcd(MIN_REG, min, 6);
}
void DS1302::hour(uint8_t hr)
{
write_register(HR_REG, 0); /* set 24-hour mode */
_register_dec_to_bcd(HR_REG, hr, 5);
}
void DS1302::date(uint8_t date)
{
_register_dec_to_bcd(DATE_REG, date, 5);
}
void DS1302::month(uint8_t mon)
{
_register_dec_to_bcd(MON_REG, mon, 4);
}
void DS1302::day(uint8_t day)
{
_register_dec_to_bcd(DAY_REG, day, 2);
}
void DS1302::year(uint16_t yr)
{
yr -= 2000;
_register_dec_to_bcd(YR_REG, yr);
}
void DS1302::time(Time t)
{
seconds(t.sec);
minutes(t.min);
hour(t.hr);
date(t.date);
month(t.mon);
day(t.day);
year(t.yr);
}

233
libraries/ds1302/DS1302.h Normal file
View File

@ -0,0 +1,233 @@
/*
Copyright (c) 2009, Matt Sparks
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
#ifndef DS1302_h
#define DS1302_h
#include "WProgram.h"
/**
* Convenience register constants
*/
#define SEC_REG 0
#define MIN_REG 1
#define HR_REG 2
#define DATE_REG 3
#define MON_REG 4
#define DAY_REG 5
#define YR_REG 6
#define WP_REG 7
/**
* Type for a register number
*/
typedef uint8_t reg_t;
/**
* Class representing a particular time and date.
*/
class Time
{
public:
uint8_t sec;
uint8_t min;
uint8_t hr;
uint8_t date;
uint8_t mon;
uint8_t day;
uint16_t yr;
/**
* Default constructor.
*
* Creates a time object dated to Saturday Jan 1, 2000 at 00:00:00.
* The date and time can be changed by editing the instance variables.
*/
Time();
/**
* Create a Time object with a given time.
*
* Args:
* yr: year. Range: {2000, ..., 2099}.
* mon: month. Range: {1, ..., 12}.
* date: date (of the month). Range: {1, ..., 31}.
* hr: hour. Range: {0, ..., 23}.
* min: minutes. Range: {0, ..., 59}.
* sec: seconds. Range: {0, ..., 59}.
* day: day of the week. Sunday is 1. Range: {1, ..., 7}.
*/
Time(uint16_t yr, uint8_t mon, uint8_t date,
uint8_t hr, uint8_t min, uint8_t sec,
uint8_t day);
};
/**
* Talk to a Dallas Semiconductor DS1302 Real Time Clock (RTC) chip.
*/
class DS1302
{
public:
/**
* Constructor.
*
* Args:
* ce_pin: CE pin number
* io_pin: IO pin number
* sclk_pin: SCLK pin number
*/
DS1302(uint8_t ce_pin, uint8_t io_pin, uint8_t sclk_pin);
/**
* Read register byte value.
*
* Args:
* reg: register number
*
* Returns:
* register value
*/
uint8_t read_register(reg_t reg);
/**
* Write byte into register.
*
* Args:
* reg: register number
* value: byte to write
*/
void write_register(reg_t reg, uint8_t value);
/**
* Enable or disable write protection on chip.
*
* Args:
* enable: true to enable, false to disable.
*/
void write_protect(bool enable);
/**
* Set or clear clock halt flag.
*
* Args:
* value: true to set halt flag, false to clear.
*/
void halt(bool value);
/**
* Get individual pieces of the time and date.
*/
uint8_t seconds();
uint8_t minutes();
uint8_t hour();
uint8_t date();
uint8_t month();
uint8_t day();
uint16_t year();
/**
* Get the current time and date in a Time object.
*
* Returns:
* Time object.
*/
Time time();
/**
* Individually set pieces of the date and time.
*
* The arguments here follow the rules specified above in Time::Time(...).
*/
void seconds(uint8_t sec);
void minutes(uint8_t min);
void hour(uint8_t hr);
void date(uint8_t date);
void month(uint8_t mon);
void day(uint8_t day);
void year(uint16_t yr);
/**
* Set the time and date to the instant specified in a given Time object.
*
* Args:
* t: Time object to use
*/
void time(Time t);
private:
uint8_t _ce_pin;
uint8_t _io_pin;
uint8_t _sclk_pin;
/**
* Shift out a value to the IO pin.
*
* Side effects: sets _io_pin as OUTPUT.
*
* Args:
* value: byte to shift out
*/
void _write_out(uint8_t value);
/**
* Read in a byte from the IO pin.
*
* Side effects: sets _io_pin to INPUT.
*
* Returns:
* byte read in
*/
uint8_t _read_in();
/**
* Get a binary-coded decimal register and return it in decimal.
*
* Args:
* reg: register number
* high_bit: number of the bit containing the last BCD value ({0, ..., 7})
*
* Returns:
* decimal value
*/
uint8_t _register_bcd_to_dec(reg_t reg, uint8_t high_bit);
uint8_t _register_bcd_to_dec(reg_t reg);
/**
* Set a register with binary-coded decimal converted from a given value.
*
* Args:
* reg: register number
* value: decimal value to convert to BCD
* high_bit: highest bit in the register allowed to contain BCD value
*/
void _register_dec_to_bcd(reg_t reg, uint8_t value, uint8_t high_bit);
void _register_dec_to_bcd(reg_t reg, uint8_t value);
};
#endif

View File

@ -0,0 +1,92 @@
/*
Example sketch for interfacing with the DS1302 timekeeping chip.
Copyright (c) 2009, Matt Sparks
All rights reserved.
http://quadpoint.org/projects/arduino-ds1302
*/
#include <stdio.h>
#include <string.h>
#include <DS1302.h>
/* Set the appropriate digital I/O pin connections */
uint8_t CE_PIN = 5;
uint8_t IO_PIN = 6;
uint8_t SCLK_PIN = 7;
/* Create buffers */
char buf[50];
char day[10];
/* Create a DS1302 object */
DS1302 rtc(CE_PIN, IO_PIN, SCLK_PIN);
void print_time()
{
/* Get the current time and date from the chip */
Time t = rtc.time();
/* Name the day of the week */
memset(day, 0, sizeof(day)); /* clear day buffer */
switch (t.day) {
case 1:
strcpy(day, "Sunday");
break;
case 2:
strcpy(day, "Monday");
break;
case 3:
strcpy(day, "Tuesday");
break;
case 4:
strcpy(day, "Wednesday");
break;
case 5:
strcpy(day, "Thursday");
break;
case 6:
strcpy(day, "Friday");
break;
case 7:
strcpy(day, "Saturday");
break;
}
/* Format the time and date and insert into the temporary buffer */
snprintf(buf, sizeof(buf), "%s %04d-%02d-%02d %02d:%02d:%02d",
day,
t.yr, t.mon, t.date,
t.hr, t.min, t.sec);
/* Print the formatted string to serial so we can see the time */
Serial.println(buf);
}
void setup()
{
Serial.begin(9600);
/* Initialize a new chip by turning off write protection and clearing the
clock halt flag. These methods needn't always be called. See the DS1302
datasheet for details. */
rtc.write_protect(false);
rtc.halt(false);
/* Make a new time object to set the date and time */
/* Tuesday, May 19, 2009 at 21:16:37. */
Time t(2009, 5, 19, 21, 16, 37, 3);
/* Set the time and date on the chip */
rtc.time(t);
}
/* Loop and print the time every second */
void loop()
{
print_time();
delay(1000);
}

244
wordclock/Dutch.h Normal file
View File

@ -0,0 +1,244 @@
/**************************************************************************
* *
* W O R D C L O C K - A clock that tells the time using words. *
* *
* DUTCH Language Support Functions *
* *
* Copyright (C) 2009,2010,2011 Doug Jackson (doug@doughq.com) *
* *
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
* MA 02111-1307 USA *
* *
***************************************************************************
*
* Revision History
* 20110315 DRJ Split off from Wordclock.pde to simplify modifying
* code for multiple languages
*/
// Display output pin assignments
#define MTEN Display1=Display1 | (1<<1); Serial.print("tien ");
#define HALF Display1=Display1 | (1<<2); Serial.print("half ");
#define PAST Display1=Display1 | (1<<3); Serial.print("over ");
#define THREE Display1=Display1 | (1<<4); Serial.print("drie ");
#define ITIS Display1=Display1 | (1<<5); Serial.print("het is ")
#define TO Display1=Display1 | (1<<7); Serial.print("voor ");
#define TWO Display2=Display2 | (1<<0); Serial.print("twee ");
#define SIX Display2=Display2 | (1<<1); Serial.print("zes ");
#define TWELVE Display2=Display2 | (1<<2); Serial.print("twaalf ");
#define HFIVE Display2=Display2 | (1<<3); Serial.print("vijf ");
#define SEVEN Display2=Display2 | (1<<4); Serial.print("zeven ");
#define HOUR Display2=Display2 | (1<<5); Serial.print("uur ");
#define ONE Display2=Display2 | (1<<6); Serial.print("een ");
#define QUARTER Display2=Display2 | (1<<7); Serial.print("kwart ");
#define EIGHT Display3=Display3 | (1<<0); Serial.print("acht ");
#define MFIVE Display3=Display3 | (1<<1); Serial.print("vijf ");
#define ELEVEN Display3=Display3 | (1<<3); Serial.print("elf ");
#define HTEN Display3=Display3 | (1<<4); Serial.print("tien ");
#define NINE Display3=Display3 | (1<<5); Serial.print("negen ");
#define FOUR Display3=Display3 | (1<<6); Serial.print("vier ");
#define LED1 Led1=1; Serial.print("MINLED 1 ")
#define LED2 Led2=1; Serial.print("2 ")
#define LED3 Led3=1; Serial.print("3 ")
#define LED4 Led4=1; Serial.print("4 ")
/*#define LED1 digitalWrite(LED1PIN,HIGH)
#define LED2 digitalWrite(LED2PIN,HIGH)
#define LED3 digitalWrite(LED3PIN,HIGH)
#define LED4 digitalWrite(LED4PIN,HIGH)*/
void selftest(void){
Serial.print("Selftest started");
// start by clearing the display to a known state
ledsoff(); ITIS; delay(500);
ledsoff(); MFIVE; delay(500);
ledsoff(); MTEN; delay(500);
ledsoff(); QUARTER; delay(500);
ledsoff(); PAST; delay(500);
ledsoff(); TO; delay(500);
ledsoff(); HALF; delay(500);
ledsoff(); ONE; delay(500);
ledsoff(); TWO; delay(500);
ledsoff(); THREE; delay(500);
ledsoff(); FOUR; delay(500);
ledsoff(); HFIVE; delay(500);
ledsoff(); SIX; delay(500);
ledsoff(); SEVEN; delay(500);
ledsoff(); EIGHT; delay(500);
ledsoff(); NINE; delay(500);
ledsoff(); HTEN; delay(500);
ledsoff(); ELEVEN; ; delay(500);
ledsoff(); TWELVE; delay(500);
ledsoff(); HOUR; delay(500);
ledsoff(); LED1; delay(500);
ledsoff(); LED2; delay(500);
ledsoff(); LED3; delay(500);
ledsoff(); LED4; delay(500);
Serial.println(" .. ok");
for(int i=0; i<5; i++)
{
Display1=255; Display2=255; Display3=255; LED1; LED2; LED3; LED4; delay(500);
ledsoff(); delay(500);
}
}
void displaytime(void){
// start by clearing the display to a known state
ledsoff();
// Now, turn on the "It is" leds
ITIS;
// now we display the appropriate minute counter
if ((minute>4) && (minute<10)) { MFIVE; PAST; }
if ((minute>9) && (minute<15)) { MTEN; PAST; }
if ((minute>14) && (minute<20)) { QUARTER; PAST; }
if ((minute>19) && (minute<25)) { MTEN; TO; HALF; }
if ((minute>24) && (minute<30)) { MFIVE; TO; HALF; }
if ((minute>29) && (minute<35)) { HALF; }
if ((minute>34) && (minute<40)) { MFIVE; PAST; HALF; }
if ((minute>39) && (minute<45)) { MTEN; PAST; HALF; }
if ((minute>44) && (minute<50)) { QUARTER; TO; }
if ((minute>49) && (minute<55)) { MTEN; TO; }
if (minute>54) { MFIVE; TO; }
if ((minute <5))
{
switch (hour) {
case 1:
case 13: ONE; break;
case 2:
case 14: TWO; break;
case 3:
case 15: THREE; break;
case 4:
case 16: FOUR; break;
case 5:
case 17: HFIVE; break;
case 6:
case 18: SIX; break;
case 7:
case 19: SEVEN; break;
case 8:
case 20: EIGHT; break;
case 9:
case 21: NINE; break;
case 10:
case 22: HTEN; break;
case 11:
case 23: ELEVEN; break;
case 0:
case 12:
case 24: TWELVE; break;
}
HOUR;
}
else
if ((minute < 20) && (minute >4))
{
switch (hour) {
case 1:
case 13: ONE; break;
case 2:
case 14: TWO; break;
case 3:
case 15: THREE; break;
case 4:
case 16: FOUR; break;
case 5:
case 17: HFIVE; break;
case 6:
case 18: SIX; break;
case 7:
case 19: SEVEN; break;
case 8:
case 20: EIGHT; break;
case 9:
case 21: NINE; break;
case 10:
case 22: HTEN; break;
case 11:
case 23: ELEVEN; break;
case 0:
case 12:
case 24: TWELVE; break;
}
}
else
{
// if we are greater than 34 minutes past the hour then display
// the next hour
switch (hour) {
case 1:
case 13: TWO; break;
case 14:
case 2: THREE; break;
case 15:
case 3: FOUR; break;
case 4:
case 16: HFIVE; break;
case 5:
case 17: SIX; break;
case 6:
case 18: SEVEN; break;
case 7:
case 19: EIGHT; break;
case 8:
case 20: NINE; break;
case 9:
case 21: HTEN; break;
case 10:
case 22: ELEVEN; break;
case 11:
case 23: TWELVE; break;
case 0:
case 12:
case 24: ONE; break;
}
}
// now we can illuminate the extra minute LEDs
if ((minute-(minute/5)*5)==1) { LED1; }
if ((minute-(minute/5)*5)==2) { LED1; LED2; }
if ((minute-(minute/5)*5)==3) { LED1; LED2; LED3; }
if ((minute-(minute/5)*5)==4) { LED1; LED2; LED3; LED4; }
// WriteLEDs();
}

277
wordclock/English.h Normal file
View File

@ -0,0 +1,277 @@
/**************************************************************************
* *
* W O R D C L O C K - A clock that tells the time using words. *
* *
* ELGLISH LANGUAGE SUPPORT FILE *
* *
* Hardware: Arduino Dumelove with a set of individual LEDs under a word *
* stencil. *
* *
* Copyright (C) 2009 Doug Jackson (doug@doughq.com) *
* *
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
* MA 02111-1307 USA *
* *
***************************************************************************
*
* Revision History
*
* Date By What
*/
// Display output pin assignments
#define MINUTES Display1=Display1 | (1<<0); Serial.print("Minutes ");
#define MTEN Display1=Display1 | (1<<1); Serial.print("ten ");
#define HALF Display1=Display1 | (1<<2); Serial.print("half ");
#define PAST Display1=Display1 | (1<<3); Serial.print("past ");
#define THREE Display1=Display1 | (1<<4); Serial.print("three ");
#define ITIS Display1=Display1 | (1<<5); Serial.print("It is ");
#define TWENTY Display1=Display1 | (1<<6); Serial.print("twenty ");
#define TO Display1=Display1 | (1<<7); Serial.print("to ");
#define TWO Display2=Display2 | (1<<0); Serial.print("two ");
#define SIX Display2=Display2 | (1<<1); Serial.print("six ");
#define TWELVE Display2=Display2 | (1<<2); Serial.print("twelve ");
#define HFIVE Display2=Display2 | (1<<3); Serial.print("five ");
#define SEVEN Display2=Display2 | (1<<4); Serial.print("seven ");
#define OCLOCK Display2=Display2 | (1<<5); Serial.print("oclock ");
#define ONE Display2=Display2 | (1<<6); Serial.print("one ");
#define QUARTER Display2=Display2 | (1<<7); Serial.print("quarter ");
#define EIGHT Display3=Display3 | (1<<0); Serial.print("eight ");
#define MFIVE Display3=Display3 | (1<<1); Serial.print("five ");
#define ELEVEN Display3=Display3 | (1<<3); Serial.print("eleven ");
#define HTEN Display3=Display3 | (1<<4); Serial.print("ten ");
#define NINE Display3=Display3 | (1<<5); Serial.print("nine ");
#define FOUR Display3=Display3 | (1<<6); Serial.print("four ");
#define WORD1 Display3=Display3 | (1<<7); Serial.print("word1 ");
#define WORD2 Display3=Display3 | (1<<2); Serial.print("word2 ");
#define WORD1OFF Display3=Display3 & ~(1<<7);
#define WORD2OFF Display3=Display3 & ~(1<<2);
#define LED1 Led1=1; Serial.print("MINLED 1 ")
#define LED2 Led2=1; Serial.print("2 ")
#define LED3 Led3=1; Serial.print("3 ")
#define LED4 Led4=1; Serial.print("4 ")
void selftest(void){
// start by clearing the display to a known state
ledsoff(); ITIS; delay(500);
ledsoff(); HALF; delay(500);
ledsoff(); MTEN; delay(500);
ledsoff(); QUARTER; delay(500);
ledsoff(); TWENTY; delay(500);
ledsoff(); MFIVE; delay(500);
ledsoff(); MINUTES; delay(500);
ledsoff(); TO; delay(500);
ledsoff(); PAST; delay(500);
ledsoff(); ONE; delay(500);
ledsoff(); THREE; delay(500);
ledsoff(); TWO; delay(500);
ledsoff(); FOUR; delay(500);
ledsoff(); HFIVE; delay(500);
ledsoff(); SIX; delay(500);
ledsoff(); SEVEN; delay(500);
ledsoff(); EIGHT; delay(500);
ledsoff(); NINE; delay(500);
ledsoff(); HTEN; delay(500);
ledsoff(); ELEVEN; delay(500);
ledsoff(); TWELVE; delay(500);
ledsoff(); OCLOCK; delay(500);
ledsoff(); WORD1; delay(500);
ledsoff(); WORD2; delay(500);
ledsoff(); LED1; delay(500);
ledsoff(); LED2; delay(500);
ledsoff(); LED3; delay(500);
ledsoff(); LED4; delay(500);
for(int i=0; i<5; i++)
{
Display1=255; Display2=255; Display3=255; delay(500);
ledsoff(); delay(500);
}
}
void displaytime(void){
// start by clearing the display to a known state
ledsoff();
// Now, turn on the "It is" leds
ITIS;
// now we display the appropriate minute counter
if ((minute>4) && (minute<10)) { MFIVE; MINUTES; }
if ((minute>9) && (minute<15)) { MTEN; MINUTES; }
if ((minute>14) && (minute<20)) { QUARTER; }
if ((minute>19) && (minute<25)) { TWENTY; MINUTES; }
if ((minute>24) && (minute<30)) { TWENTY; MFIVE; MINUTES; }
if ((minute>29) && (minute<35)) { HALF; }
if ((minute>34) && (minute<40)) { TWENTY; MFIVE; MINUTES; }
if ((minute>39) && (minute<45)) { TWENTY; MINUTES; }
if ((minute>44) && (minute<50)) { QUARTER; }
if ((minute>49) && (minute<55)) { MTEN; MINUTES; }
if (minute>54) { MFIVE; MINUTES; }
if ((minute <5))
{
switch (hour) {
case 1:
case 13: ONE; break;
case 2:
case 14: TWO; break;
case 3:
case 15: THREE; break;
case 4:
case 16: FOUR; break;
case 5:
case 17: HFIVE; break;
case 6:
case 18: SIX; break;
case 7:
case 19: SEVEN; break;
case 8:
case 20: EIGHT; break;
case 9:
case 21: NINE; break;
case 10:
case 22: HTEN; break;
case 11:
case 23: ELEVEN; break;
case 0:
case 12: TWELVE; break;
}
OCLOCK;
}
else
if ((minute < 35) && (minute >4))
{
PAST;
switch (hour) {
case 1:
case 13: ONE; break;
case 2:
case 14: TWO; break;
case 3:
case 15: THREE; break;
case 4:
case 16: FOUR; break;
case 5:
case 17: HFIVE; break;
case 6:
case 18: SIX; break;
case 7:
case 19: SEVEN; break;
case 8:
case 20: EIGHT; break;
case 9:
case 21: NINE; break;
case 10:
case 22: HTEN; break;
case 11:
case 23: ELEVEN; break;
case 0:
case 12: TWELVE; break;
}
}
else
{
// if we are greater than 34 minutes past the hour then display
// the next hour, as we will be displaying a 'to' sign
TO;
switch (hour) {
case 1:
case 13: TWO; break;
case 2:
case 14: THREE; break;
case 3:
case 15: FOUR; break;
case 4:
case 16: HFIVE; break;
case 5:
case 17: SIX; break;
case 6:
case 18: SEVEN; break;
case 7:
case 19: EIGHT; break;
case 8:
case 20: NINE; break;
case 9:
case 21: HTEN; break;
case 10:
case 22: ELEVEN; break;
case 11:
case 23: TWELVE; break;
case 0:
case 12: ONE; break;
}
}
// now we can illuminate the extra minute LEDs
if ((minute-(minute/5)*5)==1) { LED1; }
if ((minute-(minute/5)*5)==2) { LED1; LED2; }
if ((minute-(minute/5)*5)==3) { LED1; LED2; LED3; }
if ((minute-(minute/5)*5)==4) { LED1; LED2; LED3; LED4; }
if (( minute==0) && (second==0))
{
Serial.println("ALARM!!");
WORD1; delay(500);
WORD1OFF; delay(500);
WORD2; delay(500);
WORD2OFF; delay(500);
WORD1; delay(300);
WORD1OFF; delay(300);
WORD2; delay(300);
WORD2OFF; delay(300);
WORD1; delay(200);
WORD1OFF; delay(200);
WORD2; delay(200);
WORD2OFF; delay(200);
WORD1; delay(500);
WORD1OFF; delay(500);
WORD2; delay(500);
WORD2OFF; delay(500);
WORD1; delay(300);
WORD1OFF; delay(300);
WORD2; delay(300);
WORD2OFF; delay(300);
WORD1; delay(200);
WORD1OFF; delay(200);
WORD2; delay(200);
WORD2OFF; delay(200);
}
}

269
wordclock/French.h Normal file
View File

@ -0,0 +1,269 @@
/**************************************************************************
* *
* W O R D C L O C K - A clock that tells the time using words. *
* *
* FRENCH VERSION - thanks to Lionel Martin for testing *
* *
* *
* Hardware: Arduino Dumelove with a set of individual LEDs under a word *
* stencil. *
* Copyright (C) 2009,2010,2011 Doug Jackson (doug@doughq.com) *
* *
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
* MA 02111-1307 USA *
* *
***************************************************************************
*
* Revision History
*
* Date By What
* 20110310 DRJ Modified to French Language
*/
// Display output pin assignments
#define UNE Display1=Display1 | (1<<0); Serial.print("une ");
#define DEUX Display1=Display1 | (1<<1); Serial.print("duex ");
#define TROIS Display1=Display1 | (1<<2); Serial.print("trois ");
#define QUATRE Display1=Display1 | (1<<3); Serial.print("quatre ");
#define MCINQ Display1=Display1 | (1<<4); Serial.print("mcinq ");
#define SIX Display1=Display1 | (1<<5); Serial.print("six ");
#define SEPT Display1=Display1 | (1<<6); Serial.print("sept ");
#define HUIT Display1=Display1 | (1<<7); Serial.print("huit ");
#define NEUF Display2=Display2 | (1<<0); Serial.print("neuf ");
#define HDIX Display2=Display2 | (1<<1); Serial.print("hdix ");
#define MINUIT Display2=Display2 | (1<<2); Serial.print("minuit ");
#define MIDI Display2=Display2 | (1<<3); Serial.print("midi ");
#define ONZE Display2=Display2 | (1<<4); Serial.print("onze ");
#define HEURE Display2=Display2 | (1<<5); Serial.print("heure ");
#define S Display2=Display2 | (1<<6); Serial.print("s ");
#define MOINS Display2=Display2 | (1<<7); Serial.print("moins ");
#define LE Display3=Display3 | (1<<0); Serial.print("le ");
#define MDIX Display3=Display3 | (1<<1); Serial.print("mdix ");
#define ET Display3=Display3 | (1<<2); Serial.print("et ");
#define QUART Display3=Display3 | (1<<3); Serial.print("quart ");
#define VINGT Display3=Display3 | (1<<4); Serial.print("vingt ");
#define DASH Display3=Display3 | (1<<5); Serial.print("- ");
#define HCINQ Display3=Display3 | (1<<6); Serial.print("hcinq ");
#define DEMIE Display3=Display3 | (1<<7); Serial.print("demie ");
#define LED1 Led1=1; Serial.print("MINLED1 ")
#define LED2 Led2=1; Serial.print("2 ")
#define LED3 Led3=1; Serial.print("3 ")
#define LED4 Led4=1; Serial.print("4 ")
void selftest(void){
// start by clearing the display to a known state
ledsoff();
Serial.println("Start Self Test ");
UNE; delay(500); ledsoff();
DEUX; delay(500); ledsoff();
TROIS; delay(500); ledsoff();
QUATRE; delay(500); ledsoff();
MCINQ; delay(500); ledsoff();
SIX; delay(500); ledsoff();
SEPT; delay(500); ledsoff();
HUIT; delay(500); ledsoff();
NEUF; delay(500); ledsoff();
MDIX; delay(500); ledsoff();
MINUIT; delay(500); ledsoff();
MIDI; delay(500); ledsoff();
ONZE; delay(500); ledsoff();
HEURE; delay(500); ledsoff();
S; delay(500); ledsoff();
MOINS; delay(500); ledsoff();
LE; delay(500); ledsoff();
HDIX; delay(500); ledsoff();
ET; delay(500); ledsoff();
QUART; delay(500); ledsoff();
VINGT; delay(500); ledsoff();
DASH; delay(500); ledsoff();
HCINQ; delay(500); ledsoff();
DEMIE; delay(500); ledsoff();
LED1; delay(500); ledsoff();
LED2; delay(500); ledsoff();
LED3; delay(500); ledsoff();
LED4; delay(500);
Serial.println(" ");
for(int i=0; i<5; i++)
{
Display1=255;
Display2=255;
Display3=255;
delay(500);
ledsoff();
delay(500);
}
Serial.println("End Self Test");
}
void displaytime(void){
/**************************************************************************
Display is performed using word strings such as:
IL EST UNE HEURE - It is One O'clock
IL EST UNE HEURE ET DEMI - It is One thirty
IL EST TROIS HEURES - It is Three Thirty
IL EST QUATRE HEURES VINGT - It is Twenty minutes past Four
IL EST QUATRE HEURES MOINS VINGT - It is Twenty Minutes to Four
Display Logic:
HEURE is displayed when hours is Singular
S (After HEURE) is displayed when hours is plural - and not midday or midnight
MOINS is displayed between xx:35 and xx:59
CINQ is displayed at xx:05, xx:25, xx:35 and xx:55
- is displayed at xx:25 and xx:35
ET (before QUART) is displayed at xx:15
LE is displayed at xx:45
UNE is displayed between 01:00-01:59 and 13:00-13:59
DEUX is displayed between 02:00-02:59 and 14:00-14:59
TROIS is displayed between 03:00-03:59 and 15:00-15:59
QUATRE is displayed between 04:00-04:59 and 16:00-16:59
CINQ is displayed between 05:00-05:59 and 17:00-17:59
SIX is displayed between 06:00-06:59 and 18:00-18:59
SEPT is displayed between 07:00-09:59 and 19:00-19:59
HEUT is displayed between 08:00-09:59 and 20:00-20:59
NEUF is displayed between 09:00-09:59 and 21:00-21:59
DIX is displayed between 10:00-10:59 and 22:00-22:59
ONZE is displayed between 11:00-11:59 and 23:00-23:59
MIDI is displayed between 12:00-12:59
MINUIT is displayed between 00:00-00:59
DIX is displayed between xx:10-xx:14 and 0x:50-0x:54
QUART is displayed between xx:15-xx:19 and xx:45-xx:49
VINGT is displayed between xx:20-xx:29 and xx:35-xx:44
ET-DEMI is displayed between xx:30 and xx:34
*/
// start by clearing the display to a known state
ledsoff();
// IL-EST is hard wired to stay on as we only have 24 outputs
Serial.print("Il est ");
if ((minute>=0) && (minute<35)) switch (hour) {
case 1: UNE; HEURE; break;
case 2: DEUX; HEURE; S; break;
case 3: TROIS; HEURE; S; break;
case 4: QUATRE; HEURE; S; break;
case 5: HCINQ; HEURE; S; break;
case 6: SIX; HEURE; S; break;
case 7: SEPT; HEURE; S; break;
case 8: HUIT; HEURE; S; break;
case 9: NEUF; HEURE; S; break;
case 10: HDIX; HEURE; S; break;
case 11: ONZE; HEURE; S; break;
case 12: MIDI; break;
case 13: UNE; HEURE; break;
case 14: DEUX; HEURE; S; break;
case 15: TROIS; HEURE; S; break;
case 16: QUATRE; HEURE; S; break;
case 17: HCINQ; HEURE; S; break;
case 18: SIX; HEURE; S; break;
case 19: SEPT; HEURE; S; break;
case 20: HUIT; HEURE; S; break;
case 21: NEUF; HEURE; S; break;
case 22: HDIX; HEURE; S; break;
case 23: ONZE; HEURE; S; break;
case 00: MINUIT; break;
case 24: MINUIT; break;
}
else switch (hour) {
case 0: UNE; HEURE; break;
case 1: DEUX; HEURE; S; break;
case 2: TROIS; HEURE; S; break;
case 3: QUATRE; HEURE; S; break;
case 4: HCINQ; HEURE; S; break;
case 5: SIX; HEURE; S; break;
case 6: SEPT; HEURE; S; break;
case 7: HUIT; HEURE; S; break;
case 8: NEUF; HEURE; S; break;
case 9: HDIX; HEURE; S; break;
case 10: ONZE; HEURE; S; break;
case 11: MIDI; break;
case 12: UNE; HEURE; break;
case 13: DEUX; HEURE; S; break;
case 14: TROIS; HEURE; S; break;
case 15: QUATRE; HEURE; S; break;
case 16: HCINQ; HEURE; S; break;
case 17: SIX; HEURE; S; break;
case 18: SEPT; HEURE; S; break;
case 19: HUIT; HEURE; S; break;
case 20: NEUF; HEURE; S; break;
case 21: HDIX; HEURE; S; break;
case 22: ONZE; HEURE; S; break;
case 23: MINUIT; break;
}
// now we display the appropriate minute counter
if ((minute>4) && (minute<10)) { MCINQ; }
if ((minute>9) && (minute<15)) { MDIX; }
if ((minute>14) && (minute<20)) { ET; QUART; }
if ((minute>19) && (minute<25)) { VINGT; }
if ((minute>24) && (minute<30)) { VINGT; DASH; MCINQ; }
if ((minute>29) && (minute<35)) { ET; DEMIE; }
if ((minute>34) && (minute<40)) { MOINS; VINGT; DASH; MCINQ; }
if ((minute>39) && (minute<45)) { MOINS; VINGT; }
if ((minute>44) && (minute<50)) { MOINS; LE; QUART; }
if ((minute>49) && (minute<55)) { MOINS; MDIX; }
if ((minute>54) && (minute<60)) { MOINS; MCINQ; }
Serial.print(" ");
// now we can illuminate the extra minute LEDs
if ((minute-(minute/5)*5)==1) {
LED1;
}
if ((minute-(minute/5)*5)==2) {
LED1;
LED2;
}
if ((minute-(minute/5)*5)==3) {
LED1;
LED2;
LED3;
}
if ((minute-(minute/5)*5)==4) {
LED1;
LED2;
LED3;
LED4;
}
}

242
wordclock/German.h Normal file
View File

@ -0,0 +1,242 @@
/**************************************************************************
* *
* W O R D C L O C K - A clock that tells the time using words. *
* *
* GERMAN Language Support Functions *
* *
* Copyright (C) 2009,2010,2011 Doug Jackson (doug@doughq.com) *
* *
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
* MA 02111-1307 USA *
* *
***************************************************************************
*
* Revision History
* 20110315 DRJ Split off from Wordclock.pde to simplify modifying
* code for multiple languages
*/
// Display output pin assignments
#define ZENH Display1=Display1 | (1<<1); Serial.print("zenh ");
#define HALB Display1=Display1 | (1<<2); Serial.print("halb ");
#define NACH Display1=Display1 | (1<<3); Serial.print("nach ");
#define DREI Display1=Display1 | (1<<4); Serial.print("drei ");
#define ESIST Display1=Display1 | (1<<5); Serial.print("Es ist ");
#define ZWANZIG Display1=Display1 | (1<<6); Serial.print("zwanzig ");
#define VOR Display1=Display1 | (1<<7); Serial.print("vor ");
#define ZWEI Display2=Display2 | (1<<0); Serial.print("zwei ");
#define SECHS Display2=Display2 | (1<<1); Serial.print("sechs ");
#define ZWOLF Display2=Display2 | (1<<2); Serial.print("zwolf ");
#define HFUNF Display2=Display2 | (1<<3); Serial.print("funf ");
#define SIEBEN Display2=Display2 | (1<<4); Serial.print("sieben ");
#define UHR Display2=Display2 | (1<<5); Serial.print("uhr ");
#define ONE Display2=Display2 | (1<<6); Serial.print("ein ");
#define VIERTEL Display2=Display2 | (1<<7); Serial.print("viertel ");
#define ACHT Display3=Display3 | (1<<0); Serial.print("acht ");
#define MFUNF Display3=Display3 | (1<<1); Serial.print("funf ");
#define ELEVEN Display3=Display3 | (1<<3); Serial.print("elf ");
#define HZENH Display3=Display3 | (1<<4); Serial.print("zenh ");
#define NEUN Display3=Display3 | (1<<5); Serial.print("neun ");
#define VIER Display3=Display3 | (1<<6); Serial.print("vier ");
#define LED1 Led1=1; Serial.print("MINLED 1 ")
#define LED2 Led2=1; Serial.print("2 ")
#define LED3 Led3=1; Serial.print("3 ")
#define LED4 Led4=1; Serial.print("4 ")
void selftest(void){
Serial.print("Selftest started ");
// start by clearing the display to a known state
ledsoff(); ESIST; delay(500);
ledsoff(); MFUNF; delay(500);
ledsoff(); ZENH; delay(500);
ledsoff(); VIERTEL; delay(500);
ledsoff(); ZWANZIG; delay(500);
ledsoff(); NACH; delay(500);
ledsoff(); VOR; delay(500);
ledsoff(); HALB; delay(500);
ledsoff(); ELEVEN; ; delay(500);
ledsoff(); HFUNF; delay(500);
ledsoff(); ZWEI; delay(500);
ledsoff(); ONE; delay(500);
ledsoff(); VIER; delay(500);
ledsoff(); HZENH; delay(500);
ledsoff(); ZWOLF; delay(500);
ledsoff(); DREI; delay(500);
ledsoff(); NEUN; delay(500);
ledsoff(); ACHT; delay(500);
ledsoff(); SECHS; delay(500);
ledsoff(); SIEBEN; delay(500);
ledsoff(); UHR; delay(500);
ledsoff(); LED1; delay(500);
ledsoff(); LED2; delay(500);
ledsoff(); LED3; delay(500);
ledsoff(); LED4; delay(500);
Serial.println(" .. ok");
for(int i=0; i<5; i++)
{
Display1=255; Display2=255; Display3=255; delay(500);
ledsoff(); delay(500);
}
}
void displaytime(void){
// start by clearing the display to a known state
ledsoff();
// Now, turn on the "It is" leds
ESIST;
// now we display the appropriate minute counter
if ((minute>4) && (minute<10)) { MFUNF; NACH; }
if ((minute>9) && (minute<15)) { ZENH; NACH; }
if ((minute>14) && (minute<20)) { VIERTEL; NACH; }
if ((minute>19) && (minute<25)) { ZWANZIG; NACH; }
if ((minute>24) && (minute<30)) { MFUNF; VOR; HALB; }
if ((minute>29) && (minute<35)) { HALB;}
if ((minute>34) && (minute<40)) { MFUNF; NACH; HALB; }
if ((minute>39) && (minute<45)) { ZWANZIG; VOR; }
if ((minute>44) && (minute<50)) { VIERTEL; VOR; }
if ((minute>49) && (minute<55)) { ZENH; VOR; }
if (minute>54) { MFUNF; VOR; }
if ((minute <5))
{
switch (hour) {
case 1:
case 13: ONE; break;
case 2:
case 14: ZWEI; break;
case 3:
case 15: DREI; break;
case 4:
case 16: VIER; break;
case 5:
case 17: HFUNF; break;
case 6:
case 18: SECHS; break;
case 7:
case 19: SIEBEN; break;
case 8:
case 20: ACHT; break;
case 9:
case 21: NEUN; break;
case 10:
case 22: HZENH; break;
case 11:
case 23: ELEVEN; break;
case 0:
case 12:
case 24: ZWOLF; break;
}
UHR;
}
else
if ((minute < 25) && (minute >4))
{
switch (hour) {
case 1:
case 13: ONE; break;
case 2:
case 14: ZWEI; break;
case 3:
case 15: DREI; break;
case 4:
case 16: VIER; break;
case 5:
case 17: HFUNF; break;
case 6:
case 18: SECHS; break;
case 7:
case 19: SIEBEN; break;
case 8:
case 20: ACHT; break;
case 9:
case 21: NEUN; break;
case 10:
case 22: HZENH; break;
case 11:
case 23: ELEVEN; break;
case 0:
case 12:
case 24: ZWOLF; break;
}
}
else
{
// if we are greater than 34 minutes NACH the hour then display
// the next hour
switch (hour) {
case 1:
case 13: ZWEI; break;
case 14:
case 2: DREI; break;
case 15:
case 3: VIER; break;
case 4:
case 16: HFUNF; break;
case 5:
case 17: SECHS; break;
case 6:
case 18: SIEBEN; break;
case 7:
case 19: ACHT; break;
case 8:
case 20: NEUN; break;
case 9:
case 21: HZENH; break;
case 10:
case 22: ELEVEN; break;
case 11:
case 23: ZWOLF; break;
case 0:
case 12:
case 24: ONE; break;
}
}
// now we can illuminate the extra minute LEDs
if ((minute-(minute/5)*5)==1) { LED1; }
if ((minute-(minute/5)*5)==2) { LED1; LED2; }
if ((minute-(minute/5)*5)==3) { LED1; LED2; LED3; }
if ((minute-(minute/5)*5)==4) { LED1; LED2; LED3; LED4; }
// WriteLEDs();
}

486
wordclock/wordclock.pde Normal file
View File

@ -0,0 +1,486 @@
#include <stdio.h>
#include <string.h>
#include <DS1302.h> // I use the library that Matt Sparks created
#include <avr/interrupt.h>
#include <avr/io.h>
// uncomment the following to speed up the timer for testing
//#define TESTMODE
// specify the language - defines the header to be included
// available choices - English, Danish, French, German
//#define LANGUAGE "English.h"
#define LANGUAGE "Dutch.h"
/**************************************************************************
* *
* W O R D C L O C K - A clock that tells the time using words. *
* *
* Hardware: Arduino Dumelove with a set of individual LEDs under a word *
* stencil. *
* *
* Copyright (C) 2009 Doug Jackson (doug@doughq.com) *
* *
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
* MA 02111-1307 USA *
* *
***************************************************************************
*
* Revision History
*
* Date By What
* 20010205 DRJ Initial Creation of Arduino Version
* - based on Wordclock.c - from PIC version
* 20100428 DRJ Added support for DS1302 RTC Chip - Code verifies
* device is present - and if so, uses it for timekeeping
* 20100511 DRJ Added ability to detect old vs new Arduino boards
* New board uses diferent time button sense.
* 20100511 DRJ Minute LED support on Analog5-1 pins.
* 20100927 DRJ Added brightness support by enabling interrupts and
* using an ISR to control the display
*/
// DAY Brightness setting 0 = off 20 = full
#define DAYBRIGHTNESS 20
// NIGHT Brightness setting 0 = off 20 = full
#define NIGHTBRIGHTNESS 20
//#define LED1 Led1=1
//#define LED2 Led2=1
//#define LED3 Led3=1
//#define LED4 Led4=1
#define INIT_TIMER_COUNT 6
#define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT
int hour=12, minute=0, second=00;
static unsigned long msTick =0; // the number of Millisecond Ticks since we last
// incremented the second counter
int count;
int selftestmode; // 1 = in self test - flash display
int DS1302Present=0; // flag to indicate that the 1302 is there.. 1 = present
char Display1=0, Display2=0, Display3=0, Led1=0, Led2=0, Led3=0, Led4=0;
int OldHardware = 0; // 1 = we are running on old hardwrae
int BTNActive = 1; // the sense of the button inputs (Changes based on hardware type)
int timercount=10; // used for interrupt counting to determine the brightnes of the display
// hardware constants
int LEDClockPin=5; // Arduino Pin#11 - 4094 Pin 3 clock
int LEDDataPin=3; // Arduino Pin#5 - 4094 pin 2 Data
int LEDStrobePin=4; // Arduino Pin#6 - 4094 pin 1 Strobe
// buttons
int FWDButtonPin=6;
int REVButtonPin=7;
// 1302 RTC Constants
int DS1302IOPin=10;
int DS1302CEPin=8;
int DS1302CLKPin=9;
// Minute LED Pins
int LED1PIN=19; // Arduino analog 5
int LED2PIN=18; // Arduino analog 4
int LED3PIN=17; // Arduino analog 3
int LED4PIN=16; // Arduino analog 2
int current_brightnes=0;
// define the language to be used for this project:
#include LANGUAGE // The language pack
/* Create buffers */
char buf[50]; // time output string for debugging
// create an object that talks to the RTC
DS1302 rtc(DS1302CEPin, DS1302IOPin, DS1302CLKPin);
void print_DS1302time()
{
/* Get the current time and date from the chip */
Time t = rtc.time();
/* Format the time and date and insert into the temporary buffer */
snprintf(buf, sizeof(buf), "DS1302 time: %02d:%02d:%02d",
t.hr, t.min, t.sec);
/* Print the formatted string to serial so we can see the time */
Serial.println(buf);
}
void setup()
{
// initialise the hardware
// initialize the appropriate pins as outputs:
pinMode(LEDClockPin, OUTPUT);
pinMode(LEDDataPin, OUTPUT);
pinMode(LEDStrobePin, OUTPUT);
pinMode(FWDButtonPin, INPUT);
pinMode(REVButtonPin, INPUT);
// setup 1302
pinMode(DS1302IOPin, OUTPUT);
pinMode(DS1302CEPin, OUTPUT);
pinMode(DS1302CLKPin, OUTPUT);
// Minute LEDS
pinMode(LED1PIN, OUTPUT);
pinMode(LED2PIN, OUTPUT);
pinMode(LED3PIN, OUTPUT);
pinMode(LED4PIN, OUTPUT);
current_brightnes=DAYBRIGHTNESS;
Serial.begin(9600); // setup the serial port to 9600 baud
SWversion(); // Display the version number of the software
// test whether the DS1302 is there
Serial.print("Verifying DS1302 ");
// start by verifying that the chip has a valid signature
if (rtc.read_register(0x20) == 0xa5) {
// Signature is there - set the present flag and mmove on
DS1302Present=1;
Serial.println("present - Valid Signature");
rtc.write_protect(false);
rtc.halt(false);
}
else
{
// Signature isnt there - may be a new chip -
// do a write to see if it will hold the signature
rtc.write_register(0x20,0xa5);
if (rtc.read_register(0x20) == 0xa5) {
// We can store data - assume that it is a new chip that needs initialisation
// Start by turning off write protection and clearing the clock halt flag.
rtc.write_protect(false);
rtc.halt(false);
// Make a new time object to set the date and time
Time t(2010, 04, 28, 10, 19, 00, 01);
// Set the time and date on the chip
rtc.time(t);
// set the DS1302 present flag
DS1302Present=1;
Serial.println("present - new chip initialised.");
}
else Serial.println("absent");
}
// determine whether we are running on old or new hardware
// old hardware tied the push buttons to ground using 4k7 resistors
// and relied on the buttons to pull them high
// new hardware uses internal pullups, and uses the buttons
// to pull the inputs down.
digitalWrite(FWDButtonPin,HIGH); // Turn on weak pullups
digitalWrite(REVButtonPin,HIGH); // Turn on weak pullups
OldHardware=0;
if ( digitalRead(FWDButtonPin)==0 && digitalRead(REVButtonPin)==0)
{
Serial.println("Detected Old Hardware");
OldHardware=1; // we have old hardware
BTNActive = 1; // True = active for old hardware
digitalWrite(FWDButtonPin,LOW); // Turn off weak pullups
digitalWrite(REVButtonPin,LOW); // Turn off weak pullups
}
else
{
Serial.println("Detected New Hardware");
OldHardware=0; // we have old hardware
BTNActive = 0; // True = active for old hardware
}
// Initialise Timer2: Timer Prescaler /64,
TCCR2A = 0;
TCCR2B |= (1<<CS22);
TCCR2B &= ~((1<<CS21) | (1<<CS20));
// Use normal mode
TCCR2B &= ~((1<<WGM21) | (1<<WGM20));
// Use internal clock - external clock not used in Arduino
ASSR |= (0<<AS2);
//Timer2 Overflow Interrupt Enable
TIMSK2 |= 1<<TOIE2;
RESET_TIMER2;
sei();
Serial.println("Finished setting up Timer2 Interrupt");
msTick=millis(); // Initialise the msTick counter
selftest(); // validate the hardware for the user
selftestmode=0;
if (DS1302Present==1) {
// Get the current time and date from the chip
Time t = rtc.time();
second=t.sec;
minute=t.min;
hour=t.hr;
}
displaytime(); // display the current time
}
// Interrupt handler - Arduino runs at 16 Mhz, so we have 1000 Overflows per second...
// 1/ ((16000000 / 64) / 256) = 1 / 1000
ISR(TIMER2_OVF_vect) {
RESET_TIMER2;
if (timercount-- <= current_brightnes){
// Now we write the actual values to the hardware
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, Display3);
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, Display2);
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, Display1);
digitalWrite(LEDStrobePin,HIGH);
//delay(2);
digitalWrite(LEDStrobePin,LOW);
digitalWrite(LED1PIN,Led1);
digitalWrite(LED2PIN,Led2);
digitalWrite(LED3PIN,Led3);
digitalWrite(LED4PIN,Led4);
}
else
{
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, 0);
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, 0);
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, 0);
digitalWrite(LEDStrobePin,HIGH);
//delay(2);
digitalWrite(LEDStrobePin,LOW);
digitalWrite(LED1PIN,0);
digitalWrite(LED2PIN,0);
digitalWrite(LED3PIN,0);
digitalWrite(LED4PIN,0);
}
if (timercount==0) timercount=20;
}
void ledsoff(void) {
Display1=0;
Display2=0;
Display3=0;
Led1=0;
Led2=0;
Led3=0;
Led4=0;
}
void incrementtime(void){
// increment the time counters keeping care to rollover as required
second=0;
if (++minute >= 60) {
minute=0;
if (++hour == 25) {
hour=1;
}
}
// debug outputs
Serial.println();
if (DS1302Present==1) print_DS1302time();
else Serial.print("Arduino Time: " );
Serial.print(hour);
Serial.print(":");
Serial.print(minute);
Serial.print(":");
Serial.print(second);
Serial.print(" ");
}
void SWversion(void) {
delay(2000);
Serial.println();
Serial.println("Wordclock -Arduino v3.0a - reduced brightness version");
Serial.print(LANGUAGE); Serial.println(" header file used");
Serial.println("(c)2009, 2010, 2011 Doug Jackson");
}
void loop(void)
{
#ifdef TESTMODE
second=59;
#endif
//Serial.println("Loop Started");
// heart of the timer - keep looking at the millisecond timer on the Arduino
// and increment the seconds counter every 1000 ms
if ( millis() - msTick >999) {
msTick=millis();
second++;
// Flash the onboard Pin13 Led so we know something is hapening!
digitalWrite(13,HIGH);
delay(50);
digitalWrite(13,LOW);
delay(50);
digitalWrite(13,HIGH);
delay(50);
digitalWrite(13,LOW);
#ifndef TESTMODE
if (second%5==0) {
Serial.print(second);
Serial.print("..");
}
#endif
}
//test to see if we need to increment the time counters
if (second==60)
{
incrementtime();
displaytime();
}
if (DS1302Present==1) {
// Get the current time and date from the chip
Time t = rtc.time();
second=t.sec;
minute=t.min;
hour=t.hr;
}
// set the brightnes level based on the current hour - night=7pm - 6.59am
//
if ((hour <7) | (hour >=19))
current_brightnes=NIGHTBRIGHTNESS;
else
current_brightnes=DAYBRIGHTNESS;
// test to see if both buttons are being held down
// if so - start a self test till both buttons are held
// down again.
if ( digitalRead(FWDButtonPin)==BTNActive && digitalRead(REVButtonPin)==BTNActive)
{
selftestmode = !selftestmode;
if (selftestmode) Serial.println("Selftest Mode TRUE");
else Serial.println("Selftest mode FALSE");
}
if (selftestmode) {
for(int i=0; i<100; i++)
{
Display1=255; Display2=255; Display3=255; delay(101-i);
ledsoff();delay(101-i);
if (digitalRead(FWDButtonPin)==1) selftestmode=!selftestmode;
}
displaytime();
}
// test to see if a forward button is being held down
// for time setting
if (digitalRead(FWDButtonPin) ==BTNActive )
// the forward button is down
// and it has been more than one second since we
// last looked
{
Serial.println("Forward Button Down");
incrementtime();
second++; // Increment the second counter to ensure that the name
// flash doesnt happen when setting time
if (DS1302Present==1) {
// Make a new time object to set the date and time
Time t(2010, 04, 28, hour, minute, second, 01);
// Set the time and date on the chip
rtc.time(t);
}
delay(100);
displaytime();
}
// test to see if the back button is being held down
// for time setting
if (digitalRead(REVButtonPin)==BTNActive )
{
Serial.println("Backwards Button Down");
minute--;
minute--;
second=0; // decrement the minute counter
if (minute<0) {
minute=58;
if (--hour <0) hour=23;
}
incrementtime();
second++; // Increment the second counter to ensure that the name
// flash doesnt happen when setting time
if (DS1302Present==1) {
// Make a new time object to set the date and time
Time t(2010, 04, 28, hour, minute, second, 01);
// Set the time and date on the chip
rtc.time(t);
}
displaytime();
delay(100);
}
}