DCF77-Analyzer-Clock-v2

This commit is contained in:
Erik
2016-08-01 13:02:10 +02:00
parent f72a2fd0ed
commit fe2abf0495
34 changed files with 52208 additions and 17310 deletions

Binary file not shown.

Binary file not shown.

BIN
Arduino Libraries/Time.zip Normal file

Binary file not shown.

View 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();
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 MiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 309 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 538 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Binary file not shown.

View 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);
}

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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
-
-
-

View File

@@ -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();
}

View File

@@ -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);
}
}
}
}

View File

@@ -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();
}

View File

@@ -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)
#######################################

View File

@@ -1,4 +1,4 @@
DCF77 Analyzer / Clock DCF77 Analyzer/Clock v2.0
This sketch is free software; you can redistribute it and/or 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 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. 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. 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 Erik de Ruiter
2014-2016 2014-2016
@@ -34,9 +27,20 @@
May 2014 First version May 2014 First version
March 2016 - big overhaul... 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. - 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 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. 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. can now be configured somewhat easier by editing two variables POWERSAVINGONTIME and POWERSAVINGOFFTIME.
- changed some variable names: - changed some variable names:
- Maxim instances 'lc' and 'lc1' are now MaximCC and MaximCA - Maxim instances 'lc' and 'lc1' are now MaximCC and MaximCA
- Display description MaximDcfTime is now MaximTemperature - Display description MaximDcfTime is now DisplayTempWeek
- DCF77SOUNDPIN is now BUZZERPIN - DCF77SOUNDPIN is now BUZZERSWITCHPIN
- LED/Display test after power up now build in - LED/Display test after power up now build in
@@ -128,7 +132,7 @@
The only thing is you can't see it... ;) The only thing is you can't see it... ;)
DCF beep: 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. The tone duration is equivalent to pulse width of the DCF bits, so either 100 or 200 ms.
Miscelleanous: Miscelleanous:

Binary file not shown.