DCF77-Analyzer-Clock-v2
							
								
								
									
										
											BIN
										
									
								
								Arduino Libraries/DS1307RTC.zip
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Arduino Libraries/OneWire.zip
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Arduino Libraries/Time.zip
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,353 @@
 | 
			
		||||
//
 | 
			
		||||
//  This is the Superfilter sketch I use with the DCF Analyzer/Clock 2.0 
 | 
			
		||||
//  Udo Klein did an amazing job with this filter
 | 
			
		||||
//
 | 
			
		||||
//  Erik de Ruiter
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    Arduino Uno pin connections I used for the DCF Analyzer Clock
 | 
			
		||||
 | 
			
		||||
    DCF input ................. A5 (19)  = dcf77_sample_pin
 | 
			
		||||
    Output DCF Filtered ....... 12       = dcf77_filtered_pin
 | 
			
		||||
    Output DCF Semi Synthesized A2 (16)  = dcf77_semi_synthesized_pin
 | 
			
		||||
    Output DCF Synthesized ....  6       = dcf77_synthesized_pin
 | 
			
		||||
    LED DCF output filtered ... A4 (18)  = dcf77_monitor_pin                    = DCF Monitor LED
 | 
			
		||||
    LED 1 Hz pulse ............ 10       = dcf77_second_pulse_pin               = Filter Locked LED
 | 
			
		||||
    LED DCF OK ................ 13       = dcf77_signal_good_indicator_pin      = Signal Quality LED
 | 
			
		||||
    LED Difference Filtered ...  7       = dcf77_filter_diff_pin            \      
 | 
			
		||||
    LED Difference Semi Synth.. A0       = dcf77_semi_synthesized_diff_pin   -> = Signal Difference LED
 | 
			
		||||
    LED Difference Synthesized   4       = dcf77_synthesized_diff_pin       /
 | 
			
		||||
*/
 | 
			
		||||
    
 | 
			
		||||
//
 | 
			
		||||
//  www.blinkenlight.net
 | 
			
		||||
//
 | 
			
		||||
//  Copyright 2014, 2015 Udo Klein
 | 
			
		||||
//
 | 
			
		||||
//  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 3 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, see http://www.gnu.org/licenses/
 | 
			
		||||
 | 
			
		||||
#include <dcf77.h>
 | 
			
		||||
/*
 | 
			
		||||
const uint8_t pon_pin  = 51; // connect pon to ground !!!
 | 
			
		||||
const uint8_t data_pin = 19;
 | 
			
		||||
const uint8_t gnd_pin  = 51;
 | 
			
		||||
const uint8_t vcc_pin  = 49;
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
const uint8_t dcf77_analog_samples = false;
 | 
			
		||||
const uint8_t dcf77_analog_sample_pin = 5;
 | 
			
		||||
const uint8_t dcf77_sample_pin = 19; // A5
 | 
			
		||||
const uint8_t dcf77_inverted_samples = 0;
 | 
			
		||||
#if defined(__AVR__)
 | 
			
		||||
#define ledpin(led) (led)
 | 
			
		||||
#else
 | 
			
		||||
#define ledpin(led) (led<14? led: led+(54-14))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
const uint8_t dcf77_monitor_pin = ledpin(18); // A4
 | 
			
		||||
 | 
			
		||||
const bool provide_filtered_output = true;
 | 
			
		||||
const uint8_t dcf77_filtered_pin          = ledpin(12);
 | 
			
		||||
const uint8_t dcf77_inverted_filtered_pin = ledpin(11);
 | 
			
		||||
const uint8_t dcf77_filter_diff_pin       = ledpin(7);
 | 
			
		||||
 | 
			
		||||
const bool provide_semi_synthesized_output = true;
 | 
			
		||||
const uint8_t dcf77_semi_synthesized_pin          = ledpin(16);
 | 
			
		||||
const uint8_t dcf77_inverted_semi_synthesized_pin = ledpin(15);
 | 
			
		||||
const uint8_t dcf77_semi_synthesized_diff_pin     = ledpin(14);
 | 
			
		||||
 | 
			
		||||
const bool provide_synthesized_output = true;
 | 
			
		||||
const uint8_t dcf77_synthesized_pin          = ledpin(6);
 | 
			
		||||
const uint8_t dcf77_inverted_synthesized_pin = ledpin(5);
 | 
			
		||||
const uint8_t dcf77_synthesized_diff_pin     = ledpin(4);
 | 
			
		||||
 | 
			
		||||
const uint8_t dcf77_second_pulse_pin = ledpin(10);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const uint8_t dcf77_signal_good_indicator_pin = ledpin(13);
 | 
			
		||||
 | 
			
		||||
volatile uint16_t ms_counter = 0;
 | 
			
		||||
volatile Internal::DCF77::tick_t tick = Internal::DCF77::undefined;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template <bool enable, uint8_t threshold,
 | 
			
		||||
          uint8_t filtered_pin, uint8_t inverted_filtered_pin, uint8_t diff_pin>
 | 
			
		||||
void set_output(uint8_t clock_state, uint8_t sampled_data, uint8_t synthesized_signal)
 | 
			
		||||
{
 | 
			
		||||
    if (enable) {
 | 
			
		||||
        const uint8_t filtered_output = clock_state < threshold? sampled_data: synthesized_signal;
 | 
			
		||||
        digitalWrite(filtered_pin, filtered_output);
 | 
			
		||||
        digitalWrite(inverted_filtered_pin, !filtered_output);
 | 
			
		||||
        digitalWrite(diff_pin, filtered_output ^ sampled_data);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
    struct Scope {
 | 
			
		||||
        static const uint16_t samples_per_second = 1000;
 | 
			
		||||
        static const uint8_t bins                = 100;
 | 
			
		||||
        static const uint8_t samples_per_bin     = samples_per_second / bins;
 | 
			
		||||
 | 
			
		||||
        volatile uint8_t gbin[bins];
 | 
			
		||||
        volatile boolean samples_pending = false;
 | 
			
		||||
        volatile uint32_t count = 0;
 | 
			
		||||
 | 
			
		||||
        void process_one_sample(const uint8_t sample) {
 | 
			
		||||
            static uint8_t sbin[bins];
 | 
			
		||||
 | 
			
		||||
            static uint16_t ticks = 999;  // first pass will init the bins
 | 
			
		||||
            ++ticks;
 | 
			
		||||
 | 
			
		||||
            if (ticks == 1000) {
 | 
			
		||||
                ticks = 0;
 | 
			
		||||
                memcpy((void *)gbin, sbin, bins);
 | 
			
		||||
                memset(sbin, 0, bins);
 | 
			
		||||
                samples_pending = true;
 | 
			
		||||
                ++count;
 | 
			
		||||
            }
 | 
			
		||||
            sbin[ticks/samples_per_bin] += sample;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void print() {
 | 
			
		||||
            uint8_t lbin[bins];
 | 
			
		||||
 | 
			
		||||
            if (samples_pending) {
 | 
			
		||||
                noInterrupts();
 | 
			
		||||
                memcpy(lbin, (void *)gbin, bins);
 | 
			
		||||
                samples_pending = false;
 | 
			
		||||
                interrupts();
 | 
			
		||||
 | 
			
		||||
                // ensure the count values will be aligned to the right
 | 
			
		||||
                for (int32_t val=count; val < 100000000; val *= 10) {
 | 
			
		||||
                    Serial.print(' ');
 | 
			
		||||
                }
 | 
			
		||||
                Serial.print((int32_t)count);
 | 
			
		||||
                Serial.print(", ");
 | 
			
		||||
                for (uint8_t bin=0; bin<bins; ++bin) {
 | 
			
		||||
                    switch (lbin[bin]) {
 | 
			
		||||
                        case  0: Serial.print(bin%10? '-': '+'); break;
 | 
			
		||||
                        case 10: Serial.print('X');              break;
 | 
			
		||||
                        default: Serial.print(lbin[bin]);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                Serial.println();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Scope scope_1;
 | 
			
		||||
Scope scope_2;
 | 
			
		||||
 | 
			
		||||
uint8_t sample_input_pin() {
 | 
			
		||||
    const uint8_t clock_state = DCF77_Clock::get_clock_state();
 | 
			
		||||
    const uint8_t sampled_data =
 | 
			
		||||
        #if defined(__AVR__)
 | 
			
		||||
        dcf77_inverted_samples ^ (dcf77_analog_samples? (analogRead(dcf77_analog_sample_pin) > 200)
 | 
			
		||||
                                                      : digitalRead(dcf77_sample_pin));
 | 
			
		||||
        #else
 | 
			
		||||
        dcf77_inverted_samples ^ digitalRead(dcf77_sample_pin);
 | 
			
		||||
        #endif
 | 
			
		||||
 | 
			
		||||
    digitalWrite(dcf77_monitor_pin, sampled_data);
 | 
			
		||||
    digitalWrite(dcf77_second_pulse_pin, ms_counter < 500 && clock_state >= Clock::locked);
 | 
			
		||||
 | 
			
		||||
    const uint8_t synthesized_signal =
 | 
			
		||||
        tick == Internal::DCF77::long_tick  ? ms_counter < 200:
 | 
			
		||||
        tick == Internal::DCF77::short_tick ? ms_counter < 100:
 | 
			
		||||
        tick == Internal::DCF77::sync_mark  ? 0:
 | 
			
		||||
                                              // tick == DCF77::undefined --> default handling
 | 
			
		||||
                                              // allow signal to pass for the first 200ms of each second
 | 
			
		||||
                                              (ms_counter <=200 && sampled_data) ||
 | 
			
		||||
                                              // if the clock has valid time data then undefined ticks
 | 
			
		||||
                                              // are data bits --> first 100ms of signal must be high
 | 
			
		||||
                                              ms_counter <100;
 | 
			
		||||
 | 
			
		||||
    set_output<provide_filtered_output, Clock::locked,
 | 
			
		||||
              dcf77_filtered_pin, dcf77_inverted_filtered_pin, dcf77_filter_diff_pin>
 | 
			
		||||
              (clock_state, sampled_data, synthesized_signal);
 | 
			
		||||
 | 
			
		||||
    set_output<provide_semi_synthesized_output, Clock::unlocked,
 | 
			
		||||
               dcf77_semi_synthesized_pin, dcf77_inverted_semi_synthesized_pin, dcf77_semi_synthesized_diff_pin>
 | 
			
		||||
               (clock_state, sampled_data, synthesized_signal);
 | 
			
		||||
 | 
			
		||||
    set_output<provide_synthesized_output, Clock::free,
 | 
			
		||||
               dcf77_synthesized_pin, dcf77_inverted_synthesized_pin, dcf77_synthesized_diff_pin>
 | 
			
		||||
               (clock_state, sampled_data, synthesized_signal);
 | 
			
		||||
 | 
			
		||||
    ms_counter+= (ms_counter < 1000);
 | 
			
		||||
 | 
			
		||||
    scope_1.process_one_sample(sampled_data);
 | 
			
		||||
    scope_2.process_one_sample(digitalRead(dcf77_synthesized_pin));
 | 
			
		||||
 | 
			
		||||
    return sampled_data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void output_handler(const Clock::time_t &decoded_time) {
 | 
			
		||||
    // reset ms_counter for 1 Hz ticks
 | 
			
		||||
    ms_counter = 0;
 | 
			
		||||
 | 
			
		||||
    // status indicator --> always on if signal is good
 | 
			
		||||
    //                      blink 3s on 1s off if signal is poor
 | 
			
		||||
    //                      blink 1s on 3s off if signal is very poor
 | 
			
		||||
    //                      always off if signal is bad
 | 
			
		||||
    const uint8_t clock_state = DCF77_Clock::get_clock_state();
 | 
			
		||||
    digitalWrite(dcf77_signal_good_indicator_pin,
 | 
			
		||||
                 clock_state >= Clock::locked  ? 1:
 | 
			
		||||
                 clock_state == Clock::unlocked? (decoded_time.second.digit.lo & 0x03) != 0:
 | 
			
		||||
                 clock_state == Clock::free    ? (decoded_time.second.digit.lo & 0x03) == 0:
 | 
			
		||||
                                                  0);
 | 
			
		||||
    // compute output for signal synthesis
 | 
			
		||||
    Internal::DCF77_Encoder now;
 | 
			
		||||
    now.second                    = BCD::bcd_to_int(decoded_time.second);
 | 
			
		||||
    now.minute                    = decoded_time.minute;
 | 
			
		||||
    now.hour                      = decoded_time.hour;
 | 
			
		||||
    now.weekday                   = decoded_time.weekday;
 | 
			
		||||
    now.day                       = decoded_time.day;
 | 
			
		||||
    now.month                     = decoded_time.month;
 | 
			
		||||
    now.year                      = decoded_time.year;
 | 
			
		||||
    now.uses_summertime           = decoded_time.uses_summertime;
 | 
			
		||||
    now.leap_second_scheduled     = decoded_time.leap_second_scheduled;
 | 
			
		||||
    now.timezone_change_scheduled = decoded_time.timezone_change_scheduled;
 | 
			
		||||
 | 
			
		||||
    now.undefined_minute_output                         = false;
 | 
			
		||||
    now.undefined_uses_summertime_output                = false;
 | 
			
		||||
    now.undefined_abnormal_transmitter_operation_output = false;
 | 
			
		||||
    now.undefined_timezone_change_scheduled_output      = false;
 | 
			
		||||
 | 
			
		||||
    now.advance_minute();
 | 
			
		||||
    tick = now.get_current_signal();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void setup_serial() {
 | 
			
		||||
    Serial.begin(115200);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void output_splash_screen() {
 | 
			
		||||
    Serial.println();
 | 
			
		||||
    Serial.println(F("DCF77 Superfilter 3.0"));
 | 
			
		||||
    Serial.println(F("(c) 2015 Udo Klein"));
 | 
			
		||||
    Serial.println(F("www.blinkenlight.net"));
 | 
			
		||||
    Serial.println();
 | 
			
		||||
    Serial.print(F("Sample Pin:               ")); Serial.println(dcf77_sample_pin);
 | 
			
		||||
    Serial.print(F("Inverted Mode:            ")); Serial.println(dcf77_inverted_samples);
 | 
			
		||||
    #if defined(__AVR__)
 | 
			
		||||
    Serial.print(F("Analog Mode:              ")); Serial.println(dcf77_analog_samples);
 | 
			
		||||
    #endif
 | 
			
		||||
    Serial.print(F("Monitor Pin:              ")); Serial.println(dcf77_monitor_pin);
 | 
			
		||||
    Serial.println();
 | 
			
		||||
 | 
			
		||||
    if (provide_filtered_output) {
 | 
			
		||||
        Serial.println(F("Filtered Output"));
 | 
			
		||||
        Serial.print(F("    Filtered Pin:         ")); Serial.println(dcf77_filtered_pin);
 | 
			
		||||
        Serial.print(F("    Diff Pin:             ")); Serial.println(dcf77_filter_diff_pin);
 | 
			
		||||
        Serial.print(F("    Inverse Filtered Pin: ")); Serial.println(dcf77_inverted_filtered_pin);
 | 
			
		||||
        Serial.println();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (provide_semi_synthesized_output) {
 | 
			
		||||
        Serial.println(F("Semi Synthesized Output"));
 | 
			
		||||
        Serial.print(F("    Filtered Pin:         ")); Serial.println(dcf77_semi_synthesized_pin);
 | 
			
		||||
        Serial.print(F("    Diff Pin:             ")); Serial.println(dcf77_semi_synthesized_diff_pin);
 | 
			
		||||
        Serial.print(F("    Inverse Filtered Pin: ")); Serial.println(dcf77_inverted_semi_synthesized_pin);
 | 
			
		||||
        Serial.println();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (provide_synthesized_output) {
 | 
			
		||||
        Serial.println(F("Synthesized Output"));
 | 
			
		||||
        Serial.print(F("    Filtered Pin:         ")); Serial.println(dcf77_synthesized_pin);
 | 
			
		||||
        Serial.print(F("    Diff Pin:             ")); Serial.println(dcf77_synthesized_diff_pin);
 | 
			
		||||
        Serial.print(F("    Inverse Filtered Pin: ")); Serial.println(dcf77_inverted_synthesized_pin);
 | 
			
		||||
        Serial.println();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Serial.print(F("Second Pulse Pin:         ")); Serial.println(dcf77_second_pulse_pin);
 | 
			
		||||
    Serial.print(F("Signal Good Pin:          ")); Serial.println(dcf77_signal_good_indicator_pin);
 | 
			
		||||
 | 
			
		||||
    Serial.println();
 | 
			
		||||
 | 
			
		||||
    Serial.println();
 | 
			
		||||
    Serial.println(F("Initializing..."));
 | 
			
		||||
    Serial.println();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void setup_pins() {
 | 
			
		||||
    if (provide_filtered_output) {
 | 
			
		||||
        pinMode(dcf77_filtered_pin, OUTPUT);
 | 
			
		||||
        pinMode(dcf77_filter_diff_pin, OUTPUT);
 | 
			
		||||
        pinMode(dcf77_inverted_filtered_pin, OUTPUT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (provide_semi_synthesized_output) {
 | 
			
		||||
        pinMode(dcf77_semi_synthesized_pin, OUTPUT);
 | 
			
		||||
        pinMode(dcf77_semi_synthesized_diff_pin, OUTPUT);
 | 
			
		||||
        pinMode(dcf77_inverted_semi_synthesized_pin, OUTPUT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (provide_synthesized_output) {
 | 
			
		||||
        pinMode(dcf77_synthesized_pin, OUTPUT);
 | 
			
		||||
        pinMode(dcf77_synthesized_diff_pin, OUTPUT);
 | 
			
		||||
        pinMode(dcf77_inverted_synthesized_pin, OUTPUT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pinMode(dcf77_monitor_pin, OUTPUT);
 | 
			
		||||
    pinMode(dcf77_signal_good_indicator_pin, OUTPUT);
 | 
			
		||||
    pinMode(dcf77_second_pulse_pin, OUTPUT);
 | 
			
		||||
    pinMode(dcf77_sample_pin, INPUT);
 | 
			
		||||
    digitalWrite(dcf77_sample_pin, HIGH);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void setup_clock() {
 | 
			
		||||
    DCF77_Clock::setup();
 | 
			
		||||
    DCF77_Clock::set_input_provider(sample_input_pin);
 | 
			
		||||
    DCF77_Clock::set_output_handler(output_handler);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void setup() {
 | 
			
		||||
    setup_serial();
 | 
			
		||||
    output_splash_screen();
 | 
			
		||||
    setup_pins();
 | 
			
		||||
    setup_clock();
 | 
			
		||||
/*
 | 
			
		||||
    pinMode(gnd_pin, OUTPUT);
 | 
			
		||||
    digitalWrite(gnd_pin, LOW);
 | 
			
		||||
    pinMode(pon_pin, OUTPUT);
 | 
			
		||||
    digitalWrite(pon_pin, LOW);
 | 
			
		||||
    pinMode(vcc_pin, OUTPUT);
 | 
			
		||||
    digitalWrite(vcc_pin, HIGH);
 | 
			
		||||
    */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void loop() {
 | 
			
		||||
    Clock::time_t now;
 | 
			
		||||
    DCF77_Clock::get_current_time(now);
 | 
			
		||||
 | 
			
		||||
    if (now.month.val > 0) {
 | 
			
		||||
        Serial.println();
 | 
			
		||||
        Serial.print(F("Decoded time: "));
 | 
			
		||||
 | 
			
		||||
        DCF77_Clock::print(now);
 | 
			
		||||
        Serial.println();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Serial.print(DCF77_Clock::get_clock_state());
 | 
			
		||||
    Serial.print(' ');
 | 
			
		||||
    DCF77_Clock::debug();
 | 
			
		||||
 | 
			
		||||
    scope_1.print();
 | 
			
		||||
    scope_2.print();
 | 
			
		||||
}
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 9.2 MiB  | 
| 
		 Before Width: | Height: | Size: 2.6 MiB  | 
							
								
								
									
										
											BIN
										
									
								
								DCF77_Analyzer_Clock_v2_BackPanel_Preview.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 123 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								DCF77_Analyzer_Clock_v2_FrontPanel_Preview.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 375 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								DCF77_clock.jpg
									
									
									
									
									
								
							
							
						
						| 
		 Before Width: | Height: | Size: 309 KiB  | 
| 
		 After Width: | Height: | Size: 538 KiB  | 
| 
		 After Width: | Height: | Size: 8.8 MiB  | 
| 
		 After Width: | Height: | Size: 1.2 MiB  | 
							
								
								
									
										
											BIN
										
									
								
								Grandfather_Clock_Sound_files/T00.ogg
									
									
									
									
									
										Executable file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Grandfather_Clock_Sound_files/T10HOLDL.ogg
									
									
									
									
									
										Executable file
									
								
							
							
						
						@@ -1,213 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 *    LedControl.cpp - A library for controling Leds with a MAX7219/MAX7221
 | 
			
		||||
 *    Copyright (c) 2007 Eberhard Fahle
 | 
			
		||||
 * 
 | 
			
		||||
 *    Permission is hereby granted, free of charge, to any person
 | 
			
		||||
 *    obtaining a copy of this software and associated documentation
 | 
			
		||||
 *    files (the "Software"), to deal in the Software without
 | 
			
		||||
 *    restriction, including without limitation the rights to use,
 | 
			
		||||
 *    copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 *    copies of the Software, and to permit persons to whom the
 | 
			
		||||
 *    Software is furnished to do so, subject to the following
 | 
			
		||||
 *    conditions:
 | 
			
		||||
 * 
 | 
			
		||||
 *    This permission notice shall be included in all copies or 
 | 
			
		||||
 *    substantial portions of the Software.
 | 
			
		||||
 * 
 | 
			
		||||
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
			
		||||
 *    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 | 
			
		||||
 *    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
			
		||||
 *    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 | 
			
		||||
 *    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | 
			
		||||
 *    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
			
		||||
 *    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 | 
			
		||||
 *    OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
#include "LedControl.h"
 | 
			
		||||
 | 
			
		||||
//the opcodes for the MAX7221 and MAX7219
 | 
			
		||||
#define OP_NOOP   0
 | 
			
		||||
#define OP_DIGIT0 1
 | 
			
		||||
#define OP_DIGIT1 2
 | 
			
		||||
#define OP_DIGIT2 3
 | 
			
		||||
#define OP_DIGIT3 4
 | 
			
		||||
#define OP_DIGIT4 5
 | 
			
		||||
#define OP_DIGIT5 6
 | 
			
		||||
#define OP_DIGIT6 7
 | 
			
		||||
#define OP_DIGIT7 8
 | 
			
		||||
#define OP_DECODEMODE  9
 | 
			
		||||
#define OP_INTENSITY   10
 | 
			
		||||
#define OP_SCANLIMIT   11
 | 
			
		||||
#define OP_SHUTDOWN    12
 | 
			
		||||
#define OP_DISPLAYTEST 15
 | 
			
		||||
 | 
			
		||||
LedControl::LedControl(int dataPin, int clkPin, int csPin, int numDevices) {
 | 
			
		||||
    SPI_MOSI=dataPin;
 | 
			
		||||
    SPI_CLK=clkPin;
 | 
			
		||||
    SPI_CS=csPin;
 | 
			
		||||
    if(numDevices<=0 || numDevices>8 )
 | 
			
		||||
	numDevices=8;
 | 
			
		||||
    maxDevices=numDevices;
 | 
			
		||||
    pinMode(SPI_MOSI,OUTPUT);
 | 
			
		||||
    pinMode(SPI_CLK,OUTPUT);
 | 
			
		||||
    pinMode(SPI_CS,OUTPUT);
 | 
			
		||||
    digitalWrite(SPI_CS,HIGH);
 | 
			
		||||
    SPI_MOSI=dataPin;
 | 
			
		||||
    for(int i=0;i<64;i++) 
 | 
			
		||||
	status[i]=0x00;
 | 
			
		||||
    for(int i=0;i<maxDevices;i++) {
 | 
			
		||||
	spiTransfer(i,OP_DISPLAYTEST,0);
 | 
			
		||||
	//scanlimit is set to max on startup
 | 
			
		||||
	setScanLimit(i,7);
 | 
			
		||||
	//decode is done in source
 | 
			
		||||
	spiTransfer(i,OP_DECODEMODE,0);
 | 
			
		||||
	clearDisplay(i);
 | 
			
		||||
	//we go into shutdown-mode on startup
 | 
			
		||||
	shutdown(i,true);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int LedControl::getDeviceCount() {
 | 
			
		||||
    return maxDevices;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LedControl::shutdown(int addr, bool b) {
 | 
			
		||||
    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
    if(b)
 | 
			
		||||
	spiTransfer(addr, OP_SHUTDOWN,0);
 | 
			
		||||
    else
 | 
			
		||||
	spiTransfer(addr, OP_SHUTDOWN,1);
 | 
			
		||||
}
 | 
			
		||||
	
 | 
			
		||||
void LedControl::setScanLimit(int addr, int limit) {
 | 
			
		||||
    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
    if(limit>=0 || limit<8)
 | 
			
		||||
    	spiTransfer(addr, OP_SCANLIMIT,limit);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LedControl::setIntensity(int addr, int intensity) {
 | 
			
		||||
    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
    if(intensity>=0 || intensity<16)	
 | 
			
		||||
	spiTransfer(addr, OP_INTENSITY,intensity);
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LedControl::clearDisplay(int addr) {
 | 
			
		||||
    int offset;
 | 
			
		||||
 | 
			
		||||
    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
    offset=addr*8;
 | 
			
		||||
    for(int i=0;i<8;i++) {
 | 
			
		||||
	status[offset+i]=0;
 | 
			
		||||
	spiTransfer(addr, i+1,status[offset+i]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LedControl::setLed(int addr, int row, int column, boolean state) {
 | 
			
		||||
    int offset;
 | 
			
		||||
    byte val=0x00;
 | 
			
		||||
 | 
			
		||||
    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
    if(row<0 || row>7 || column<0 || column>7)
 | 
			
		||||
	return;
 | 
			
		||||
    offset=addr*8;
 | 
			
		||||
    val=B10000000 >> column;
 | 
			
		||||
    if(state)
 | 
			
		||||
	status[offset+row]=status[offset+row]|val;
 | 
			
		||||
    else {
 | 
			
		||||
	val=~val;
 | 
			
		||||
	status[offset+row]=status[offset+row]&val;
 | 
			
		||||
    }
 | 
			
		||||
    spiTransfer(addr, row+1,status[offset+row]);
 | 
			
		||||
}
 | 
			
		||||
	
 | 
			
		||||
void LedControl::setRow(int addr, int row, byte value) {
 | 
			
		||||
    int offset;
 | 
			
		||||
    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
    if(row<0 || row>7)
 | 
			
		||||
	return;
 | 
			
		||||
    offset=addr*8;
 | 
			
		||||
    status[offset+row]=value;
 | 
			
		||||
    spiTransfer(addr, row+1,status[offset+row]);
 | 
			
		||||
}
 | 
			
		||||
    
 | 
			
		||||
void LedControl::setColumn(int addr, int col, byte value) {
 | 
			
		||||
    byte val;
 | 
			
		||||
 | 
			
		||||
    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
    if(col<0 || col>7) 
 | 
			
		||||
	return;
 | 
			
		||||
    for(int row=0;row<8;row++) {
 | 
			
		||||
	val=value >> (7-row);
 | 
			
		||||
	val=val & 0x01;
 | 
			
		||||
	setLed(addr,row,col,val);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LedControl::setDigit(int addr, int digit, byte value, boolean dp) {
 | 
			
		||||
    int offset;
 | 
			
		||||
    byte v;
 | 
			
		||||
 | 
			
		||||
    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
    if(digit<0 || digit>7 || value>15)
 | 
			
		||||
	return;
 | 
			
		||||
    offset=addr*8;
 | 
			
		||||
    v=charTable[value];
 | 
			
		||||
    if(dp)
 | 
			
		||||
	v|=B10000000;
 | 
			
		||||
    status[offset+digit]=v;
 | 
			
		||||
    spiTransfer(addr, digit+1,v);
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LedControl::setChar(int addr, int digit, char value, boolean dp) {
 | 
			
		||||
    int offset;
 | 
			
		||||
    byte index,v;
 | 
			
		||||
 | 
			
		||||
    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
    if(digit<0 || digit>7)
 | 
			
		||||
 	return;
 | 
			
		||||
    offset=addr*8;
 | 
			
		||||
    index=(byte)value;
 | 
			
		||||
    if(index >127) {
 | 
			
		||||
	//nothing define we use the space char
 | 
			
		||||
	value=32;
 | 
			
		||||
    }
 | 
			
		||||
    v=charTable[index];
 | 
			
		||||
    if(dp)
 | 
			
		||||
	v|=B10000000;
 | 
			
		||||
    status[offset+digit]=v;
 | 
			
		||||
    spiTransfer(addr, digit+1,v);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LedControl::spiTransfer(int addr, volatile byte opcode, volatile byte data) {
 | 
			
		||||
    //Create an array with the data to shift out
 | 
			
		||||
    int offset=addr*2;
 | 
			
		||||
    int maxbytes=maxDevices*2;
 | 
			
		||||
 | 
			
		||||
    for(int i=0;i<maxbytes;i++)
 | 
			
		||||
	spidata[i]=(byte)0;
 | 
			
		||||
    //put our device data into the array
 | 
			
		||||
    spidata[offset+1]=opcode;
 | 
			
		||||
    spidata[offset]=data;
 | 
			
		||||
    //enable the line 
 | 
			
		||||
    digitalWrite(SPI_CS,LOW);
 | 
			
		||||
    //Now shift out the data 
 | 
			
		||||
    for(int i=maxbytes;i>0;i--)
 | 
			
		||||
 	shiftOut(SPI_MOSI,SPI_CLK,MSBFIRST,spidata[i-1]);
 | 
			
		||||
    //latch the data onto the display
 | 
			
		||||
    digitalWrite(SPI_CS,HIGH);
 | 
			
		||||
}    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -1,188 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 *    LedControl.h - A library for controling Leds with a MAX7219/MAX7221
 | 
			
		||||
 *    Copyright (c) 2007 Eberhard Fahle
 | 
			
		||||
 * 
 | 
			
		||||
 *    Permission is hereby granted, free of charge, to any person
 | 
			
		||||
 *    obtaining a copy of this software and associated documentation
 | 
			
		||||
 *    files (the "Software"), to deal in the Software without
 | 
			
		||||
 *    restriction, including without limitation the rights to use,
 | 
			
		||||
 *    copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 *    copies of the Software, and to permit persons to whom the
 | 
			
		||||
 *    Software is furnished to do so, subject to the following
 | 
			
		||||
 *    conditions:
 | 
			
		||||
 * 
 | 
			
		||||
 *    This permission notice shall be included in all copies or 
 | 
			
		||||
 *    substantial portions of the Software.
 | 
			
		||||
 * 
 | 
			
		||||
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
			
		||||
 *    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 | 
			
		||||
 *    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
			
		||||
 *    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 | 
			
		||||
 *    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | 
			
		||||
 *    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
			
		||||
 *    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 | 
			
		||||
 *    OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef LedControl_h
 | 
			
		||||
#define LedControl_h
 | 
			
		||||
 | 
			
		||||
#if (ARDUINO >= 100)
 | 
			
		||||
#include <Arduino.h>
 | 
			
		||||
#else
 | 
			
		||||
#include <WProgram.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Segments to be switched on for characters and digits on
 | 
			
		||||
 * 7-Segment Displays
 | 
			
		||||
 */
 | 
			
		||||
const static byte charTable[128] = {
 | 
			
		||||
    B01111110,B00110000,B01101101,B01111001,B00110011,B01011011,B01011111,B01110000,
 | 
			
		||||
    B01111111,B01111011,B01110111,B00011111,B00001101,B00111101,B01001111,B01000111,
 | 
			
		||||
    B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
 | 
			
		||||
    B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
 | 
			
		||||
    B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
 | 
			
		||||
    B00000000,B00000000,B00000000,B00000000,B10000000,B00000001,B10000000,B00000000,
 | 
			
		||||
    B01111110,B00110000,B01101101,B01111001,B00110011,B01011011,B01011111,B01110000,
 | 
			
		||||
    B01111111,B01111011,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
 | 
			
		||||
    B00000000,B01110111,B00011111,B00001101,B00111101,B01001111,B01000111,B00000000,
 | 
			
		||||
    B00110111,B00000000,B00000000,B00000000,B00001110,B00000000,B00000000,B00000000,
 | 
			
		||||
    B01100111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
 | 
			
		||||
    B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001000,
 | 
			
		||||
    B00000000,B01110111,B00011111,B00001101,B00111101,B01001111,B01000111,B00000000,
 | 
			
		||||
    B00110111,B00000000,B00000000,B00000000,B00001110,B00000000,B00000000,B00000000,
 | 
			
		||||
    B01100111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
 | 
			
		||||
    B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class LedControl {
 | 
			
		||||
 private :
 | 
			
		||||
    /* The array for shifting the data to the devices */
 | 
			
		||||
    byte spidata[16];
 | 
			
		||||
    /* Send out a single command to the device */
 | 
			
		||||
    void spiTransfer(int addr, byte opcode, byte data);
 | 
			
		||||
 | 
			
		||||
    /* We keep track of the led-status for all 8 devices in this array */
 | 
			
		||||
    byte status[64];
 | 
			
		||||
    /* Data is shifted out of this pin*/
 | 
			
		||||
    int SPI_MOSI;
 | 
			
		||||
    /* The clock is signaled on this pin */
 | 
			
		||||
    int SPI_CLK;
 | 
			
		||||
    /* This one is driven LOW for chip selectzion */
 | 
			
		||||
    int SPI_CS;
 | 
			
		||||
    /* The maximum number of devices we use */
 | 
			
		||||
    int maxDevices;
 | 
			
		||||
    
 | 
			
		||||
 public:
 | 
			
		||||
    /* 
 | 
			
		||||
     * Create a new controler 
 | 
			
		||||
     * Params :
 | 
			
		||||
     * dataPin		pin on the Arduino where data gets shifted out
 | 
			
		||||
     * clockPin		pin for the clock
 | 
			
		||||
     * csPin		pin for selecting the device 
 | 
			
		||||
     * numDevices	maximum number of devices that can be controled
 | 
			
		||||
     */
 | 
			
		||||
    LedControl(int dataPin, int clkPin, int csPin, int numDevices=1);
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * Gets the number of devices attached to this LedControl.
 | 
			
		||||
     * Returns :
 | 
			
		||||
     * int	the number of devices on this LedControl
 | 
			
		||||
     */
 | 
			
		||||
    int getDeviceCount();
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Set the shutdown (power saving) mode for the device
 | 
			
		||||
     * Params :
 | 
			
		||||
     * addr	The address of the display to control
 | 
			
		||||
     * status	If true the device goes into power-down mode. Set to false
 | 
			
		||||
     *		for normal operation.
 | 
			
		||||
     */
 | 
			
		||||
    void shutdown(int addr, bool status);
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Set the number of digits (or rows) to be displayed.
 | 
			
		||||
     * See datasheet for sideeffects of the scanlimit on the brightness
 | 
			
		||||
     * of the display.
 | 
			
		||||
     * Params :
 | 
			
		||||
     * addr	address of the display to control
 | 
			
		||||
     * limit	number of digits to be displayed (1..8)
 | 
			
		||||
     */
 | 
			
		||||
    void setScanLimit(int addr, int limit);
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Set the brightness of the display.
 | 
			
		||||
     * Params:
 | 
			
		||||
     * addr		the address of the display to control
 | 
			
		||||
     * intensity	the brightness of the display. (0..15)
 | 
			
		||||
     */
 | 
			
		||||
    void setIntensity(int addr, int intensity);
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Switch all Leds on the display off. 
 | 
			
		||||
     * Params:
 | 
			
		||||
     * addr	address of the display to control
 | 
			
		||||
     */
 | 
			
		||||
    void clearDisplay(int addr);
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Set the status of a single Led.
 | 
			
		||||
     * Params :
 | 
			
		||||
     * addr	address of the display 
 | 
			
		||||
     * row	the row of the Led (0..7)
 | 
			
		||||
     * col	the column of the Led (0..7)
 | 
			
		||||
     * state	If true the led is switched on, 
 | 
			
		||||
     *		if false it is switched off
 | 
			
		||||
     */
 | 
			
		||||
    void setLed(int addr, int row, int col, boolean state);
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Set all 8 Led's in a row to a new state
 | 
			
		||||
     * Params:
 | 
			
		||||
     * addr	address of the display
 | 
			
		||||
     * row	row which is to be set (0..7)
 | 
			
		||||
     * value	each bit set to 1 will light up the
 | 
			
		||||
     *		corresponding Led.
 | 
			
		||||
     */
 | 
			
		||||
    void setRow(int addr, int row, byte value);
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Set all 8 Led's in a column to a new state
 | 
			
		||||
     * Params:
 | 
			
		||||
     * addr	address of the display
 | 
			
		||||
     * col	column which is to be set (0..7)
 | 
			
		||||
     * value	each bit set to 1 will light up the
 | 
			
		||||
     *		corresponding Led.
 | 
			
		||||
     */
 | 
			
		||||
    void setColumn(int addr, int col, byte value);
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Display a hexadecimal digit on a 7-Segment Display
 | 
			
		||||
     * Params:
 | 
			
		||||
     * addr	address of the display
 | 
			
		||||
     * digit	the position of the digit on the display (0..7)
 | 
			
		||||
     * value	the value to be displayed. (0x00..0x0F)
 | 
			
		||||
     * dp	sets the decimal point.
 | 
			
		||||
     */
 | 
			
		||||
    void setDigit(int addr, int digit, byte value, boolean dp);
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Display a character on a 7-Segment display.
 | 
			
		||||
     * There are only a few characters that make sense here :
 | 
			
		||||
     *	'0','1','2','3','4','5','6','7','8','9','0',
 | 
			
		||||
     *  'A','b','c','d','E','F','H','L','P',
 | 
			
		||||
     *  '.','-','_',' ' 
 | 
			
		||||
     * Params:
 | 
			
		||||
     * addr	address of the display
 | 
			
		||||
     * digit	the position of the character on the display (0..7)
 | 
			
		||||
     * value	the character to be displayed. 
 | 
			
		||||
     * dp	sets the decimal point.
 | 
			
		||||
     */
 | 
			
		||||
    void setChar(int addr, int digit, char value, boolean dp);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif	//LedControl.h
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -1,310 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 *    LedControl.cpp - A library for controling Leds with a MAX7219/MAX7221
 | 
			
		||||
 *    Copyright (c) 2007 Eberhard Fahle
 | 
			
		||||
 * 
 | 
			
		||||
 *    Permission is hereby granted, free of charge, to any person
 | 
			
		||||
 *    obtaining a copy of this software and associated documentation
 | 
			
		||||
 *    files (the "Software"), to deal in the Software without
 | 
			
		||||
 *    restriction, including without limitation the rights to use,
 | 
			
		||||
 *    copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 *    copies of the Software, and to permit persons to whom the
 | 
			
		||||
 *    Software is furnished to do so, subject to the following
 | 
			
		||||
 *    conditions:
 | 
			
		||||
 * 
 | 
			
		||||
 *    This permission notice shall be included in all copies or 
 | 
			
		||||
 *    substantial portions of the Software.
 | 
			
		||||
 * 
 | 
			
		||||
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
			
		||||
 *    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 | 
			
		||||
 *    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
			
		||||
 *    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 | 
			
		||||
 *    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | 
			
		||||
 *    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
			
		||||
 *    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 | 
			
		||||
 *    OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
#include "LedControl.h"
 | 
			
		||||
 | 
			
		||||
//the opcodes for the MAX7221 and MAX7219
 | 
			
		||||
#define OP_NOOP   0
 | 
			
		||||
#define OP_DIGIT0 1
 | 
			
		||||
#define OP_DIGIT1 2
 | 
			
		||||
#define OP_DIGIT2 3
 | 
			
		||||
#define OP_DIGIT3 4
 | 
			
		||||
#define OP_DIGIT4 5
 | 
			
		||||
#define OP_DIGIT5 6
 | 
			
		||||
#define OP_DIGIT6 7
 | 
			
		||||
#define OP_DIGIT7 8
 | 
			
		||||
#define OP_DECODEMODE  9
 | 
			
		||||
#define OP_INTENSITY   10
 | 
			
		||||
#define OP_SCANLIMIT   11
 | 
			
		||||
#define OP_SHUTDOWN    12
 | 
			
		||||
#define OP_DISPLAYTEST 15
 | 
			
		||||
 | 
			
		||||
LedControl::LedControl(int dataPin, int clkPin, int csPin, int numDevices, bool anode) {
 | 
			
		||||
    SPI_MOSI=dataPin;
 | 
			
		||||
    SPI_CLK=clkPin;
 | 
			
		||||
    SPI_CS=csPin;
 | 
			
		||||
    if(numDevices<=0 || numDevices>8 )
 | 
			
		||||
	numDevices=8;
 | 
			
		||||
    maxDevices=numDevices;
 | 
			
		||||
    anodeMode=anode;
 | 
			
		||||
    pinMode(SPI_MOSI,OUTPUT);
 | 
			
		||||
    pinMode(SPI_CLK,OUTPUT);
 | 
			
		||||
    pinMode(SPI_CS,OUTPUT);
 | 
			
		||||
    digitalWrite(SPI_CS,HIGH);
 | 
			
		||||
    SPI_MOSI=dataPin;
 | 
			
		||||
    for(int i=0;i<64;i++) { 
 | 
			
		||||
 	status[i]=0x00;
 | 
			
		||||
 	statusTransposed[i]=0x00;
 | 
			
		||||
    }
 | 
			
		||||
	for(int i=0;i<maxDevices;i++) {
 | 
			
		||||
	spiTransfer(i,OP_DISPLAYTEST,0);
 | 
			
		||||
	//scanlimit is set to max on startup
 | 
			
		||||
	setScanLimit(i,7);
 | 
			
		||||
	//decode is done in source
 | 
			
		||||
	spiTransfer(i,OP_DECODEMODE,0);
 | 
			
		||||
	clearDisplay(i);
 | 
			
		||||
	//we go into shutdown-mode on startup
 | 
			
		||||
	shutdown(i,true);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int LedControl::getDeviceCount() {
 | 
			
		||||
    return maxDevices;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LedControl::shutdown(int addr, bool b) {
 | 
			
		||||
    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
    if(b)
 | 
			
		||||
	spiTransfer(addr, OP_SHUTDOWN,0);
 | 
			
		||||
    else
 | 
			
		||||
	spiTransfer(addr, OP_SHUTDOWN,1);
 | 
			
		||||
}
 | 
			
		||||
	
 | 
			
		||||
void LedControl::setScanLimit(int addr, int limit) {
 | 
			
		||||
    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
    if(limit>=0 || limit<8)
 | 
			
		||||
    	spiTransfer(addr, OP_SCANLIMIT,limit);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LedControl::setIntensity(int addr, int intensity) {
 | 
			
		||||
    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
    if(intensity>=0 || intensity<16)	
 | 
			
		||||
	spiTransfer(addr, OP_INTENSITY,intensity);
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LedControl::clearDisplay(int addr) {
 | 
			
		||||
    int offset;
 | 
			
		||||
 | 
			
		||||
    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
    offset=addr*8;
 | 
			
		||||
    for(int i=0;i<8;i++) {
 | 
			
		||||
	status[offset+i]=0;
 | 
			
		||||
    }
 | 
			
		||||
     if (anodeMode) {
 | 
			
		||||
     	transposeData(addr);
 | 
			
		||||
     	for(int i=0;i<8;i++) {
 | 
			
		||||
 	    spiTransfer(addr, i+1, statusTransposed[offset+i]);
 | 
			
		||||
     	}
 | 
			
		||||
     } else {
 | 
			
		||||
     	for(int i=0;i<8;i++) {
 | 
			
		||||
 	    spiTransfer(addr, i+1, status[offset+i]);
 | 
			
		||||
     	}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LedControl::setLed(int addr, int row, int column, boolean state) {
 | 
			
		||||
    int offset;
 | 
			
		||||
    byte val=0x00;
 | 
			
		||||
 | 
			
		||||
    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
    if(row<0 || row>7 || column<0 || column>7)
 | 
			
		||||
	return;
 | 
			
		||||
    offset=addr*8;
 | 
			
		||||
    val=B10000000 >> column;
 | 
			
		||||
    if(state)
 | 
			
		||||
	status[offset+row]=status[offset+row]|val;
 | 
			
		||||
    else {
 | 
			
		||||
	val=~val;
 | 
			
		||||
	status[offset+row]=status[offset+row]&val;
 | 
			
		||||
    }
 | 
			
		||||
    spiTransfer(addr, row+1,status[offset+row]);
 | 
			
		||||
}
 | 
			
		||||
	
 | 
			
		||||
void LedControl::setRow(int addr, int row, byte value) {
 | 
			
		||||
    int offset;
 | 
			
		||||
    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
    if(row<0 || row>7)
 | 
			
		||||
	return;
 | 
			
		||||
    offset=addr*8;
 | 
			
		||||
    status[offset+row]=value;
 | 
			
		||||
    spiTransfer(addr, row+1,status[offset+row]);
 | 
			
		||||
}
 | 
			
		||||
    
 | 
			
		||||
void LedControl::setColumn(int addr, int col, byte value) {
 | 
			
		||||
    byte val;
 | 
			
		||||
 | 
			
		||||
    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
    if(col<0 || col>7) 
 | 
			
		||||
	return;
 | 
			
		||||
    for(int row=0;row<8;row++) {
 | 
			
		||||
	val=value >> (7-row);
 | 
			
		||||
	val=val & 0x01;
 | 
			
		||||
	setLed(addr,row,col,val);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LedControl::setDigit(int addr, int digit, byte value, boolean dp) {
 | 
			
		||||
    int offset;
 | 
			
		||||
    byte v;
 | 
			
		||||
 | 
			
		||||
    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
    if(digit<0 || digit>7 || value>15)
 | 
			
		||||
	return;
 | 
			
		||||
    offset=addr*8;
 | 
			
		||||
    v=charTable[value];
 | 
			
		||||
    if(dp)
 | 
			
		||||
	v|=B10000000;
 | 
			
		||||
    status[offset+digit]=v;
 | 
			
		||||
    if (anodeMode) {
 | 
			
		||||
     	//transpose the digit matrix
 | 
			
		||||
     	transposeData(addr);
 | 
			
		||||
     	//send the entire set of digits
 | 
			
		||||
     	for(int i=0;i<8;i++) {
 | 
			
		||||
 	    spiTransfer(addr, i+1, statusTransposed[offset+i]);
 | 
			
		||||
     	}
 | 
			
		||||
     } else {
 | 
			
		||||
     	spiTransfer(addr, digit+1, v);
 | 
			
		||||
     }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LedControl::setChar(int addr, int digit, char value, boolean dp) {
 | 
			
		||||
    int offset;
 | 
			
		||||
    byte index,v;
 | 
			
		||||
 | 
			
		||||
    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
    if(digit<0 || digit>7)
 | 
			
		||||
 	return;
 | 
			
		||||
   
 | 
			
		||||
    offset=addr*8;
 | 
			
		||||
    index=(byte)value;
 | 
			
		||||
    if(index >127) {
 | 
			
		||||
	//nothing defined we use the space char
 | 
			
		||||
	value=32;
 | 
			
		||||
    }
 | 
			
		||||
    v=charTable[index];
 | 
			
		||||
    if(dp)
 | 
			
		||||
	v|=B10000000;
 | 
			
		||||
    status[offset+digit]=v;
 | 
			
		||||
    if (anodeMode) {
 | 
			
		||||
	   	//transpose the digit matrix
 | 
			
		||||
   		transposeData(addr);
 | 
			
		||||
   		//send the entire set of digits
 | 
			
		||||
   		for(int i=0;i<8;i++) {
 | 
			
		||||
		spiTransfer(addr, i+1, statusTransposed[offset+i]);
 | 
			
		||||
   		}
 | 
			
		||||
    } else {
 | 
			
		||||
   		spiTransfer(addr, digit+1, v);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LedControl::spiTransfer(int addr, volatile byte opcode, volatile byte data) {
 | 
			
		||||
    //Create an array with the data to shift out
 | 
			
		||||
    int offset=addr*2;
 | 
			
		||||
    int maxbytes=maxDevices*2;
 | 
			
		||||
 | 
			
		||||
    for(int i=0;i<maxbytes;i++)
 | 
			
		||||
	spidata[i]=(byte)0;
 | 
			
		||||
    //put our device data into the array
 | 
			
		||||
    spidata[offset+1]=opcode;
 | 
			
		||||
    spidata[offset]=data;
 | 
			
		||||
    //enable the line 
 | 
			
		||||
    digitalWrite(SPI_CS,LOW);
 | 
			
		||||
    //Now shift out the data 
 | 
			
		||||
    for(int i=maxbytes;i>0;i--)
 | 
			
		||||
 	shiftOut(SPI_MOSI,SPI_CLK,MSBFIRST,spidata[i-1]);
 | 
			
		||||
    //latch the data onto the display
 | 
			
		||||
    digitalWrite(SPI_CS,HIGH);
 | 
			
		||||
}    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void LedControl::transposeData(int addr) {
 | 
			
		||||
 int offset=addr*8;
 | 
			
		||||
 byte a0, a1, a2, a3, a4, a5, a6, a7,
 | 
			
		||||
      b0, b1, b2, b3, b4, b5, b6, b7;
 | 
			
		||||
 
 | 
			
		||||
 // Perform a bitwise transpose operation on an 8x8 bit matrix, stored as 8-byte array.
 | 
			
		||||
 // We have to use the naive method because we're working on a 16-bit microprocessor.
 | 
			
		||||
 | 
			
		||||
 // Load the array into eight one-byte variables.
 | 
			
		||||
 a0 = status[offset];
 | 
			
		||||
 a1 = status[offset+1];
 | 
			
		||||
 a2 = status[offset+2];
 | 
			
		||||
 a3 = status[offset+3];
 | 
			
		||||
 a4 = status[offset+4];
 | 
			
		||||
 a5 = status[offset+5];
 | 
			
		||||
 a6 = status[offset+6];
 | 
			
		||||
 a7 = status[offset+7];
 | 
			
		||||
 
 | 
			
		||||
 // Magic happens. Credit goes to: http://www.hackersdelight.org/HDcode/transpose8.c.txt
 | 
			
		||||
 b0 = (a0 & 128)    | (a1 & 128)/2  | (a2 & 128)/4  | (a3 & 128)/8 |
 | 
			
		||||
      (a4 & 128)/16 | (a5 & 128)/32 | (a6 & 128)/64 | (a7      )/128;
 | 
			
		||||
 b1 = (a0 &  64)*2  | (a1 &  64)    | (a2 &  64)/2  | (a3 &  64)/4 |
 | 
			
		||||
      (a4 &  64)/8  | (a5 &  64)/16 | (a6 &  64)/32 | (a7 &  64)/64;
 | 
			
		||||
 b2 = (a0 &  32)*4  | (a1 &  32)*2  | (a2 &  32)    | (a3 &  32)/2 |
 | 
			
		||||
      (a4 &  32)/4  | (a5 &  32)/8  | (a6 &  32)/16 | (a7 &  32)/32;
 | 
			
		||||
 b3 = (a0 &  16)*8  | (a1 &  16)*4  | (a2 &  16)*2  | (a3 &  16)   |
 | 
			
		||||
      (a4 &  16)/2  | (a5 &  16)/4  | (a6 &  16)/8  | (a7 &  16)/16;
 | 
			
		||||
 b4 = (a0 &   8)*16 | (a1 &   8)*8  | (a2 &   8)*4  | (a3 &   8)*2 |
 | 
			
		||||
      (a4 &   8)    | (a5 &   8)/2  | (a6 &   8)/4  | (a7 &   8)/8;
 | 
			
		||||
 b5 = (a0 &   4)*32 | (a1 &   4)*16 | (a2 &   4)*8  | (a3 &   4)*4 |
 | 
			
		||||
      (a4 &   4)*2  | (a5 &   4)    | (a6 &   4)/2  | (a7 &   4)/4;
 | 
			
		||||
 b6 = (a0 &   2)*64 | (a1 &   2)*32 | (a2 &   2)*16 | (a3 &   2)*8 |
 | 
			
		||||
      (a4 &   2)*4  | (a5 &   2)*2  | (a6 &   2)    | (a7 &   2)/2;
 | 
			
		||||
 b7 = (a0      )*128| (a1 &   1)*64 | (a2 &   1)*32 | (a3 &   1)*16|
 | 
			
		||||
      (a4 &   1)*8  | (a5 &   1)*4  | (a6 &   1)*2  | (a7 &   1);
 | 
			
		||||
 | 
			
		||||
 // Assemble into output array.
 | 
			
		||||
 statusTransposed[offset] = b0;
 | 
			
		||||
 statusTransposed[offset+1] = b1;
 | 
			
		||||
 statusTransposed[offset+2] = b2;
 | 
			
		||||
 statusTransposed[offset+3] = b3;
 | 
			
		||||
 statusTransposed[offset+4] = b4;
 | 
			
		||||
 statusTransposed[offset+5] = b5;
 | 
			
		||||
 statusTransposed[offset+6] = b6;
 | 
			
		||||
 statusTransposed[offset+7] = b7;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LedControl::setDirectDigit(int addr, int digit, byte value) {
 | 
			
		||||
   int offset;
 | 
			
		||||
 | 
			
		||||
   if(addr<0 || addr>=maxDevices)
 | 
			
		||||
	return;
 | 
			
		||||
   if(digit<0 || digit>7)
 | 
			
		||||
	return;
 | 
			
		||||
   offset=addr*8;
 | 
			
		||||
   status[offset+digit]=value;
 | 
			
		||||
   if (anodeMode) {
 | 
			
		||||
   	transposeData(addr);
 | 
			
		||||
   	for(int i=0;i<8;i++) {
 | 
			
		||||
	    spiTransfer(addr, i+1, statusTransposed[offset+i]);
 | 
			
		||||
   	}
 | 
			
		||||
   } else {
 | 
			
		||||
   	spiTransfer(addr, digit+1, value);
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1,217 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 *    LedControl.h - A library for controling Leds with a MAX7219/MAX7221
 | 
			
		||||
 *    Copyright (c) 2007 Eberhard Fahle
 | 
			
		||||
 * 
 | 
			
		||||
 *    Permission is hereby granted, free of charge, to any person
 | 
			
		||||
 *    obtaining a copy of this software and associated documentation
 | 
			
		||||
 *    files (the "Software"), to deal in the Software without
 | 
			
		||||
 *    restriction, including without limitation the rights to use,
 | 
			
		||||
 *    copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 *    copies of the Software, and to permit persons to whom the
 | 
			
		||||
 *    Software is furnished to do so, subject to the following
 | 
			
		||||
 *    conditions:
 | 
			
		||||
 * 
 | 
			
		||||
 *    This permission notice shall be included in all copies or 
 | 
			
		||||
 *    substantial portions of the Software.
 | 
			
		||||
 * 
 | 
			
		||||
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
			
		||||
 *    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 | 
			
		||||
 *    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
			
		||||
 *    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 | 
			
		||||
 *    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | 
			
		||||
 *    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
			
		||||
 *    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 | 
			
		||||
 *    OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef LedControl_h
 | 
			
		||||
#define LedControl_h
 | 
			
		||||
 | 
			
		||||
#if (ARDUINO >= 100)
 | 
			
		||||
#include <Arduino.h>
 | 
			
		||||
#else
 | 
			
		||||
#include <WProgram.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Segments to be switched on for characters and digits on
 | 
			
		||||
 * 7-Segment Displays
 | 
			
		||||
 */
 | 
			
		||||
const static byte charTable[128] = {
 | 
			
		||||
    B01111110,B00110000,B01101101,B01111001,B00110011,B01011011,B01011111,B01110000,
 | 
			
		||||
    B01111111,B01111011,B01110111,B00011111,B00001101,B00111101,B01001111,B01000111,
 | 
			
		||||
    B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
 | 
			
		||||
    B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
 | 
			
		||||
    B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
 | 
			
		||||
    B00000000,B00000000,B00000000,B00000000,B10000000,B00000001,B10000000,B00000000,
 | 
			
		||||
    B01111110,B00110000,B01101101,B01111001,B00110011,B01011011,B01011111,B01110000,
 | 
			
		||||
    B01111111,B01111011,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
 | 
			
		||||
    B00000000,B01110111,B00011111,B00001101,B00111101,B01001111,B01000111,B00000000,
 | 
			
		||||
    B00110111,B00000000,B00000000,B00000000,B00001110,B00000000,B00000000,B00000000,
 | 
			
		||||
    B01100111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
 | 
			
		||||
    B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001000,
 | 
			
		||||
    B00000000,B01110111,B00011111,B00001101,B00111101,B01001111,B01000111,B00000000,
 | 
			
		||||
    B00110111,B00000000,B00000000,B00000000,B00001110,B00000000,B00000000,B00000000,
 | 
			
		||||
    B01100111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
 | 
			
		||||
    B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class LedControl {
 | 
			
		||||
 private :
 | 
			
		||||
    /* The array for shifting the data to the devices */
 | 
			
		||||
    byte spidata[16];
 | 
			
		||||
    /* Send out a single command to the device */
 | 
			
		||||
    void spiTransfer(int addr, byte opcode, byte data);
 | 
			
		||||
 | 
			
		||||
    /* We keep track of the led-status for all 8 devices in this array */
 | 
			
		||||
    byte status[64];
 | 
			
		||||
    /* We also keep track of the transposed version */
 | 
			
		||||
    byte statusTransposed[64];
 | 
			
		||||
    /* Data is shifted out of this pin*/
 | 
			
		||||
    int SPI_MOSI;
 | 
			
		||||
    /* The clock is signaled on this pin */
 | 
			
		||||
    int SPI_CLK;
 | 
			
		||||
    /* This one is driven LOW for chip selectzion */
 | 
			
		||||
    int SPI_CS;
 | 
			
		||||
    /* The maximum number of devices we use */
 | 
			
		||||
    int maxDevices;
 | 
			
		||||
    /* Choose whether we're using common cathode or common anode displays */
 | 
			
		||||
    bool anodeMode;
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
 public:
 | 
			
		||||
    /* 
 | 
			
		||||
     * Create a new controler 
 | 
			
		||||
     * Params :
 | 
			
		||||
     * dataPin		pin on the Arduino where data gets shifted out
 | 
			
		||||
     * clockPin		pin for the clock
 | 
			
		||||
     * csPin		pin for selecting the device 
 | 
			
		||||
     * numDevices	maximum number of devices that can be controled
 | 
			
		||||
     * anode		false for common-cathode displays, true for common-anode displays
 | 
			
		||||
     */
 | 
			
		||||
	LedControl(int dataPin, int clkPin, int csPin, int numDevices=1, bool anode=false);
 | 
			
		||||
    /*
 | 
			
		||||
     * Gets the number of devices attached to this LedControl.
 | 
			
		||||
     * Returns :
 | 
			
		||||
     * int	the number of devices on this LedControl
 | 
			
		||||
     */
 | 
			
		||||
    int getDeviceCount();
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Set the shutdown (power saving) mode for the device
 | 
			
		||||
     * Params :
 | 
			
		||||
     * addr	The address of the display to control
 | 
			
		||||
     * status	If true the device goes into power-down mode. Set to false
 | 
			
		||||
     *		for normal operation.
 | 
			
		||||
     */
 | 
			
		||||
    void shutdown(int addr, bool status);
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Set the number of digits (or rows) to be displayed.
 | 
			
		||||
     * See datasheet for sideeffects of the scanlimit on the brightness
 | 
			
		||||
     * of the display.
 | 
			
		||||
     * Params :
 | 
			
		||||
     * addr	address of the display to control
 | 
			
		||||
     * limit	number of digits to be displayed (1..8)
 | 
			
		||||
     */
 | 
			
		||||
    void setScanLimit(int addr, int limit);
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Set the brightness of the display.
 | 
			
		||||
     * Params:
 | 
			
		||||
     * addr		the address of the display to control
 | 
			
		||||
     * intensity	the brightness of the display. (0..15)
 | 
			
		||||
     */
 | 
			
		||||
    void setIntensity(int addr, int intensity);
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Switch all Leds on the display off. 
 | 
			
		||||
     * Params:
 | 
			
		||||
     * addr	address of the display to control
 | 
			
		||||
     */
 | 
			
		||||
    void clearDisplay(int addr);
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Set the status of a single Led.
 | 
			
		||||
     * Params :
 | 
			
		||||
     * addr	address of the display 
 | 
			
		||||
     * row	the row of the Led (0..7)
 | 
			
		||||
     * col	the column of the Led (0..7)
 | 
			
		||||
     * state	If true the led is switched on, 
 | 
			
		||||
     *		if false it is switched off
 | 
			
		||||
     */
 | 
			
		||||
    void setLed(int addr, int row, int col, boolean state);
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Set all 8 Led's in a row to a new state
 | 
			
		||||
     * Params:
 | 
			
		||||
     * addr	address of the display
 | 
			
		||||
     * row	row which is to be set (0..7)
 | 
			
		||||
     * value	each bit set to 1 will light up the
 | 
			
		||||
     *		corresponding Led.
 | 
			
		||||
     */
 | 
			
		||||
    void setRow(int addr, int row, byte value);
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Set all 8 Led's in a column to a new state
 | 
			
		||||
     * Params:
 | 
			
		||||
     * addr	address of the display
 | 
			
		||||
     * col	column which is to be set (0..7)
 | 
			
		||||
     * value	each bit set to 1 will light up the
 | 
			
		||||
     *		corresponding Led.
 | 
			
		||||
     */
 | 
			
		||||
    void setColumn(int addr, int col, byte value);
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Display a hexadecimal digit on a 7-Segment Display
 | 
			
		||||
     * Params:
 | 
			
		||||
     * addr	address of the display
 | 
			
		||||
     * digit	the position of the digit on the display (0..7)
 | 
			
		||||
     * value	the value to be displayed. (0x00..0x0F)
 | 
			
		||||
     * dp	sets the decimal point.
 | 
			
		||||
     */
 | 
			
		||||
    void setDigit(int addr, int digit, byte value, boolean dp);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /* 
 | 
			
		||||
     * Display a character on a 7-Segment display.
 | 
			
		||||
     * There are only a few characters that make sense here :
 | 
			
		||||
     *	'0','1','2','3','4','5','6','7','8','9','0',
 | 
			
		||||
     *  'A','b','c','d','E','F','H','L','P',
 | 
			
		||||
     *  '.','-','_',' ' 
 | 
			
		||||
     * Params:
 | 
			
		||||
     * addr	address of the display
 | 
			
		||||
     * digit	the position of the character on the display (0..7)
 | 
			
		||||
     * value	the character to be displayed. 
 | 
			
		||||
     * dp	sets the decimal point.
 | 
			
		||||
     */
 | 
			
		||||
    void setChar(int addr, int digit, char value, boolean dp);
 | 
			
		||||
 | 
			
		||||
     
 | 
			
		||||
     /*
 | 
			
		||||
      * Transpose data matrix for use with common-anode displays.
 | 
			
		||||
      * Params:
 | 
			
		||||
      * addr	address of the display
 | 
			
		||||
      */
 | 
			
		||||
     void transposeData(int addr);
 | 
			
		||||
     
 | 
			
		||||
     /*
 | 
			
		||||
      * Light up segments of a 7-segment display directly by passing a binary value.
 | 
			
		||||
      * The eight bits of the byte each refer to a segment:
 | 
			
		||||
      *     Byte:   0 0 0 0 0 0 0 0
 | 
			
		||||
      *  Segments: DP A B C D E F G
 | 
			
		||||
      * Params:
 | 
			
		||||
      * addr	address of the display
 | 
			
		||||
      * digit	the position of the character on the display (0..7)
 | 
			
		||||
      * value	the binary value to be displayed
 | 
			
		||||
      */
 | 
			
		||||
     void setDirectDigit(int addr, int digit, byte value);
 | 
			
		||||
 
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif	//LedControl.h
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -1,228 +0,0 @@
 | 
			
		||||
Common subdirectories: LedControl-unpatched/examples and LedControl/examples
 | 
			
		||||
diff -u LedControl-unpatched/LedControl.cpp LedControl/LedControl.cpp
 | 
			
		||||
--- LedControl-unpatched/LedControl.cpp	2008-10-14 02:21:21.000000000 -0700
 | 
			
		||||
+++ LedControl/LedControl.cpp	2012-09-02 01:24:35.000000000 -0700
 | 
			
		||||
@@ -35,20 +35,23 @@
 | 
			
		||||
 #define OP_SHUTDOWN    12
 | 
			
		||||
 #define OP_DISPLAYTEST 15
 | 
			
		||||
 
 | 
			
		||||
-LedControl::LedControl(int dataPin, int clkPin, int csPin, int numDevices) {
 | 
			
		||||
+LedControl::LedControl(int dataPin, int clkPin, int csPin, int numDevices, bool anode) {
 | 
			
		||||
     SPI_MOSI=dataPin;
 | 
			
		||||
     SPI_CLK=clkPin;
 | 
			
		||||
     SPI_CS=csPin;
 | 
			
		||||
     if(numDevices<=0 || numDevices>8 )
 | 
			
		||||
 	numDevices=8;
 | 
			
		||||
     maxDevices=numDevices;
 | 
			
		||||
+    anodeMode=anode;
 | 
			
		||||
     pinMode(SPI_MOSI,OUTPUT);
 | 
			
		||||
     pinMode(SPI_CLK,OUTPUT);
 | 
			
		||||
     pinMode(SPI_CS,OUTPUT);
 | 
			
		||||
     digitalWrite(SPI_CS,HIGH);
 | 
			
		||||
     SPI_MOSI=dataPin;
 | 
			
		||||
-    for(int i=0;i<64;i++) 
 | 
			
		||||
+    for(int i=0;i<64;i++) { 
 | 
			
		||||
 	status[i]=0x00;
 | 
			
		||||
+	statusTransposed[i]=0x00;
 | 
			
		||||
+    }
 | 
			
		||||
     for(int i=0;i<maxDevices;i++) {
 | 
			
		||||
 	spiTransfer(i,OP_DISPLAYTEST,0);
 | 
			
		||||
 	//scanlimit is set to max on startup
 | 
			
		||||
@@ -97,7 +100,16 @@
 | 
			
		||||
     offset=addr*8;
 | 
			
		||||
     for(int i=0;i<8;i++) {
 | 
			
		||||
 	status[offset+i]=0;
 | 
			
		||||
-	spiTransfer(addr, i+1,status[offset+i]);
 | 
			
		||||
+    }
 | 
			
		||||
+    if (anodeMode) {
 | 
			
		||||
+    	transposeData(addr);
 | 
			
		||||
+    	for(int i=0;i<8;i++) {
 | 
			
		||||
+	    spiTransfer(addr, i+1, statusTransposed[offset+i]);
 | 
			
		||||
+    	}
 | 
			
		||||
+    } else {
 | 
			
		||||
+    	for(int i=0;i<8;i++) {
 | 
			
		||||
+	    spiTransfer(addr, i+1, status[offset+i]);
 | 
			
		||||
+    	}
 | 
			
		||||
     }
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -158,8 +170,16 @@
 | 
			
		||||
     if(dp)
 | 
			
		||||
 	v|=B10000000;
 | 
			
		||||
     status[offset+digit]=v;
 | 
			
		||||
-    spiTransfer(addr, digit+1,v);
 | 
			
		||||
-    
 | 
			
		||||
+    if (anodeMode) {
 | 
			
		||||
+    	//transpose the digit matrix
 | 
			
		||||
+    	transposeData(addr);
 | 
			
		||||
+    	//send the entire set of digits
 | 
			
		||||
+    	for(int i=0;i<8;i++) {
 | 
			
		||||
+	    spiTransfer(addr, i+1, statusTransposed[offset+i]);
 | 
			
		||||
+    	}
 | 
			
		||||
+    } else {
 | 
			
		||||
+    	spiTransfer(addr, digit+1, v);
 | 
			
		||||
+    }
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 void LedControl::setChar(int addr, int digit, char value, boolean dp) {
 | 
			
		||||
@@ -173,14 +193,23 @@
 | 
			
		||||
     offset=addr*8;
 | 
			
		||||
     index=(byte)value;
 | 
			
		||||
     if(index >127) {
 | 
			
		||||
-	//nothing define we use the space char
 | 
			
		||||
+	//nothing defined we use the space char
 | 
			
		||||
 	value=32;
 | 
			
		||||
     }
 | 
			
		||||
     v=charTable[index];
 | 
			
		||||
     if(dp)
 | 
			
		||||
 	v|=B10000000;
 | 
			
		||||
     status[offset+digit]=v;
 | 
			
		||||
-    spiTransfer(addr, digit+1,v);
 | 
			
		||||
+    if (anodeMode) {
 | 
			
		||||
+    	//transpose the digit matrix
 | 
			
		||||
+    	transposeData(addr);
 | 
			
		||||
+    	//send the entire set of digits
 | 
			
		||||
+    	for(int i=0;i<8;i++) {
 | 
			
		||||
+	    spiTransfer(addr, i+1, statusTransposed[offset+i]);
 | 
			
		||||
+    	}
 | 
			
		||||
+    } else {
 | 
			
		||||
+    	spiTransfer(addr, digit+1, v);
 | 
			
		||||
+    }
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 void LedControl::spiTransfer(int addr, volatile byte opcode, volatile byte data) {
 | 
			
		||||
@@ -202,4 +231,73 @@
 | 
			
		||||
     digitalWrite(SPI_CS,HIGH);
 | 
			
		||||
 }    
 | 
			
		||||
 
 | 
			
		||||
+void LedControl::transposeData(int addr) {
 | 
			
		||||
+  int offset=addr*8;
 | 
			
		||||
+  byte a0, a1, a2, a3, a4, a5, a6, a7,
 | 
			
		||||
+       b0, b1, b2, b3, b4, b5, b6, b7;
 | 
			
		||||
+  
 | 
			
		||||
+  // Perform a bitwise transpose operation on an 8x8 bit matrix, stored as 8-byte array.
 | 
			
		||||
+  // We have to use the naive method because we're working on a 16-bit microprocessor.
 | 
			
		||||
+
 | 
			
		||||
+  // Load the array into eight one-byte variables.
 | 
			
		||||
+  a0 = status[offset];
 | 
			
		||||
+  a1 = status[offset+1];
 | 
			
		||||
+  a2 = status[offset+2];
 | 
			
		||||
+  a3 = status[offset+3];
 | 
			
		||||
+  a4 = status[offset+4];
 | 
			
		||||
+  a5 = status[offset+5];
 | 
			
		||||
+  a6 = status[offset+6];
 | 
			
		||||
+  a7 = status[offset+7];
 | 
			
		||||
+  
 | 
			
		||||
+  // Magic happens. Credit goes to: http://www.hackersdelight.org/HDcode/transpose8.c.txt
 | 
			
		||||
+  b0 = (a0 & 128)    | (a1 & 128)/2  | (a2 & 128)/4  | (a3 & 128)/8 |
 | 
			
		||||
+       (a4 & 128)/16 | (a5 & 128)/32 | (a6 & 128)/64 | (a7      )/128;
 | 
			
		||||
+  b1 = (a0 &  64)*2  | (a1 &  64)    | (a2 &  64)/2  | (a3 &  64)/4 |
 | 
			
		||||
+       (a4 &  64)/8  | (a5 &  64)/16 | (a6 &  64)/32 | (a7 &  64)/64;
 | 
			
		||||
+  b2 = (a0 &  32)*4  | (a1 &  32)*2  | (a2 &  32)    | (a3 &  32)/2 |
 | 
			
		||||
+       (a4 &  32)/4  | (a5 &  32)/8  | (a6 &  32)/16 | (a7 &  32)/32;
 | 
			
		||||
+  b3 = (a0 &  16)*8  | (a1 &  16)*4  | (a2 &  16)*2  | (a3 &  16)   |
 | 
			
		||||
+       (a4 &  16)/2  | (a5 &  16)/4  | (a6 &  16)/8  | (a7 &  16)/16;
 | 
			
		||||
+  b4 = (a0 &   8)*16 | (a1 &   8)*8  | (a2 &   8)*4  | (a3 &   8)*2 |
 | 
			
		||||
+       (a4 &   8)    | (a5 &   8)/2  | (a6 &   8)/4  | (a7 &   8)/8;
 | 
			
		||||
+  b5 = (a0 &   4)*32 | (a1 &   4)*16 | (a2 &   4)*8  | (a3 &   4)*4 |
 | 
			
		||||
+       (a4 &   4)*2  | (a5 &   4)    | (a6 &   4)/2  | (a7 &   4)/4;
 | 
			
		||||
+  b6 = (a0 &   2)*64 | (a1 &   2)*32 | (a2 &   2)*16 | (a3 &   2)*8 |
 | 
			
		||||
+       (a4 &   2)*4  | (a5 &   2)*2  | (a6 &   2)    | (a7 &   2)/2;
 | 
			
		||||
+  b7 = (a0      )*128| (a1 &   1)*64 | (a2 &   1)*32 | (a3 &   1)*16|
 | 
			
		||||
+       (a4 &   1)*8  | (a5 &   1)*4  | (a6 &   1)*2  | (a7 &   1);
 | 
			
		||||
+
 | 
			
		||||
+  // Assemble into output array.
 | 
			
		||||
+  statusTransposed[offset] = b0;
 | 
			
		||||
+  statusTransposed[offset+1] = b1;
 | 
			
		||||
+  statusTransposed[offset+2] = b2;
 | 
			
		||||
+  statusTransposed[offset+3] = b3;
 | 
			
		||||
+  statusTransposed[offset+4] = b4;
 | 
			
		||||
+  statusTransposed[offset+5] = b5;
 | 
			
		||||
+  statusTransposed[offset+6] = b6;
 | 
			
		||||
+  statusTransposed[offset+7] = b7;
 | 
			
		||||
+
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+void LedControl::setDirectDigit(int addr, int digit, byte value) {
 | 
			
		||||
+    int offset;
 | 
			
		||||
+
 | 
			
		||||
+    if(addr<0 || addr>=maxDevices)
 | 
			
		||||
+	return;
 | 
			
		||||
+    if(digit<0 || digit>7)
 | 
			
		||||
+	return;
 | 
			
		||||
+    offset=addr*8;
 | 
			
		||||
+    status[offset+digit]=value;
 | 
			
		||||
+    if (anodeMode) {
 | 
			
		||||
+    	transposeData(addr);
 | 
			
		||||
+    	for(int i=0;i<8;i++) {
 | 
			
		||||
+	    spiTransfer(addr, i+1, statusTransposed[offset+i]);
 | 
			
		||||
+    	}
 | 
			
		||||
+    } else {
 | 
			
		||||
+    	spiTransfer(addr, digit+1, value);
 | 
			
		||||
+    }
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+
 | 
			
		||||
+
 | 
			
		||||
 
 | 
			
		||||
diff -u LedControl-unpatched/LedControl.h LedControl/LedControl.h
 | 
			
		||||
--- LedControl-unpatched/LedControl.h	2011-09-20 23:49:06.000000000 -0700
 | 
			
		||||
+++ LedControl/LedControl.h	2012-09-02 00:18:47.000000000 -0700
 | 
			
		||||
@@ -58,6 +58,8 @@
 | 
			
		||||
 
 | 
			
		||||
     /* We keep track of the led-status for all 8 devices in this array */
 | 
			
		||||
     byte status[64];
 | 
			
		||||
+    /* We also keep track of the transposed version */
 | 
			
		||||
+    byte statusTransposed[64];
 | 
			
		||||
     /* Data is shifted out of this pin*/
 | 
			
		||||
     int SPI_MOSI;
 | 
			
		||||
     /* The clock is signaled on this pin */
 | 
			
		||||
@@ -66,6 +68,8 @@
 | 
			
		||||
     int SPI_CS;
 | 
			
		||||
     /* The maximum number of devices we use */
 | 
			
		||||
     int maxDevices;
 | 
			
		||||
+    /* Choose whether we're using common cathode or common anode displays */
 | 
			
		||||
+    bool anodeMode;
 | 
			
		||||
     
 | 
			
		||||
  public:
 | 
			
		||||
     /* 
 | 
			
		||||
@@ -75,8 +79,9 @@
 | 
			
		||||
      * clockPin		pin for the clock
 | 
			
		||||
      * csPin		pin for selecting the device 
 | 
			
		||||
      * numDevices	maximum number of devices that can be controled
 | 
			
		||||
+     * anode		false for common-cathode displays, true for common-anode displays
 | 
			
		||||
      */
 | 
			
		||||
-    LedControl(int dataPin, int clkPin, int csPin, int numDevices=1);
 | 
			
		||||
+    LedControl(int dataPin, int clkPin, int csPin, int numDevices=1, bool anode=false);
 | 
			
		||||
 
 | 
			
		||||
     /*
 | 
			
		||||
      * Gets the number of devices attached to this LedControl.
 | 
			
		||||
@@ -173,9 +178,25 @@
 | 
			
		||||
      * dp	sets the decimal point.
 | 
			
		||||
      */
 | 
			
		||||
     void setChar(int addr, int digit, char value, boolean dp);
 | 
			
		||||
+    
 | 
			
		||||
+    /*
 | 
			
		||||
+     * Transpose data matrix for use with common-anode displays.
 | 
			
		||||
+     * Params:
 | 
			
		||||
+     * addr	address of the display
 | 
			
		||||
+     */
 | 
			
		||||
+    void transposeData(int addr);
 | 
			
		||||
+    
 | 
			
		||||
+    /*
 | 
			
		||||
+     * Light up segments of a 7-segment display directly by passing a binary value.
 | 
			
		||||
+     * The eight bits of the byte each refer to a segment:
 | 
			
		||||
+     *     Byte:   0 0 0 0 0 0 0 0
 | 
			
		||||
+     *  Segments: DP A B C D E F G
 | 
			
		||||
+     * Params:
 | 
			
		||||
+     * addr	address of the display
 | 
			
		||||
+     * digit	the position of the character on the display (0..7)
 | 
			
		||||
+     * value	the binary value to be displayed
 | 
			
		||||
+     */
 | 
			
		||||
+    void setDirectDigit(int addr, int digit, byte value);
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
 #endif	//LedControl.h
 | 
			
		||||
-
 | 
			
		||||
-
 | 
			
		||||
-
 | 
			
		||||
@@ -1,73 +0,0 @@
 | 
			
		||||
//We always have to include the library
 | 
			
		||||
#include "LedControl.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 Now we need a LedControl to work with.
 | 
			
		||||
 ***** These pin numbers will probably not work with your hardware *****
 | 
			
		||||
 pin 12 is connected to the DataIn 
 | 
			
		||||
 pin 11 is connected to the CLK 
 | 
			
		||||
 pin 10 is connected to LOAD 
 | 
			
		||||
 We have only a single MAX72XX.
 | 
			
		||||
 */
 | 
			
		||||
LedControl lc=LedControl(12,11,10,1);
 | 
			
		||||
 | 
			
		||||
/* we always wait a bit between updates of the display */
 | 
			
		||||
unsigned long delaytime=250;
 | 
			
		||||
 | 
			
		||||
void setup() {
 | 
			
		||||
  /*
 | 
			
		||||
   The MAX72XX is in power-saving mode on startup,
 | 
			
		||||
   we have to do a wakeup call
 | 
			
		||||
   */
 | 
			
		||||
  lc.shutdown(0,false);
 | 
			
		||||
  /* Set the brightness to a medium values */
 | 
			
		||||
  lc.setIntensity(0,8);
 | 
			
		||||
  /* and clear the display */
 | 
			
		||||
  lc.clearDisplay(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 This method will display the characters for the
 | 
			
		||||
 word "Arduino" one after the other on digit 0. 
 | 
			
		||||
 */
 | 
			
		||||
void writeArduinoOn7Segment() {
 | 
			
		||||
  lc.setChar(0,0,'a',false);
 | 
			
		||||
  delay(delaytime);
 | 
			
		||||
  lc.setRow(0,0,0x05);
 | 
			
		||||
  delay(delaytime);
 | 
			
		||||
  lc.setChar(0,0,'d',false);
 | 
			
		||||
  delay(delaytime);
 | 
			
		||||
  lc.setRow(0,0,0x1c);
 | 
			
		||||
  delay(delaytime);
 | 
			
		||||
  lc.setRow(0,0,B00010000);
 | 
			
		||||
  delay(delaytime);
 | 
			
		||||
  lc.setRow(0,0,0x15);
 | 
			
		||||
  delay(delaytime);
 | 
			
		||||
  lc.setRow(0,0,0x1D);
 | 
			
		||||
  delay(delaytime);
 | 
			
		||||
  lc.clearDisplay(0);
 | 
			
		||||
  delay(delaytime);
 | 
			
		||||
} 
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  This method will scroll all the hexa-decimal
 | 
			
		||||
 numbers and letters on the display. You will need at least
 | 
			
		||||
 four 7-Segment digits. otherwise it won't really look that good.
 | 
			
		||||
 */
 | 
			
		||||
void scrollDigits() {
 | 
			
		||||
  for(int i=0;i<13;i++) {
 | 
			
		||||
    lc.setDigit(0,3,i,false);
 | 
			
		||||
    lc.setDigit(0,2,i+1,false);
 | 
			
		||||
    lc.setDigit(0,1,i+2,false);
 | 
			
		||||
    lc.setDigit(0,0,i+3,false);
 | 
			
		||||
    delay(delaytime);
 | 
			
		||||
  }
 | 
			
		||||
  lc.clearDisplay(0);
 | 
			
		||||
  delay(delaytime);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void loop() { 
 | 
			
		||||
  writeArduinoOn7Segment();
 | 
			
		||||
  scrollDigits();
 | 
			
		||||
}
 | 
			
		||||
@@ -1,52 +0,0 @@
 | 
			
		||||
//We always have to include the library
 | 
			
		||||
#include "LedControl.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 Now we need a LedControl to work with.
 | 
			
		||||
 ***** These pin numbers will probably not work with your hardware *****
 | 
			
		||||
 pin 12 is connected to the DataIn 
 | 
			
		||||
 pin 11 is connected to the CLK 
 | 
			
		||||
 pin 10 is connected to LOAD 
 | 
			
		||||
 ***** Please set the number of devices you have *****
 | 
			
		||||
 But the maximum default of 8 MAX72XX wil also work.
 | 
			
		||||
 */
 | 
			
		||||
LedControl lc=LedControl(12,11,10,8);
 | 
			
		||||
 | 
			
		||||
/* we always wait a bit between updates of the display */
 | 
			
		||||
unsigned long delaytime=500;
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
 This time we have more than one device. 
 | 
			
		||||
 But all of them have to be initialized 
 | 
			
		||||
 individually.
 | 
			
		||||
 */
 | 
			
		||||
void setup() {
 | 
			
		||||
  //we have already set the number of devices when we created the LedControl
 | 
			
		||||
  int devices=lc.getDeviceCount();
 | 
			
		||||
  //we have to init all devices in a loop
 | 
			
		||||
  for(int address=0;address<devices;address++) {
 | 
			
		||||
    /*The MAX72XX is in power-saving mode on startup*/
 | 
			
		||||
    lc.shutdown(address,false);
 | 
			
		||||
    /* Set the brightness to a medium values */
 | 
			
		||||
    lc.setIntensity(address,8);
 | 
			
		||||
    /* and clear the display */
 | 
			
		||||
    lc.clearDisplay(address);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void loop() { 
 | 
			
		||||
  //read the number cascaded devices
 | 
			
		||||
  int devices=lc.getDeviceCount();
 | 
			
		||||
  
 | 
			
		||||
  //we have to init all devices in a loop
 | 
			
		||||
  for(int row=0;row<8;row++) {
 | 
			
		||||
    for(int col=0;col<8;col++) {
 | 
			
		||||
      for(int address=0;address<devices;address++) {
 | 
			
		||||
        delay(delaytime);
 | 
			
		||||
        lc.setLed(address,row,col,true);
 | 
			
		||||
        delay(delaytime);
 | 
			
		||||
        lc.setLed(address,row,col,false);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,163 +0,0 @@
 | 
			
		||||
//We always have to include the library
 | 
			
		||||
#include "LedControl.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 Now we need a LedControl to work with.
 | 
			
		||||
 ***** These pin numbers will probably not work with your hardware *****
 | 
			
		||||
 pin 12 is connected to the DataIn 
 | 
			
		||||
 pin 11 is connected to the CLK 
 | 
			
		||||
 pin 10 is connected to LOAD 
 | 
			
		||||
 We have only a single MAX72XX.
 | 
			
		||||
 */
 | 
			
		||||
LedControl lc=LedControl(12,11,10,1);
 | 
			
		||||
 | 
			
		||||
/* we always wait a bit between updates of the display */
 | 
			
		||||
unsigned long delaytime=100;
 | 
			
		||||
 | 
			
		||||
void setup() {
 | 
			
		||||
  /*
 | 
			
		||||
   The MAX72XX is in power-saving mode on startup,
 | 
			
		||||
   we have to do a wakeup call
 | 
			
		||||
   */
 | 
			
		||||
  lc.shutdown(0,false);
 | 
			
		||||
  /* Set the brightness to a medium values */
 | 
			
		||||
  lc.setIntensity(0,8);
 | 
			
		||||
  /* and clear the display */
 | 
			
		||||
  lc.clearDisplay(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 This method will display the characters for the
 | 
			
		||||
 word "Arduino" one after the other on the matrix. 
 | 
			
		||||
 (you need at least 5x7 leds to see the whole chars)
 | 
			
		||||
 */
 | 
			
		||||
void writeArduinoOnMatrix() {
 | 
			
		||||
  /* here is the data for the characters */
 | 
			
		||||
  byte a[5]={B01111110,B10001000,B10001000,B10001000,B01111110};
 | 
			
		||||
  byte r[5]={B00111110,B00010000,B00100000,B00100000,B00010000};
 | 
			
		||||
  byte d[5]={B00011100,B00100010,B00100010,B00010010,B11111110};
 | 
			
		||||
  byte u[5]={B00111100,B00000010,B00000010,B00000100,B00111110};
 | 
			
		||||
  byte i[5]={B00000000,B00100010,B10111110,B00000010,B00000000};
 | 
			
		||||
  byte n[5]={B00111110,B00010000,B00100000,B00100000,B00011110};
 | 
			
		||||
  byte o[5]={B00011100,B00100010,B00100010,B00100010,B00011100};
 | 
			
		||||
 | 
			
		||||
  /* now display them one by one with a small delay */
 | 
			
		||||
  lc.setRow(0,0,a[0]);
 | 
			
		||||
  lc.setRow(0,1,a[1]);
 | 
			
		||||
  lc.setRow(0,2,a[2]);
 | 
			
		||||
  lc.setRow(0,3,a[3]);
 | 
			
		||||
  lc.setRow(0,4,a[4]);
 | 
			
		||||
  delay(delaytime);
 | 
			
		||||
  lc.setRow(0,0,r[0]);
 | 
			
		||||
  lc.setRow(0,1,r[1]);
 | 
			
		||||
  lc.setRow(0,2,r[2]);
 | 
			
		||||
  lc.setRow(0,3,r[3]);
 | 
			
		||||
  lc.setRow(0,4,r[4]);
 | 
			
		||||
  delay(delaytime);
 | 
			
		||||
  lc.setRow(0,0,d[0]);
 | 
			
		||||
  lc.setRow(0,1,d[1]);
 | 
			
		||||
  lc.setRow(0,2,d[2]);
 | 
			
		||||
  lc.setRow(0,3,d[3]);
 | 
			
		||||
  lc.setRow(0,4,d[4]);
 | 
			
		||||
  delay(delaytime);
 | 
			
		||||
  lc.setRow(0,0,u[0]);
 | 
			
		||||
  lc.setRow(0,1,u[1]);
 | 
			
		||||
  lc.setRow(0,2,u[2]);
 | 
			
		||||
  lc.setRow(0,3,u[3]);
 | 
			
		||||
  lc.setRow(0,4,u[4]);
 | 
			
		||||
  delay(delaytime);
 | 
			
		||||
  lc.setRow(0,0,i[0]);
 | 
			
		||||
  lc.setRow(0,1,i[1]);
 | 
			
		||||
  lc.setRow(0,2,i[2]);
 | 
			
		||||
  lc.setRow(0,3,i[3]);
 | 
			
		||||
  lc.setRow(0,4,i[4]);
 | 
			
		||||
  delay(delaytime);
 | 
			
		||||
  lc.setRow(0,0,n[0]);
 | 
			
		||||
  lc.setRow(0,1,n[1]);
 | 
			
		||||
  lc.setRow(0,2,n[2]);
 | 
			
		||||
  lc.setRow(0,3,n[3]);
 | 
			
		||||
  lc.setRow(0,4,n[4]);
 | 
			
		||||
  delay(delaytime);
 | 
			
		||||
  lc.setRow(0,0,o[0]);
 | 
			
		||||
  lc.setRow(0,1,o[1]);
 | 
			
		||||
  lc.setRow(0,2,o[2]);
 | 
			
		||||
  lc.setRow(0,3,o[3]);
 | 
			
		||||
  lc.setRow(0,4,o[4]);
 | 
			
		||||
  delay(delaytime);
 | 
			
		||||
  lc.setRow(0,0,0);
 | 
			
		||||
  lc.setRow(0,1,0);
 | 
			
		||||
  lc.setRow(0,2,0);
 | 
			
		||||
  lc.setRow(0,3,0);
 | 
			
		||||
  lc.setRow(0,4,0);
 | 
			
		||||
  delay(delaytime);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  This function lights up a some Leds in a row.
 | 
			
		||||
 The pattern will be repeated on every row.
 | 
			
		||||
 The pattern will blink along with the row-number.
 | 
			
		||||
 row number 4 (index==3) will blink 4 times etc.
 | 
			
		||||
 */
 | 
			
		||||
void rows() {
 | 
			
		||||
  for(int row=0;row<8;row++) {
 | 
			
		||||
    delay(delaytime);
 | 
			
		||||
    lc.setRow(0,row,B10100000);
 | 
			
		||||
    delay(delaytime);
 | 
			
		||||
    lc.setRow(0,row,(byte)0);
 | 
			
		||||
    for(int i=0;i<row;i++) {
 | 
			
		||||
      delay(delaytime);
 | 
			
		||||
      lc.setRow(0,row,B10100000);
 | 
			
		||||
      delay(delaytime);
 | 
			
		||||
      lc.setRow(0,row,(byte)0);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  This function lights up a some Leds in a column.
 | 
			
		||||
 The pattern will be repeated on every column.
 | 
			
		||||
 The pattern will blink along with the column-number.
 | 
			
		||||
 column number 4 (index==3) will blink 4 times etc.
 | 
			
		||||
 */
 | 
			
		||||
void columns() {
 | 
			
		||||
  for(int col=0;col<8;col++) {
 | 
			
		||||
    delay(delaytime);
 | 
			
		||||
    lc.setColumn(0,col,B10100000);
 | 
			
		||||
    delay(delaytime);
 | 
			
		||||
    lc.setColumn(0,col,(byte)0);
 | 
			
		||||
    for(int i=0;i<col;i++) {
 | 
			
		||||
      delay(delaytime);
 | 
			
		||||
      lc.setColumn(0,col,B10100000);
 | 
			
		||||
      delay(delaytime);
 | 
			
		||||
      lc.setColumn(0,col,(byte)0);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
 This function will light up every Led on the matrix.
 | 
			
		||||
 The led will blink along with the row-number.
 | 
			
		||||
 row number 4 (index==3) will blink 4 times etc.
 | 
			
		||||
 */
 | 
			
		||||
void single() {
 | 
			
		||||
  for(int row=0;row<8;row++) {
 | 
			
		||||
    for(int col=0;col<8;col++) {
 | 
			
		||||
      delay(delaytime);
 | 
			
		||||
      lc.setLed(0,row,col,true);
 | 
			
		||||
      delay(delaytime);
 | 
			
		||||
      for(int i=0;i<col;i++) {
 | 
			
		||||
        lc.setLed(0,row,col,false);
 | 
			
		||||
        delay(delaytime);
 | 
			
		||||
        lc.setLed(0,row,col,true);
 | 
			
		||||
        delay(delaytime);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void loop() { 
 | 
			
		||||
  writeArduinoOnMatrix();
 | 
			
		||||
  rows();
 | 
			
		||||
  columns();
 | 
			
		||||
  single();
 | 
			
		||||
}
 | 
			
		||||
@@ -1,28 +0,0 @@
 | 
			
		||||
#######################################
 | 
			
		||||
# Syntax Coloring Map For LedControl
 | 
			
		||||
#######################################
 | 
			
		||||
 | 
			
		||||
#######################################
 | 
			
		||||
# Datatypes (KEYWORD1)
 | 
			
		||||
#######################################
 | 
			
		||||
 | 
			
		||||
LedControl	KEYWORD1
 | 
			
		||||
 | 
			
		||||
#######################################
 | 
			
		||||
# Methods and Functions (KEYWORD2)
 | 
			
		||||
#######################################
 | 
			
		||||
 | 
			
		||||
shutdown	KEYWORD2
 | 
			
		||||
setScanLimit	KEYWORD2
 | 
			
		||||
setIntensity	KEYWORD2
 | 
			
		||||
clearDisplay	KEYWORD2
 | 
			
		||||
setLed		KEYWORD2
 | 
			
		||||
setRow		KEYWORD2
 | 
			
		||||
setColumn	KEYWORD2
 | 
			
		||||
setDigit	KEYWORD2
 | 
			
		||||
setChar		KEYWORD2
 | 
			
		||||
 | 
			
		||||
#######################################
 | 
			
		||||
# Constants (LITERAL1)
 | 
			
		||||
#######################################
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										30
									
								
								README.md
									
									
									
									
									
								
							
							
						
						@@ -1,4 +1,4 @@
 | 
			
		||||
 DCF77 Analyzer / Clock
 | 
			
		||||
 DCF77 Analyzer/Clock v2.0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 This sketch is free software; you can redistribute it and/or
 | 
			
		||||
@@ -16,17 +16,10 @@
 | 
			
		||||
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 The C++ code is far from optimized because I myself am an Arduino and C++ novice.
 | 
			
		||||
 This C++ code is far from optimized because I myself am an Arduino and C++ novice.
 | 
			
		||||
 But even after learning some more now, I want to keep the code simpel and readable.
 | 
			
		||||
 That is why I maybe over-documented the code to help understand what's going on.
 | 
			
		||||
 | 
			
		||||
 HELP WANTED: 
 | 
			
		||||
 I'm not experienced enough to get to the point where the second-tick
 | 
			
		||||
 of the Real Time Clock display is exactly in sync with the DCF pulse.
 | 
			
		||||
 Now there's a small time lag.
 | 
			
		||||
 If you have a solution, please let me know! 
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
 Erik de Ruiter
 | 
			
		||||
 2014-2016
 | 
			
		||||
   
 | 
			
		||||
@@ -34,9 +27,20 @@
 | 
			
		||||
 | 
			
		||||
 May 2014 First version
 | 
			
		||||
 March 2016 - big overhaul...
 | 
			
		||||
 July 2016 - Start with building the v2.0 Clock and adapting the sketch
 | 
			
		||||
 | 
			
		||||
 Version 2.0 - August 2016
 | 
			
		||||
 - This sketch is adapted for my 2.0 version of the DCF/Analyzer Clock. It used the Arduino MEGA and the DCF Superfilter
 | 
			
		||||
   by default and to drive the many seperate LED's I now use the ports of an Arduino Mega instead of a Maxim 7219 chip. 
 | 
			
		||||
   This is because driving LED's with many different Voltage/Current specs is problematic with the Maxim chip. 
 | 
			
		||||
   Lighting additional LED's for expample will influence (dim) the LED's already on. As I'm not an electronics engineer
 | 
			
		||||
   my only solution was to use the extra ports of the Arduino Mega. Ofcourse you can use transistors or extra chips to
 | 
			
		||||
   drive the LED's but for me this was the obvious solution.
 | 
			
		||||
 - Removed all the code to use Maxim 72xx chips with Common Anode displays
 | 
			
		||||
 | 
			
		||||
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
 | 
			
		||||
 Version 1.72
 | 
			
		||||
 | 
			
		||||
 Version 1.72 - May 2016
 | 
			
		||||
 - Option: Use a cheap Ebay PIR detector to shut off selectable display's when no activity is detected. 
 | 
			
		||||
   The switch off delay can be set by the user to prevent the display shutting of if a person
 | 
			
		||||
   is not moving but the display should be on.
 | 
			
		||||
@@ -77,8 +81,8 @@
 | 
			
		||||
   can now be configured somewhat easier by editing two variables POWERSAVINGONTIME and POWERSAVINGOFFTIME.
 | 
			
		||||
 - changed some variable names:
 | 
			
		||||
   - Maxim instances 'lc' and 'lc1' are now MaximCC and MaximCA
 | 
			
		||||
   - Display description MaximDcfTime is now MaximTemperature 
 | 
			
		||||
   - DCF77SOUNDPIN is now BUZZERPIN
 | 
			
		||||
   - Display description MaximDcfTime is now DisplayTempWeek 
 | 
			
		||||
   - DCF77SOUNDPIN is now BUZZERSWITCHPIN
 | 
			
		||||
 - LED/Display test after power up now build in
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@@ -128,7 +132,7 @@
 | 
			
		||||
    The only thing is you can't see it... ;)
 | 
			
		||||
 | 
			
		||||
  DCF beep:
 | 
			
		||||
    With a switch, connected to pin BUZZERPIN, you can hear the received DCF bits coming in. 
 | 
			
		||||
    With a switch, connected to pin BUZZERSWITCHPIN, you can hear the received DCF bits coming in. 
 | 
			
		||||
    The tone duration is equivalent to pulse width of the DCF bits, so either 100 or 200 ms.
 | 
			
		||||
  
 | 
			
		||||
  Miscelleanous:
 | 
			
		||||
 
 | 
			
		||||