710 lines
20 KiB
C++
710 lines
20 KiB
C++
#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>
|
|
#include <math.h>
|
|
#include <pt.h>
|
|
|
|
// uncomment the following to speed up the timer for testing
|
|
//#define TESTMODE
|
|
|
|
// Insert function prototypes -- Paul
|
|
void ledsoff(void);
|
|
void setup(void);
|
|
void SWversion(void);
|
|
|
|
// 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
|
|
*/
|
|
|
|
// set SKIPSELFTEST to 1 to skip selftest
|
|
#define SKIPSELFTEST 1
|
|
|
|
// set USELIGHTSENSOR to 1 to use ambient light sensor connected to ADC0 (pin
|
|
// 23)
|
|
#define USELIGHTSENSOR 1
|
|
// analog input put to which ambiend light sensor is connected
|
|
#define LIGHTSENSOR_INPUTPIN 0
|
|
// bottom of light sensor (ambient light values at or lower than this level will
|
|
// be mapped to MINBRIGHTNESS)
|
|
#define LIGHTSENSOR_BOTTOM 0
|
|
// top of light sensor (ambient light values at or higher than this level will
|
|
// be mapped to MAXBRIGHTNESS)
|
|
#define LIGHTSENSOR_TOP 150
|
|
// slope of mapping function at bottom
|
|
#define LIGHTSENSOR_ALPHA1 0.02
|
|
// slope of mapping function at top
|
|
#define LIGHTSENSOR_ALPHA2 0.20
|
|
|
|
// weight for exponential decaying averaging (actual weigth is 2 ^ LIGHTSENSOR_WEIGHT)
|
|
#define LIGHTSENSOR_WEIGHT 4
|
|
// base of exponential mapping (must be > 1)
|
|
#define LIGHTSENSOR_BASE 1.40
|
|
|
|
#define N_PWM_STEPS 11
|
|
// DAY Brightness setting 0 = off, N_PWM_STEPS - 1 = full
|
|
#define MAXBRIGHTNESS 10
|
|
// start MAXBRIGHTNESS at DAYLIGHTHOUR (7 am)
|
|
#define DAYLIGHTHOUR 7
|
|
// NIGHT Brightness setting 0 = off, N_PWM_STEPS - 1 = full
|
|
#define MINBRIGHTNESS 1
|
|
// start MINBRIGHTNESS at NIGHTLIGHTHOUR (7 pm)
|
|
#define NIGHTLIGHTHOUR 19
|
|
|
|
#define INIT_TIMER_COUNT 6
|
|
#define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT
|
|
|
|
// there are only 20 brightness levels and 1024 lightsensor levels -> we need to
|
|
// scale the brightness levels to something closer to avoid having to work with
|
|
// floating point numbers
|
|
#define LIGHTSENSOR_SCALE 10
|
|
unsigned int brightness_per_unit_light = ((1 << LIGHTSENSOR_SCALE) * (MAXBRIGHTNESS -
|
|
MINBRIGHTNESS)) / (LIGHTSENSOR_TOP - LIGHTSENSOR_BOTTOM);
|
|
|
|
int hour=12, minute=0, second=0;
|
|
// 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 hardware
|
|
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
|
|
#define FWD_BUTTON_PIN 6
|
|
#define REV_BUTTON_PIN 7
|
|
#define BUTTON_PORT PIND
|
|
#define FWD_BUTTON_MASK (1 << 6)
|
|
#define REV_BUTTON_MASK (1 << 7)
|
|
|
|
// delay in ms before repeating key
|
|
#define BUTTON_DELAY_LONG 1000
|
|
// delay in ms before repeating key a second time
|
|
#define BUTTON_DELAY_SHORT 200
|
|
|
|
|
|
// 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;
|
|
|
|
char ambient_light_to_brightness[1024];
|
|
|
|
|
|
// 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);
|
|
|
|
// ProtoThread structures (one for each thread)
|
|
static struct pt blink_thread_pt, lightsensor_thread_pt, buttons_thread_pt, wordclock_thread_pt;
|
|
|
|
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()
|
|
{
|
|
int n;
|
|
|
|
// a, b, c and e are needed to compute lookup table for ambient light sensor
|
|
float a, b, c, e;
|
|
|
|
// initialise the hardware
|
|
// initialize the appropriate pins as outputs:
|
|
pinMode(LEDClockPin, OUTPUT);
|
|
pinMode(LEDDataPin, OUTPUT);
|
|
pinMode(LEDStrobePin, OUTPUT);
|
|
pinMode(FWD_BUTTON_PIN, INPUT);
|
|
pinMode(REV_BUTTON_PIN, 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);
|
|
|
|
//analogReference(DEFAULT);
|
|
analogReference(INTERNAL);
|
|
//analogReference(EXTERNAL);
|
|
// known 'bug' in AVR ADC: after switching analog reference, first sample
|
|
// could be corrupt and should be ignored --> discard this sample now
|
|
analogRead(LIGHTSENSOR_INPUTPIN);
|
|
|
|
current_brightnes=MAXBRIGHTNESS;
|
|
|
|
//Serial.begin(9600); // setup the serial port to 9600 baud
|
|
Serial.begin(115200); // setup the serial port to 115200 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");
|
|
}
|
|
|
|
// compute ambient light level to brightness level mapping
|
|
a = LIGHTSENSOR_ALPHA1 * LIGHTSENSOR_TOP / log(LIGHTSENSOR_ALPHA2 /
|
|
LIGHTSENSOR_ALPHA1);
|
|
b = LIGHTSENSOR_ALPHA1 / a;
|
|
c = MINBRIGHTNESS - a;
|
|
e = 2.718281828459045297;
|
|
|
|
for (n = 0; n < sizeof(ambient_light_to_brightness); n++)
|
|
{
|
|
if (n <= LIGHTSENSOR_BOTTOM)
|
|
ambient_light_to_brightness[n] = MINBRIGHTNESS;
|
|
else if (n >= LIGHTSENSOR_TOP)
|
|
ambient_light_to_brightness[n] = MAXBRIGHTNESS;
|
|
else
|
|
{
|
|
ambient_light_to_brightness[n] =
|
|
round(((float) a) * pow(e, ((float) b) *
|
|
((float) n)) + (float) c);
|
|
if (ambient_light_to_brightness[n] < MINBRIGHTNESS)
|
|
ambient_light_to_brightness[n] = MINBRIGHTNESS;
|
|
if (ambient_light_to_brightness[n] > MAXBRIGHTNESS)
|
|
ambient_light_to_brightness[n] = MAXBRIGHTNESS;
|
|
}
|
|
}
|
|
|
|
// 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(FWD_BUTTON_PIN,HIGH); // Turn on weak pullups
|
|
digitalWrite(REV_BUTTON_PIN,HIGH); // Turn on weak pullups
|
|
|
|
OldHardware=0;
|
|
if ( digitalRead(FWD_BUTTON_PIN)==0 && digitalRead(REV_BUTTON_PIN)==0)
|
|
{
|
|
Serial.println("Detected Old Hardware");
|
|
OldHardware=1; // we have old hardware
|
|
BTNActive = 1; // True = active for old hardware
|
|
digitalWrite(FWD_BUTTON_PIN,LOW); // Turn off weak pullups
|
|
digitalWrite(REV_BUTTON_PIN,LOW); // Turn off weak pullups
|
|
|
|
}
|
|
else
|
|
{
|
|
Serial.println("Detected New Hardware");
|
|
OldHardware=0; // we have new 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");
|
|
|
|
|
|
|
|
#if (SKIPSELFTEST != 1)
|
|
selftest(); // validate the hardware for the user
|
|
#endif
|
|
|
|
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=N_PWM_STEPS-1;
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
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 process_buttons(unsigned char button_status)
|
|
{
|
|
char buttonPressed = 0, fwdButtonPressed = 0, revButtonPressed = 0, buttonStatus = 0;
|
|
static unsigned long buttonPressedMillis = 0;
|
|
static unsigned long button_delay = BUTTON_DELAY_LONG;
|
|
unsigned long millisNow = 0, new_button_delay;
|
|
|
|
if (BTNActive)
|
|
{
|
|
if ((button_status & FWD_BUTTON_MASK) > 0)
|
|
fwdButtonPressed = 1;
|
|
if ((button_status & REV_BUTTON_MASK) > 0)
|
|
revButtonPressed = 1;
|
|
}
|
|
else
|
|
{
|
|
if ((button_status & FWD_BUTTON_MASK) == 0)
|
|
fwdButtonPressed = 1;
|
|
if ((button_status & REV_BUTTON_MASK) == 0)
|
|
revButtonPressed = 1;
|
|
}
|
|
|
|
if (fwdButtonPressed && revButtonPressed)
|
|
{
|
|
selftestmode != selftestmode;
|
|
}
|
|
|
|
// 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(FWD_BUTTON_PIN)==BTNActive && digitalRead(REV_BUTTON_PIN)==BTNActive)
|
|
if (selftestmode) {
|
|
Serial.println("Selftest Mode TRUE");
|
|
for(int i=0; i<100; i++)
|
|
{
|
|
Display1=255; Display2=255; Display3=255; delay(101-i);
|
|
ledsoff();delay(101-i);
|
|
if (digitalRead(FWD_BUTTON_PIN)==1)
|
|
selftestmode=!selftestmode;
|
|
}
|
|
displaytime();
|
|
}
|
|
|
|
if (fwdButtonPressed)
|
|
{
|
|
// 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);
|
|
}
|
|
displaytime();
|
|
}
|
|
|
|
if (revButtonPressed)
|
|
{
|
|
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();
|
|
}
|
|
|
|
// key repeat delay code:
|
|
millisNow = millis();
|
|
|
|
if (millisNow - buttonPressedMillis < BUTTON_DELAY_LONG)
|
|
new_button_delay = BUTTON_DELAY_SHORT;
|
|
else
|
|
new_button_delay = BUTTON_DELAY_LONG;
|
|
|
|
delay(button_delay);
|
|
button_delay = new_button_delay;
|
|
buttonPressedMillis = millis();
|
|
}
|
|
|
|
static int buttons_thread(struct pt *pt)
|
|
{
|
|
PT_BEGIN(pt);
|
|
|
|
while(1)
|
|
{
|
|
if (BTNActive)
|
|
{
|
|
PT_WAIT_UNTIL(pt, ((BUTTON_PORT & FWD_BUTTON_MASK) > 0) ||
|
|
((BUTTON_PORT & REV_BUTTON_MASK) > 0));
|
|
process_buttons(BUTTON_PORT);
|
|
}
|
|
else
|
|
{
|
|
PT_WAIT_UNTIL(pt, ((BUTTON_PORT & FWD_BUTTON_MASK) == 0) ||
|
|
((BUTTON_PORT & REV_BUTTON_MASK) == 0));
|
|
process_buttons(BUTTON_PORT);
|
|
}
|
|
}
|
|
|
|
PT_END(pt);
|
|
}
|
|
|
|
static int lightsensor_thread(struct pt *pt)
|
|
{
|
|
static unsigned long msTick =0; // the number of Millisecond Ticks since we last
|
|
static unsigned long int lightlevel_avg;
|
|
unsigned long int lightlevel_sample;
|
|
static char millisWillOverflow = 0;
|
|
static char n_lightlevel_samples = 0;
|
|
|
|
PT_BEGIN(pt);
|
|
|
|
while(1)
|
|
{
|
|
PT_WAIT_UNTIL(pt, millisWillOverflow ? (millis() - msTick > 99) :
|
|
((millis() < 4294967295 - 98) && (millis() - msTick > 99)));
|
|
msTick=millis();
|
|
|
|
lightlevel_sample = analogRead(LIGHTSENSOR_INPUTPIN);
|
|
|
|
// update average
|
|
if (n_lightlevel_samples < (1 << LIGHTSENSOR_WEIGHT))
|
|
{
|
|
// add (1 << (LIGHTSENSOR_WEIGHT - 1)) to average before division so that
|
|
// the average is round()-ed instead of floor()-ed
|
|
lightlevel_avg = (n_lightlevel_samples * lightlevel_avg +
|
|
lightlevel_sample + (1 << (LIGHTSENSOR_WEIGHT - 1))) /
|
|
(n_lightlevel_samples + 1);
|
|
n_lightlevel_samples++;
|
|
}
|
|
else
|
|
{
|
|
// do not update n_lightlevel_samples to prevent overflow
|
|
|
|
// add (1 << (LIGHTSENSOR_WEIGHT - 1)) to average before division so that
|
|
// the average is round()-ed instead of floor()-ed
|
|
lightlevel_avg = ( ((1 << LIGHTSENSOR_WEIGHT) - 1) * lightlevel_avg +
|
|
lightlevel_sample + (1 << (LIGHTSENSOR_WEIGHT - 1))) >> LIGHTSENSOR_WEIGHT;
|
|
}
|
|
|
|
// compute new brightness level
|
|
/*
|
|
// linear method
|
|
if (lightlevel_avg <= LIGHTSENSOR_BOTTOM)
|
|
current_brightnes = MINBRIGHTNESS;
|
|
else if (lightlevel_avg >= LIGHTSENSOR_TOP)
|
|
current_brightnes = MAXBRIGHTNESS;
|
|
else
|
|
{
|
|
current_brightnes = (brightness_per_unit_light * (lightlevel_avg -
|
|
LIGHTSENSOR_BOTTOM)) / (1 << LIGHTSENSOR_SCALE) + MINBRIGHTNESS;
|
|
} */
|
|
|
|
current_brightnes = ambient_light_to_brightness[lightlevel_avg];
|
|
|
|
Serial.print("lightsensor: ");
|
|
Serial.print(lightlevel_sample);
|
|
Serial.print(" / ");
|
|
Serial.print(lightlevel_avg);
|
|
Serial.print(", brightness: ");
|
|
Serial.println(current_brightnes);
|
|
}
|
|
|
|
PT_END(pt);
|
|
}
|
|
|
|
static int blink_thread(struct pt *pt)
|
|
{
|
|
static unsigned long msTick =0; // the number of Millisecond Ticks since we last
|
|
static char millisWillOverflow = 0;
|
|
|
|
PT_BEGIN(pt);
|
|
|
|
while(1)
|
|
{
|
|
PT_WAIT_UNTIL(pt, millisWillOverflow ? (millis() - msTick > 999) :
|
|
((millis() < 4294967295 - 998) && (millis() - msTick > 999)));
|
|
msTick=millis();
|
|
Serial.println(":)");
|
|
|
|
// 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);
|
|
}
|
|
|
|
PT_END(pt);
|
|
}
|
|
|
|
static int wordclock_thread(struct pt *pt)
|
|
{
|
|
static unsigned int counter = 0;
|
|
static unsigned long msTick =0; // the number of Millisecond Ticks since we last
|
|
static char millisWillOverflow = 0;
|
|
|
|
#ifdef TESTMODE
|
|
second=59;
|
|
#endif
|
|
|
|
//Serial.println("Loop Started");
|
|
|
|
PT_BEGIN(pt);
|
|
msTick=millis(); // Initialise the msTick counter
|
|
|
|
// heart of the timer - keep looking at the millisecond timer on the Arduino
|
|
// and increment the seconds counter every 1000 ms
|
|
|
|
while(1)
|
|
{
|
|
PT_WAIT_UNTIL(pt, millisWillOverflow ? (millis() - msTick > 999) :
|
|
((millis() < 4294967295 - 998) && (millis() - msTick > 999)));
|
|
msTick=millis();
|
|
if (msTick > 4294967295 - 998)
|
|
{
|
|
// millis() will overflow --> adjust msTick
|
|
msTick = 999 - (4294967295 - msTick);
|
|
millisWillOverflow = 1;
|
|
}
|
|
else
|
|
millisWillOverflow = 0;
|
|
|
|
second++;
|
|
|
|
//test to see if we need to increment the time counters
|
|
if (second==60)
|
|
{
|
|
incrementtime();
|
|
displaytime();
|
|
Serial.print("time: ");
|
|
Serial.print(hour, DEC);
|
|
Serial.print(":");
|
|
Serial.print(minute, DEC);
|
|
Serial.print(":");
|
|
Serial.println(second, DEC);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
#if (USELIGHTSENSOR == 0)
|
|
// set the brightnes level based on the current hour - night=7pm - 6.59am
|
|
if ((hour < DAYLIGHTHOUR) | (hour >= NIGHTLIGHTHOUR))
|
|
current_brightnes=MINBRIGHTNESS;
|
|
else
|
|
current_brightnes=MAXBRIGHTNESS;
|
|
#endif
|
|
|
|
PT_END(pt);
|
|
}
|
|
}
|
|
|
|
void loop()
|
|
{
|
|
// call each thread continuously
|
|
wordclock_thread(&wordclock_thread_pt);
|
|
buttons_thread(&buttons_thread_pt);
|
|
#if (USELIGHTSENSOR == 1)
|
|
lightsensor_thread(&lightsensor_thread_pt);
|
|
#endif
|
|
blink_thread(&blink_thread_pt);
|
|
}
|
|
|