summaryrefslogtreecommitdiffstats
path: root/Matrix_9x14/libraries/Charliplexing
diff options
context:
space:
mode:
authorAlexander Kauerz <kauerz@informatik.uni-luebeck.de>2012-02-09 22:59:58 +0100
committerAlexander Kauerz <kauerz@informatik.uni-luebeck.de>2012-02-09 22:59:58 +0100
commitfbea3ae42daade09ad42fe9ae9ca542f77b96c20 (patch)
tree4d2162027b1bac7830569d5f8efd9813f3497902 /Matrix_9x14/libraries/Charliplexing
parent8f428f51b4b62d1f07c88cace7bb127e436271a5 (diff)
downloadledmatrix-fbea3ae42daade09ad42fe9ae9ca542f77b96c20.tar
ledmatrix-fbea3ae42daade09ad42fe9ae9ca542f77b96c20.zip
lolshield-matrix hinzu
Diffstat (limited to 'Matrix_9x14/libraries/Charliplexing')
-rw-r--r--Matrix_9x14/libraries/Charliplexing/.svn/all-wcprops47
-rw-r--r--Matrix_9x14/libraries/Charliplexing/.svn/entries269
-rw-r--r--Matrix_9x14/libraries/Charliplexing/.svn/text-base/Charliplexing.cpp.svn-base502
-rw-r--r--Matrix_9x14/libraries/Charliplexing/.svn/text-base/Charliplexing.h.svn-base34
-rw-r--r--Matrix_9x14/libraries/Charliplexing/.svn/text-base/Figure.cpp.svn-base125
-rw-r--r--Matrix_9x14/libraries/Charliplexing/.svn/text-base/Figure.h.svn-base42
-rw-r--r--Matrix_9x14/libraries/Charliplexing/.svn/text-base/Font.cpp.svn-base219
-rw-r--r--Matrix_9x14/libraries/Charliplexing/.svn/text-base/Font.h.svn-base40
-rw-r--r--Matrix_9x14/libraries/Charliplexing/.svn/text-base/keywords.txt.svn-base14
-rw-r--r--Matrix_9x14/libraries/Charliplexing/Charliplexing.cpp502
-rw-r--r--Matrix_9x14/libraries/Charliplexing/Charliplexing.h34
-rw-r--r--Matrix_9x14/libraries/Charliplexing/Figure.cpp125
-rw-r--r--Matrix_9x14/libraries/Charliplexing/Figure.h42
-rw-r--r--Matrix_9x14/libraries/Charliplexing/Font.cpp219
-rw-r--r--Matrix_9x14/libraries/Charliplexing/Font.h40
15 files changed, 2254 insertions, 0 deletions
diff --git a/Matrix_9x14/libraries/Charliplexing/.svn/all-wcprops b/Matrix_9x14/libraries/Charliplexing/.svn/all-wcprops
new file mode 100644
index 0000000..e64fbe9
--- /dev/null
+++ b/Matrix_9x14/libraries/Charliplexing/.svn/all-wcprops
@@ -0,0 +1,47 @@
+K 25
+svn:wc:ra_dav:version-url
+V 26
+/svn/!svn/ver/24/trunk/lib
+END
+Charliplexing.h
+K 25
+svn:wc:ra_dav:version-url
+V 42
+/svn/!svn/ver/23/trunk/lib/Charliplexing.h
+END
+Figure.cpp
+K 25
+svn:wc:ra_dav:version-url
+V 37
+/svn/!svn/ver/20/trunk/lib/Figure.cpp
+END
+keywords.txt
+K 25
+svn:wc:ra_dav:version-url
+V 38
+/svn/!svn/ver/6/trunk/lib/keywords.txt
+END
+Figure.h
+K 25
+svn:wc:ra_dav:version-url
+V 34
+/svn/!svn/ver/2/trunk/lib/Figure.h
+END
+Font.cpp
+K 25
+svn:wc:ra_dav:version-url
+V 34
+/svn/!svn/ver/7/trunk/lib/Font.cpp
+END
+Charliplexing.cpp
+K 25
+svn:wc:ra_dav:version-url
+V 44
+/svn/!svn/ver/23/trunk/lib/Charliplexing.cpp
+END
+Font.h
+K 25
+svn:wc:ra_dav:version-url
+V 32
+/svn/!svn/ver/7/trunk/lib/Font.h
+END
diff --git a/Matrix_9x14/libraries/Charliplexing/.svn/entries b/Matrix_9x14/libraries/Charliplexing/.svn/entries
new file mode 100644
index 0000000..470af9f
--- /dev/null
+++ b/Matrix_9x14/libraries/Charliplexing/.svn/entries
@@ -0,0 +1,269 @@
+10
+
+dir
+26
+http://lolshield.googlecode.com/svn/trunk/lib
+http://lolshield.googlecode.com/svn
+
+
+
+2012-01-13T17:54:37.624437Z
+24
+thilo.alexander@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+a9283160-f6ed-11de-885d-7376d8f76b83
+
+Charliplexing.h
+file
+
+
+
+
+2012-02-09T20:19:37.528308Z
+5cd52a3fe91e62b285b19574f0d9be0e
+2012-01-07T22:37:32.348571Z
+23
+thilo.alexander@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+979
+
+Figure.cpp
+file
+
+
+
+
+2012-02-09T20:19:37.528308Z
+c4b4529e0fd718132e2e7fea79305d5d
+2012-01-07T07:24:41.729156Z
+20
+thilo.alexander@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4422
+
+keywords.txt
+file
+
+
+
+
+2012-02-09T20:19:37.532308Z
+4bed9c76c30b8f7d93feb19bd7aae30e
+2010-05-28T07:21:20.858041Z
+6
+matt.mets@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+219
+
+Figure.h
+file
+
+
+
+
+2012-02-09T20:19:37.532308Z
+157c938fc59e7d5e34fd5ae27527ccad
+2010-01-07T16:19:43.833624Z
+2
+BenjaminSonntag
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1171
+
+Font.cpp
+file
+
+
+
+
+2012-02-09T20:19:37.532308Z
+d23679dd846a915028f30b8f6b08e465
+2010-07-19T06:45:40.102535Z
+7
+matt.mets@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+11343
+
+Charliplexing.cpp
+file
+
+
+
+
+2012-02-09T20:19:37.536308Z
+dd9e42d06689a07a57ef2517b96cfa35
+2012-01-07T22:37:32.348571Z
+23
+thilo.alexander@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+15883
+
+Font.h
+file
+
+
+
+
+2012-02-09T20:19:37.536308Z
+863d12dac57c9c0562b87b43b1e0090a
+2010-07-19T06:45:40.102535Z
+7
+matt.mets@gmail.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1131
+
+examples
+dir
+
diff --git a/Matrix_9x14/libraries/Charliplexing/.svn/text-base/Charliplexing.cpp.svn-base b/Matrix_9x14/libraries/Charliplexing/.svn/text-base/Charliplexing.cpp.svn-base
new file mode 100644
index 0000000..d68b209
--- /dev/null
+++ b/Matrix_9x14/libraries/Charliplexing/.svn/text-base/Charliplexing.cpp.svn-base
@@ -0,0 +1,502 @@
+/*
+ Charliplexing.cpp - Using timer2 with 1ms resolution
+
+ Alex Wenger <a.wenger@gmx.de> http://arduinobuch.wordpress.com/
+ Matt Mets <mahto@cibomahto.com> http://cibomahto.com/
+
+ Timer init code from MsTimer2 - Javier Valencia <javiervalencia80@gmail.com>
+ Misc functions from Benjamin Sonnatg <benjamin@sonntag.fr>
+
+ History:
+ 2009-12-30 - V0.0 wrote the first version at 26C3/Berlin
+ 2010-01-01 - V0.1 adding misc utility functions
+ (Clear, Vertical, Horizontal) comment are Doxygen complaints now
+ 2010-05-27 - V0.2 add double-buffer mode
+ 2010-08-18 - V0.9 Merge brightness and grayscale
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#if defined(ARDUINO) && ARDUINO >= 100
+#include "Arduino.h"
+#else
+#include "WProgram.h"
+#endif
+#include <inttypes.h>
+#include <math.h>
+#include <avr/interrupt.h>
+#include "Charliplexing.h"
+
+volatile unsigned int LedSign::tcnt2;
+
+
+struct videoPage {
+ uint8_t pixels[SHADES][48]; // TODO: is 48 right?
+};
+
+/* ----------------------------------------------------------------- */
+/** Table for the LED multiplexing cycles
+ * Each frame is made of 24 bytes (for the 24 display cycles)
+ * There are SHADES frames per buffer in grayscale mode (one for each brigtness)
+ * and twice that many to support double-buffered grayscale.
+ */
+videoPage leds[2];
+
+/// Determines whether the display is in single or double buffer mode
+uint8_t displayMode = SINGLE_BUFFER;
+
+/// Flag indicating that the display page should be flipped as soon as the
+/// current frame is displayed
+volatile boolean videoFlipPage = false;
+
+/// Pointer to the buffer that is currently being displayed
+videoPage* displayBuffer;
+
+/// Pointer to the buffer that should currently be drawn to
+videoPage* workBuffer;
+
+/// Flag indicating that the timer buffer should be flipped as soon as the
+/// current frame is displayed
+volatile boolean videoFlipTimer = false;
+
+
+// Timer counts to display each page for, plus off time
+typedef struct timerInfo {
+ uint8_t counts[SHADES];
+ uint8_t prescaler[SHADES];
+};
+
+// Double buffer the timing information, of course.
+timerInfo* frontTimer;
+timerInfo* backTimer;
+
+timerInfo* tempTimer;
+
+timerInfo timer[2];
+
+// Record a slow and fast prescaler for later use
+typedef struct prescalerInfo {
+ uint8_t relativeSpeed;
+ uint8_t TCCR2;
+};
+
+// TODO: Generate these based on processor type and clock speed
+prescalerInfo slowPrescaler = {1, 0x03};
+//prescalerInfo fastPrescaler = {32, 0x01};
+prescalerInfo fastPrescaler = {4, 0x02};
+
+static bool initialized = false;
+
+/// Uncomment to set analog pin 5 high during interrupts, so that an
+/// oscilloscope can be used to measure the processor time taken by it
+#define MEASURE_ISR_TIME
+#ifdef MEASURE_ISR_TIME
+uint8_t statusPIN = 19;
+#endif
+
+typedef struct LEDPosition {
+ uint8_t high;
+ uint8_t low;
+};
+
+
+/* ----------------------------------------------------------------- */
+/** Table for LED Position in leds[] ram table
+ */
+
+const LEDPosition ledMap[126] = {
+ {13, 5}, {13, 6}, {13, 7}, {13, 8}, {13, 9}, {13,10}, {13,11}, {13,12},
+ {13, 4}, { 4,13}, {13, 3}, { 3,13}, {13, 2}, { 2,13},
+ {12, 5}, {12, 6}, {12, 7}, {12, 8}, {12, 9}, {12,10}, {12,11}, {12,13},
+ {12, 4}, { 4,12}, {12, 3}, { 3,12}, {12, 2}, { 2,12},
+ {11, 5}, {11, 6}, {11, 7}, {11, 8}, {11, 9}, {11,10}, {11,12}, {11,13},
+ {11, 4}, { 4,11}, {11, 3}, { 3,11}, {11, 2}, { 2,11},
+ {10, 5}, {10, 6}, {10, 7}, {10, 8}, {10, 9}, {10,11}, {10,12}, {10,13},
+ {10, 4}, { 4,10}, {10, 3}, { 3,10}, {10, 2}, { 2,10},
+ { 9, 5}, { 9, 6}, { 9, 7}, { 9, 8}, { 9,10}, { 9,11}, { 9,12}, { 9,13},
+ { 9, 4}, { 4, 9}, { 9, 3}, { 3, 9}, { 9, 2}, { 2, 9},
+ { 8, 5}, { 8, 6}, { 8, 7}, { 8, 9}, { 8,10}, { 8,11}, { 8,12}, { 8,13},
+ { 8, 4}, { 4, 8}, { 8, 3}, { 3, 8}, { 8, 2}, { 2, 8},
+ { 7, 5}, { 7, 6}, { 7, 8}, { 7, 9}, { 7,10}, { 7,11}, { 7,12}, { 7,13},
+ { 7, 4}, { 4, 7}, { 7, 3}, { 3, 7}, { 7, 2}, { 2, 7},
+ { 6, 5}, { 6, 7}, { 6, 8}, { 6, 9}, { 6,10}, { 6,11}, { 6,12}, { 6,13},
+ { 6, 4}, { 4, 6}, { 6, 3}, { 3, 6}, { 6, 2}, { 2, 6},
+ { 5, 6}, { 5, 7}, { 5, 8}, { 5, 9}, { 5,10}, { 5,11}, { 5,12}, { 5,13},
+ { 5, 4}, { 4, 5}, { 5, 3}, { 3, 5}, { 5, 2}, { 2, 5},
+};
+
+
+/* ----------------------------------------------------------------- */
+/** Constructor : Initialize the interrupt code.
+ * should be called in setup();
+ */
+void LedSign::Init(uint8_t mode)
+{
+#ifdef MEASURE_ISR_TIME
+ pinMode(statusPIN, OUTPUT);
+ digitalWrite(statusPIN, LOW);
+#endif
+
+ float prescaler = 0.0;
+
+#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1280__)
+ TIMSK2 &= ~(1<<TOIE2);
+ TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
+ TCCR2B &= ~(1<<WGM22);
+ ASSR &= ~(1<<AS2);
+ TIMSK2 &= ~(1<<OCIE2A);
+
+ if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64
+ TCCR2B |= ((1<<CS21) | (1<<CS20));
+ TCCR2B &= ~(1<<CS22);
+ prescaler = 32.0;
+ } else if (F_CPU < 1000000UL) { // prescaler set to 8
+ TCCR2B |= (1<<CS21);
+ TCCR2B &= ~((1<<CS22) | (1<<CS20));
+ prescaler = 8.0;
+ } else { // F_CPU > 16Mhz, prescaler set to 128
+ TCCR2B |= (1<<CS22);
+ TCCR2B &= ~((1<<CS21) | (1<<CS20));
+ prescaler = 64.0;
+ }
+#elif defined (__AVR_ATmega8__)
+ TIMSK &= ~(1<<TOIE2);
+ TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
+ TIMSK &= ~(1<<OCIE2);
+ ASSR &= ~(1<<AS2);
+
+ if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64
+ TCCR2 |= (1<<CS22);
+ TCCR2 &= ~((1<<CS21) | (1<<CS20));
+ prescaler = 64.0;
+ } else if (F_CPU < 1000000UL) { // prescaler set to 8
+ TCCR2 |= (1<<CS21);
+ TCCR2 &= ~((1<<CS22) | (1<<CS20));
+ prescaler = 8.0;
+ } else { // F_CPU > 16Mhz, prescaler set to 128
+ TCCR2 |= ((1<<CS22) && (1<<CS20));
+ TCCR2 &= ~(1<<CS21);
+ prescaler = 128.0;
+ }
+#elif defined (__AVR_ATmega128__)
+ TIMSK &= ~(1<<TOIE2);
+ TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
+ TIMSK &= ~(1<<OCIE2);
+
+ if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64
+ TCCR2 |= ((1<<CS21) | (1<<CS20));
+ TCCR2 &= ~(1<<CS22);
+ prescaler = 64.0;
+ } else if (F_CPU < 1000000UL) { // prescaler set to 8
+ TCCR2 |= (1<<CS21);
+ TCCR2 &= ~((1<<CS22) | (1<<CS20));
+ prescaler = 8.0;
+ } else { // F_CPU > 16Mhz, prescaler set to 256
+ TCCR2 |= (1<<CS22);
+ TCCR2 &= ~((1<<CS21) | (1<<CS20));
+ prescaler = 256.0;
+ }
+#endif
+
+ tcnt2 = 256 - (int)((float)F_CPU * 0.0005 / prescaler);
+
+ // Record whether we are in single or double buffer mode
+ displayMode = mode;
+ videoFlipPage = false;
+
+ // Point the display buffer to the first physical buffer
+ displayBuffer = &leds[0];
+
+ // If we are in single buffered mode, point the work buffer
+ // at the same physical buffer as the display buffer. Otherwise,
+ // point it at the second physical buffer.
+ if( displayMode & DOUBLE_BUFFER ) {
+ workBuffer = &leds[1];
+ }
+ else {
+ workBuffer = displayBuffer;
+ }
+
+ // Set up the timer buffering
+ frontTimer = &timer[0];
+ backTimer = &timer[1];
+
+ videoFlipTimer = false;
+ SetBrightness(127);
+
+ // Clear the buffer and display it
+ LedSign::Clear(0);
+ LedSign::Flip(false);
+
+ // Then start the display
+ TCNT2 = tcnt2;
+#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1280__)
+ TIMSK2 |= (1<<TOIE2);
+#elif defined (__AVR_ATmega128__) || defined (__AVR_ATmega8__)
+ TIMSK |= (1<<TOIE2);
+#endif
+
+ // If we are in double-buffer mode, wait until the display flips before we
+ // return
+ if (displayMode & DOUBLE_BUFFER)
+ {
+ while (videoFlipPage) {
+ delay(1);
+ }
+ }
+
+ initialized = true;
+}
+
+
+/* ----------------------------------------------------------------- */
+/** Signal that the front and back buffers should be flipped
+ * @param blocking if true : wait for flip before returning, if false :
+ * return immediately.
+ */
+void LedSign::Flip(bool blocking)
+{
+ if (displayMode & DOUBLE_BUFFER)
+ {
+ // Just set the flip flag, the buffer will flip between redraws
+ videoFlipPage = true;
+
+ // If we are blocking, sit here until the page flips.
+ while (blocking && videoFlipPage) {
+ delay(1);
+ }
+ }
+}
+
+
+/* ----------------------------------------------------------------- */
+/** Clear the screen completely
+ * @param set if 1 : make all led ON, if not set or 0 : make all led OFF
+ */
+void LedSign::Clear(int set) {
+ for(int x=0;x<14;x++)
+ for(int y=0;y<9;y++)
+ Set(x,y,set);
+}
+
+
+/* ----------------------------------------------------------------- */
+/** Clear an horizontal line completely
+ * @param y is the y coordinate of the line to clear/light [0-8]
+ * @param set if 1 : make all led ON, if not set or 0 : make all led OFF
+ */
+void LedSign::Horizontal(int y, int set) {
+ for(int x=0;x<14;x++)
+ Set(x,y,set);
+}
+
+
+/* ----------------------------------------------------------------- */
+/** Clear a vertical line completely
+ * @param x is the x coordinate of the line to clear/light [0-13]
+ * @param set if 1 : make all led ON, if not set or 0 : make all led OFF
+ */
+void LedSign::Vertical(int x, int set) {
+ for(int y=0;y<9;y++)
+ Set(x,y,set);
+}
+
+
+/* ----------------------------------------------------------------- */
+/** Set : switch on and off the leds. All the position #for char in frameString:
+ * calculations are done here, so we don't need to do in the
+ * interrupt code
+ */
+void LedSign::Set(uint8_t x, uint8_t y, uint8_t c)
+{
+ uint8_t pin_high = ledMap[x+y*14].high;
+ uint8_t pin_low = ledMap[x+y*14].low;
+ // pin_low is directly the address in the led array (minus 2 because the
+ // first two bytes are used for RS232 communication), but
+ // as it is a two byte array we need to check pin_high also.
+ // If pin_high is bigger than 8 address has to be increased by one
+
+ uint8_t bufferNum = (pin_low-2)*2 + (pin_high / 8) + ((pin_high > 7)?24:0);
+ uint8_t work = _BV(pin_high & 0x07);
+
+ // If we aren't in grayscale mode, just map any pin brightness to max
+ if (c > 0 && !(displayMode & GRAYSCALE)) {
+ c = SHADES-1;
+ }
+
+ for (int i = 0; i < SHADES-1; i++) {
+ if( c > i ) {
+ workBuffer->pixels[i][bufferNum] |= work; // ON
+ }
+ else {
+ workBuffer->pixels[i][bufferNum] &= ~work; // OFF
+ }
+ }
+}
+
+
+/* Set the overall brightness of the screen
+ * @param brightness LED brightness, from 0 (off) to 127 (full on)
+ */
+
+void LedSign::SetBrightness(uint8_t brightness)
+{
+ // An exponential fit seems to approximate a (perceived) linear scale
+ float brightnessPercent = ((float)brightness / 127)*((float)brightness / 127);
+ uint8_t difference = 0;
+
+ /* ---- This needs review! Please review. -- thilo */
+ // set up page counts
+ // TODO: make SHADES a function parameter. This would require some refactoring.
+ int start = 15;
+ int max = 255;
+ float scale = 1.5;
+ float delta = pow( max - start , 1.0 / scale) / (SHADES - 1);
+ uint8_t pageCounts[SHADES];
+
+ pageCounts[0] = max - start;
+ for (uint8_t i=1; i<SHADES; i++) {
+ pageCounts[i] = max - ( pow( i * delta, scale ) + start );
+ }
+ Serial.end();
+
+ if (! initialized) {
+ // set front timer defaults
+ for (int i = 0; i < SHADES; i++) {
+ frontTimer->counts[i] = pageCounts[i];
+ // TODO: Generate this dynamically
+ frontTimer->prescaler[i] = slowPrescaler.TCCR2;
+ }
+ }
+
+ // Wait until the previous brightness request goes through
+ while( videoFlipTimer ) {
+ delay(1);
+ }
+
+ // Compute on time for each of the pages
+ // Use the fast timer; slow timer is only useful for < 3 shades.
+ for (uint8_t i = 0; i < SHADES - 1; i++) {
+ uint8_t interval = 255 - pageCounts[i];
+
+ backTimer->counts[i] = 255 - brightnessPercent
+ * interval
+ * fastPrescaler.relativeSpeed;
+ backTimer->prescaler[i] = fastPrescaler.TCCR2;
+ difference += backTimer->counts[i] - pageCounts[i];
+ }
+
+ // Compute off time
+ backTimer->counts[SHADES - 1] = 255 - difference;
+ backTimer->prescaler[SHADES - 1] = slowPrescaler.TCCR2;
+
+ /* ---- End of "This needs review! Please review." -- thilo */
+
+ // Have the ISR update the timer registers next run
+ videoFlipTimer = true;
+}
+
+
+/* ----------------------------------------------------------------- */
+/** The Interrupt code goes here !
+ */
+ISR(TIMER2_OVF_vect) {
+ DDRD = 0x0;
+ DDRB = 0x0;
+#ifdef MEASURE_ISR_TIME
+ digitalWrite(statusPIN, HIGH);
+#endif
+
+ // For each cycle, we have potential SHADES pages to display.
+ // Once every page has been displayed, then we move on to the next
+ // cycle.
+
+ // 24 Cycles of Matrix
+ static uint8_t cycle = 0;
+
+ // SHADES pages to display
+ static uint8_t page = 0;
+
+ TCCR2B = frontTimer->prescaler[page];
+ TCNT2 = frontTimer->counts[page];
+
+ if ( page < SHADES - 1) {
+
+ if (cycle < 6) {
+ DDRD = _BV(cycle+2) | displayBuffer->pixels[page][cycle*2];
+ PORTD = displayBuffer->pixels[page][cycle*2];
+
+ DDRB = displayBuffer->pixels[page][cycle*2+1];
+ PORTB = displayBuffer->pixels[page][cycle*2+1];
+ } else if (cycle < 12) {
+ DDRD = displayBuffer->pixels[page][cycle*2];
+ PORTD = displayBuffer->pixels[page][cycle*2];
+
+ DDRB = _BV(cycle-6) | displayBuffer->pixels[page][cycle*2+1];
+ PORTB = displayBuffer->pixels[page][cycle*2+1];
+ } else if (cycle < 18) {
+ DDRD = _BV(cycle+2-12) | displayBuffer->pixels[page][cycle*2];
+ PORTD = displayBuffer->pixels[page][cycle*2];
+
+ DDRB = displayBuffer->pixels[page][cycle*2+1];
+ PORTB = displayBuffer->pixels[page][cycle*2+1];
+ } else {
+ DDRD = displayBuffer->pixels[page][cycle*2];
+ PORTD = displayBuffer->pixels[page][cycle*2];
+
+ DDRB = _BV(cycle-6-12) | displayBuffer->pixels[page][cycle*2+1];
+ PORTB = displayBuffer->pixels[page][cycle*2+1];
+ }
+ }
+ else {
+ // Turn everything off
+ DDRD = 0x0;
+ DDRB = 0x0;
+ }
+
+ page++;
+
+ if (page >= SHADES) {
+ page = 0;
+ cycle++;
+ }
+
+ if (cycle > 24) {
+ cycle = 0;
+
+ // If the page should be flipped, do it here.
+ if (videoFlipPage && (displayMode & DOUBLE_BUFFER))
+ {
+ // TODO: is this an atomic operation?
+ videoFlipPage = false;
+
+ videoPage* temp = displayBuffer;
+ displayBuffer = workBuffer;
+ workBuffer = temp;
+ }
+
+ if (videoFlipTimer) {
+ videoFlipTimer = false;
+
+ tempTimer = frontTimer;
+ frontTimer = backTimer;
+ backTimer = tempTimer;
+ }
+ }
+
+#ifdef MEASURE_ISR_TIME
+ digitalWrite(statusPIN, LOW);
+#endif
+}
diff --git a/Matrix_9x14/libraries/Charliplexing/.svn/text-base/Charliplexing.h.svn-base b/Matrix_9x14/libraries/Charliplexing/.svn/text-base/Charliplexing.h.svn-base
new file mode 100644
index 0000000..6054dc4
--- /dev/null
+++ b/Matrix_9x14/libraries/Charliplexing/.svn/text-base/Charliplexing.h.svn-base
@@ -0,0 +1,34 @@
+/*
+ Charliplexing.h - Library for controlling the charliplexed led board
+ from JimmiePRodgers.com
+ Created by Alex Wenger, December 30, 2009.
+ Modified by Matt Mets, May 28, 2010.
+ Released into the public domain.
+*/
+
+#ifndef Charliplexing_h
+#define Charliplexing_h
+
+#include <inttypes.h>
+
+#define SINGLE_BUFFER 0
+#define DOUBLE_BUFFER 1
+#define GRAYSCALE 2
+
+#define DISPLAY_COLS 14 // Number of columns in the display
+#define DISPLAY_ROWS 9 // Number of rows in the display
+#define SHADES 8 // Number of distinct shades to display, including black, i.e. OFF
+
+namespace LedSign
+{
+ extern void Init(uint8_t mode = SINGLE_BUFFER);
+ extern void Set(uint8_t x, uint8_t y, uint8_t c = 1);
+ extern void SetBrightness(uint8_t brightness);
+ extern volatile unsigned int tcnt2;
+ extern void Flip(bool blocking = false);
+ extern void Clear(int set=0);
+ extern void Horizontal(int y, int set=0);
+ extern void Vertical(int x, int set=0);
+};
+
+#endif
diff --git a/Matrix_9x14/libraries/Charliplexing/.svn/text-base/Figure.cpp.svn-base b/Matrix_9x14/libraries/Charliplexing/.svn/text-base/Figure.cpp.svn-base
new file mode 100644
index 0000000..1b8c9db
--- /dev/null
+++ b/Matrix_9x14/libraries/Charliplexing/.svn/text-base/Figure.cpp.svn-base
@@ -0,0 +1,125 @@
+/*
+ Figure drawing library
+
+ Copyright 2009/2010 Benjamin Sonntag <benjamin@sonntag.fr> http://benjamin.sonntag.fr/
+
+ History:
+ 2010-01-01 - V0.0 Initial code at Berlin after 26C3
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "Charliplexing.h"
+#include "Figure.h"
+
+#if defined(ARDUINO) && ARDUINO >= 100
+#include "Arduino.h"
+#else
+#include "WProgram.h"
+#endif
+#include <inttypes.h>
+
+
+uint8_t figuresData[][14][2] = {
+{ {0,0}, {1,0}, {2,0}, {0,1}, {2,1}, {0,2}, {2,2}, {0,3}, {2,3}, {0,4}, {1,4}, {2,4}, {9,9}, {9,9} },
+{ {1,0}, {0,1}, {1,1}, {1,2}, {1,3}, {0,4}, {1,4}, {2,4}, {9,9}, {9,9}, {9,9}, {9,9}, {9,9}, {9,9} },
+{ {0,0}, {1,0}, {2,0}, {2,1}, {1,2}, {0,3}, {0,4}, {1,4}, {2,4}, {9,9}, {9,9}, {9,9}, {9,9}, {9,9} },
+{ {0,0}, {1,0}, {2,0}, {2,1}, {0,2}, {1,2}, {2,3}, {0,4}, {1,4}, {2,4}, {9,9}, {9,9}, {9,9}, {9,9} },
+{ {0,0}, {2,0}, {0,1}, {2,1}, {0,2}, {1,2}, {2,2}, {2,3}, {2,4}, {9,9}, {9,9}, {9,9}, {9,9}, {9,9} },
+{ {0,0}, {1,0}, {2,0}, {0,1}, {0,2}, {1,2}, {2,2}, {2,3}, {0,4}, {1,4}, {2,4}, {9,9}, {9,9}, {9,9} },
+{ {0,0}, {1,0}, {2,0}, {0,1}, {0,2}, {1,2}, {2,2}, {0,3}, {2,3}, {0,4}, {1,4}, {2,4}, {9,9}, {9,9} },
+{ {0,0}, {1,0}, {2,0}, {2,1}, {2,2}, {1,3}, {1,4}, {9,9}, {9,9}, {9,9}, {9,9}, {9,9}, {9,9}, {9,9} },
+{ {0,0}, {1,0}, {2,0}, {0,1}, {2,1}, {0,2}, {1,2}, {2,2}, {0,3}, {2,3}, {0,4}, {1,4}, {2,4}, {9,9} },
+{ {0,0}, {1,0}, {2,0}, {0,1}, {2,1}, {0,2}, {1,2}, {2,2}, {2,3}, {0,4}, {1,4}, {9,9}, {9,9}, {9,9} }
+};
+
+
+/* ----------------------------------------------------------------- */
+/** Draws a figure (0-9). You should call it with set=1,
+ * wait a little them call it again with set=0
+ * @param figure is the figure [0-9]
+ * @param x,y coordinates,
+ * @param set is 1 or 0 to draw or clear it
+ */
+void Figure::Draw(int figure,int x,int y,int set) {
+ for(int i=0;i<14;i++) {
+ if (figuresData[figure][i][0]==9) break;
+ if (
+ figuresData[figure][i][0]+x<13 &&
+ figuresData[figure][i][0]+x>=0 &&
+ figuresData[figure][i][1]+y<8 &&
+ figuresData[figure][i][1]+y>=0
+ ) {
+ LedSign::Set(figuresData[figure][i][0]+x,figuresData[figure][i][1]+y,set);
+ }
+ }
+}
+
+
+/* ----------------------------------------------------------------- */
+/** Draw a figure in the other direction (rotated 90°)
+ * You should call it with set=1,
+ * wait a little them call it again with set=0
+ * @param figure is the figure [0-9]
+ * @param x,y coordinates,
+ * @param set is 1 or 0 to draw or clear it
+*/
+void Figure::Draw90(int figure,int x,int y,int set) {
+ for(int i=0;i<14;i++) {
+ if (figuresData[figure][i][0]==9) break;
+ if (
+ (5-figuresData[figure][i][1])+x<13 &&
+ (5-figuresData[figure][i][1])+x>=0 &&
+ figuresData[figure][i][0]+y<8 &&
+ figuresData[figure][i][0]+y>=0
+ ) {
+ LedSign::Set((5-figuresData[figure][i][1])+x,figuresData[figure][i][0]+y,set);
+ }
+ }
+}
+
+
+/* ----------------------------------------------------------------- */
+/** Scroll a number from right to left
+ * remove unused figures (0 at the left)
+ * valid for up to 7 figures.
+ * @param value is the value to draw and scroll
+ * @param x is the coordinate where we put the top of the figure [0-13]
+*/
+void Figure::Scroll90(unsigned long value,uint8_t x) {
+ int i,j,k;
+ uint8_t figures[]={
+ (value%10000000)/1000000,
+ (value%1000000)/100000,
+ (value%100000)/10000,
+ (value%10000)/1000,
+ (value%1000)/100,
+ (value%100)/10,
+ (value%10)
+ };
+ j=0;
+ while (figures[j]==0 && j<6) j++;
+
+ for(i=0;i<9+(7-j)*5;i++) {
+ for(k=j;k<=6;k++)
+ Figure::Draw90(figures[k],3,-i+9+4*(k-j) ,1);
+ delay(100);
+ for(k=j;k<=6;k++)
+ Figure::Draw90(figures[k],3,-i+9+4*(k-j) ,0);
+ }
+}
+
+
diff --git a/Matrix_9x14/libraries/Charliplexing/.svn/text-base/Figure.h.svn-base b/Matrix_9x14/libraries/Charliplexing/.svn/text-base/Figure.h.svn-base
new file mode 100644
index 0000000..1b3f1fe
--- /dev/null
+++ b/Matrix_9x14/libraries/Charliplexing/.svn/text-base/Figure.h.svn-base
@@ -0,0 +1,42 @@
+/*
+ Figure drawing library
+
+ Copyright 2009/2010 Benjamin Sonntag <benjamin@sonntag.fr> http://benjamin.sonntag.fr/
+
+ History:
+ 2010-01-01 - V0.0 Initial code at Berlin after 26C3
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef Figures_h
+#define Figures_h
+
+#include <inttypes.h>
+
+namespace Figure
+{
+
+extern void Draw(int figure,int x,int y,int set=1);
+
+extern void Draw90(int figure,int x,int y,int set=1);
+
+extern void Scroll90(unsigned long value,uint8_t x=3);
+
+}
+
+#endif
+
diff --git a/Matrix_9x14/libraries/Charliplexing/.svn/text-base/Font.cpp.svn-base b/Matrix_9x14/libraries/Charliplexing/.svn/text-base/Font.cpp.svn-base
new file mode 100644
index 0000000..441e29c
--- /dev/null
+++ b/Matrix_9x14/libraries/Charliplexing/.svn/text-base/Font.cpp.svn-base
@@ -0,0 +1,219 @@
+#include <avr/pgmspace.h>
+
+/*
+ Font drawing library
+
+ Copyright 2009/2010 Benjamin Sonntag <benjamin@sonntag.fr> http://benjamin.sonntag.fr/
+
+ History:
+ 2010-01-01 - V0.0 Initial code at Berlin after 26C3
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "Font.h"
+#include "Charliplexing.h"
+#include <inttypes.h>
+
+prog_uchar letters_71[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,1, 1,7, 2,1, 2,4, 2,7, 3,1, 3,2, 3,4, 3,5, 3,6, 3,7, 9,9 };
+prog_uchar letters_83[] PROGMEM = { 0,2, 0,3, 0,7, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,1, 3,5, 3,6, 9,9 };
+prog_uchar letters_67[] PROGMEM = { 0,2, 0,3, 0,4, 0,5, 0,6, 1,1, 1,7, 2,1, 2,7, 3,1, 3,7, 9,9 };
+prog_uchar letters_76[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,7, 2,7, 3,7, 9,9 };
+prog_uchar letters_89[] PROGMEM = { 0,1, 0,2, 1,3, 2,4, 2,5, 2,6, 2,7, 3,3, 4,1, 4,2, 9,9 };
+prog_uchar letters_82[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,1, 1,4, 2,1, 2,4, 2,5, 3,1, 3,4, 3,6, 4,2, 4,3, 4,7, 9,9 };
+prog_uchar letters_79[] PROGMEM = { 0,2, 0,3, 0,4, 0,5, 0,6, 1,1, 1,7, 2,1, 2,7, 3,2, 3,3, 3,4, 3,5, 3,6, 9,9 };
+prog_uchar letters_33[] PROGMEM = { 1,1, 1,2, 1,3, 1,4, 1,5, 1,7, 9,9 };
+prog_uchar letters_65[] PROGMEM = { 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,1, 1,4, 2,1, 2,4, 3,2, 3,3, 3,4, 3,5, 3,6, 3,7, 9,9 };
+prog_uchar letters_87[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,6, 2,5, 3,6, 4,1, 4,2, 4,3, 4,4, 4,5, 4,6, 4,7, 9,9 };
+prog_uchar letters_69[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,1, 3,4, 3,7, 9,9 };
+prog_uchar letters_80[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,1, 1,4, 2,1, 2,4, 3,2, 3,3, 9,9 };
+prog_uchar letters_50[] PROGMEM = { 0,2, 0,5, 0,6, 0,7, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,1, 3,4, 3,7, 4,2, 4,3, 4,7, 9,9 };
+prog_uchar letters_49[] PROGMEM = { 1,2, 1,7, 2,1, 2,2, 2,3, 2,4, 2,5, 2,6, 2,7, 3,7, 9,9 };
+prog_uchar letters_74[] PROGMEM = { 0,7, 1,1, 1,7, 2,1, 2,2, 2,3, 2,4, 2,5, 2,6, 3,1, 9,9 };
+prog_uchar letters_68[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,1, 1,7, 2,1, 2,7, 3,2, 3,3, 3,4, 3,5, 3,6, 9,9 };
+prog_uchar letters_90[] PROGMEM = { 0,1, 0,6, 0,7, 1,1, 1,5, 1,7, 2,1, 2,4, 2,7, 3,1, 3,3, 3,7, 4,1, 4,2, 4,7, 9,9 };
+prog_uchar letters_70[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,1, 1,4, 2,1, 2,4, 3,1, 3,4, 9,9 };
+prog_uchar letters_88[] PROGMEM = { 0,1, 0,2, 0,6, 0,7, 1,3, 1,5, 2,4, 3,3, 3,5, 4,1, 4,2, 4,6, 4,7, 9,9 };
+prog_uchar letters_75[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,4, 2,3, 2,5, 3,1, 3,2, 3,6, 3,7, 9,9 };
+prog_uchar letters_53[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,7, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,1, 3,4, 3,7, 4,1, 4,5, 4,6, 9,9 };
+prog_uchar letters_48[] PROGMEM = { 0,2, 0,3, 0,4, 0,5, 0,6, 1,1, 1,7, 2,1, 2,7, 3,1, 3,7, 4,2, 4,3, 4,4, 4,5, 4,6, 9,9 };
+prog_uchar letters_77[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,2, 2,3, 3,2, 4,1, 4,2, 4,3, 4,4, 4,5, 4,6, 4,7, 9,9 };
+prog_uchar letters_54[] PROGMEM = { 0,2, 0,3, 0,4, 0,5, 0,6, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,1, 3,4, 3,7, 4,2, 4,5, 4,6, 9,9 };
+prog_uchar letters_39[] PROGMEM = { 1,3, 2,1, 2,2, 9,9 };
+prog_uchar letters_85[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 1,7, 2,7, 3,1, 3,2, 3,3, 3,4, 3,5, 3,6, 9,9 };
+prog_uchar letters_57[] PROGMEM = { 0,2, 0,3, 0,7, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,1, 3,4, 3,7, 4,2, 4,3, 4,4, 4,5, 4,6, 9,9 };
+prog_uchar letters_78[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,2, 2,3, 3,4, 4,1, 4,2, 4,3, 4,4, 4,5, 4,6, 4,7, 9,9 };
+prog_uchar letters_84[] PROGMEM = { 0,1, 1,1, 1,2, 1,3, 1,4, 1,5, 1,6, 1,7, 2,1, 9,9 };
+prog_uchar letters_81[] PROGMEM = { 0,2, 0,3, 0,4, 0,5, 0,6, 1,1, 1,7, 2,1, 2,5, 2,7, 3,1, 3,6, 4,2, 4,3, 4,4, 4,5, 4,7, 9,9 };
+prog_uchar letters_51[] PROGMEM = { 0,2, 0,6, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,1, 3,4, 3,7, 4,2, 4,3, 4,5, 4,6, 9,9 };
+prog_uchar letters_86[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 1,6, 2,7, 3,6, 4,1, 4,2, 4,3, 4,4, 4,5, 9,9 };
+prog_uchar letters_72[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,4, 2,4, 3,1, 3,2, 3,3, 3,4, 3,5, 3,6, 3,7, 9,9 };
+prog_uchar letters_73[] PROGMEM = { 0,1, 0,7, 1,1, 1,2, 1,3, 1,4, 1,5, 1,6, 1,7, 2,1, 2,7, 9,9 };
+prog_uchar letters_44[] PROGMEM = { 1,7, 2,5, 2,6, 9,9 };
+prog_uchar letters_56[] PROGMEM = { 0,2, 0,3, 0,5, 0,6, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,1, 3,4, 3,7, 4,2, 4,3, 4,5, 4,6, 9,9 };
+prog_uchar letters_66[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,2, 3,3, 3,5, 3,6, 9,9 };
+prog_uchar letters_52[] PROGMEM = { 0,4, 0,5, 1,3, 1,5, 2,2, 2,5, 3,1, 3,2, 3,3, 3,4, 3,5, 3,6, 3,7, 4,5, 9,9 };
+prog_uchar letters_55[] PROGMEM = { 0,1, 1,1, 2,1, 2,5, 2,6, 2,7, 3,1, 3,3, 3,4, 4,1, 4,2, 9,9 };
+
+prog_uchar* font[] = { letters_33 /*!*/, 0, 0, 0, 0, 0, letters_39 /*'*/, 0, 0, 0, 0, letters_44 /*,*/, 0, 0, 0,
+letters_48 /*0*/, letters_49 /*1*/, letters_50 /*2*/, letters_51 /*3*/, letters_52 /*4*/, letters_53 /*5*/,
+letters_54 /*6*/, letters_55 /*7*/, letters_56 /*8*/, letters_57 /*9*/, 0, 0, 0, 0, 0, 0, 0, letters_65 /*A*/,
+letters_66 /*B*/, letters_67 /*C*/, letters_68 /*D*/, letters_69 /*E*/, letters_70 /*F*/, letters_71 /*G*/,
+letters_72 /*H*/, letters_73 /*I*/, letters_74 /*J*/, letters_75 /*K*/, letters_76 /*L*/, letters_77 /*M*/,
+letters_78 /*N*/, letters_79 /*O*/, letters_80 /*P*/, letters_81 /*Q*/, letters_82 /*R*/, letters_83 /*S*/,
+letters_84 /*T*/, letters_85 /*U*/, letters_86 /*V*/, letters_87 /*W*/, letters_88 /*X*/, letters_89 /*Y*/,
+letters_90 /*Z*/
+};
+
+
+uint16_t fontMin=33;
+uint16_t fontMax=90;
+
+#if 0
+
+// This section of the font works now, but doesn't appear to be correct.
+
+prog_uchar letters_117[] PROGMEM = { 0,4, 0,5, 0,6, 1,7, 2,7, 3,4, 3,5, 3,6, 3,7, 9,9 };
+prog_uchar letters_104[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,4, 2,4, 3,5, 3,6, 3,7, 9,9 };
+prog_uchar letters_109[] PROGMEM = { 0,4, 0,5, 0,6, 0,7, 1,4, 2,5, 2,6, 2,7, 3,4, 4,5, 4,6, 4,7, 9,9 };
+prog_uchar letters_114[] PROGMEM = { 0,4, 0,5, 0,6, 0,7, 1,4, 2,4, 9,9 };
+prog_uchar letters_108[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 9,9 };
+prog_uchar letters_116[] PROGMEM = { 0,2, 1,1, 1,2, 1,3, 1,4, 1,5, 1,6, 1,7, 2,2, 2,7, 3,7, 9,9 };
+prog_uchar letters_107[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,5, 2,4, 2,6, 3,3, 3,7, 9,9 };
+prog_uchar letters_118[] PROGMEM = { 0,4, 0,5, 1,6, 2,7, 3,6, 4,4, 4,5, 9,9 };
+prog_uchar letters_98[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,4, 1,7, 2,4, 2,7, 3,5, 3,6, 9,9 };
+prog_uchar letters_120[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,5, 2,4, 2,6, 3,3, 3,7, 9,9 };
+prog_uchar letters_119[] PROGMEM = { 0,4, 0,5, 1,6, 1,7, 2,4, 2,5, 3,6, 3,7, 4,4, 4,5, 9,9 };
+prog_uchar letters_111[] PROGMEM = { 0,5, 0,6, 1,4, 1,7, 2,4, 2,7, 3,5, 3,6, 9,9 };
+prog_uchar letters_105[] PROGMEM = { 0,1, 0,3, 0,4, 0,5, 0,6, 0,7, 9,9 };
+prog_uchar letters_110[] PROGMEM = { 0,4, 0,5, 0,6, 0,7, 1,4, 2,4, 3,5, 3,6, 3,7, 9,9 };
+prog_uchar letters_113[] PROGMEM = { 0,4, 0,5, 1,3, 1,6, 2,3, 2,6, 3,3, 3,4, 3,5, 3,6, 3,7, 3,8, 9,9 };
+prog_uchar letters_100[] PROGMEM = { 0,2, 0,3, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,1, 3,2, 3,3, 3,4, 3,5, 3,6, 9,9 };
+prog_uchar letters_103[] PROGMEM = { 0,3, 0,4, 0,8, 1,2, 1,5, 1,8, 2,2, 2,5, 2,8, 3,2, 3,3, 3,4, 3,5, 3,6, 3,7, 9,9 };
+prog_uchar letters_112[] PROGMEM = { 0,3, 0,4, 0,5, 0,6, 0,7, 0,8, 1,3, 1,6, 2,3, 2,6, 3,4, 3,5, 9,9 };
+prog_uchar letters_101[] PROGMEM = { 0,4, 0,5, 0,6, 1,3, 1,5, 1,7, 2,3, 2,5, 2,7, 3,4, 3,5, 3,7, 9,9 };
+prog_uchar letters_102[] PROGMEM = { 0,5, 1,1, 1,2, 1,3, 1,4, 1,5, 1,6, 1,7, 2,1, 2,5, 3,1, 9,9 };
+prog_uchar letters_115[] PROGMEM = { 0,3, 0,4, 0,7, 1,3, 1,5, 1,7, 2,3, 2,5, 2,7, 3,3, 3,5, 3,6, 3,7, 9,9 };
+prog_uchar letters_99[] PROGMEM = { 0,5, 0,6, 1,4, 1,7, 2,4, 2,7, 3,4, 3,7, 9,9 };
+prog_uchar letters_106[] PROGMEM = { 0,8, 1,2, 1,4, 1,5, 1,6, 1,7, 1,8, 9,9 };
+prog_uchar letters_97[] PROGMEM = { 0,6, 0,7, 1,3, 1,5, 1,7, 2,3, 2,5, 2,7, 3,4, 3,5, 3,6, 3,7, 9,9 };
+
+prog_uchar* font2[] = { 0, 0, 0, 0, 0, 0, letters_97 /*a*/, letters_98 /*b*/, letters_99 /*c*/, letters_100 /*d*/, letters_101 /*e*/, letters_102 /*f*/, letters_103 /*g*/, letters_104 /*h*/, letters_105 /*i*/, letters_106 /*j*/, letters_107 /*k*/, letters_108 /*l*/, letters_109 /*m*/, letters_110 /*n*/, letters_111 /*o*/, letters_112 /*p*/, letters_113 /*q*/, letters_114 /*r*/, letters_115 /*s*/, letters_116 /*t*/, letters_117 /*u*/, letters_118 /*v*/, letters_119 /*w*/, letters_120 /*x*/ };
+*/
+
+#endif
+
+/* ----------------------------------------------------------------- */
+/** Draws a figure (0-9). You should call it with set=1,
+ * wait a little them call it again with set=0
+ * @param figure is the figure [0-9]
+ * @param x,y coordinates,
+ * @param set is 1 or 0 to draw or clear it
+ */
+uint8_t Font::Draw(unsigned char letter,int x,int y,int set) {
+ uint16_t maxx=0;
+
+ uint8_t charCol;
+ uint8_t charRow;
+
+ prog_uchar* character;
+ if (letter==' ') return 3+2;
+ if (letter<fontMin || letter>fontMax) {
+ return 0;
+ }
+
+// if (letter>90) {
+// character = font2[letter-90];
+// } else {
+ character = font[letter-fontMin];
+// }
+
+ int i=0;
+
+ charCol = pgm_read_byte_near(character);
+ charRow = pgm_read_byte_near(character + 1);
+
+ while (charRow!=9) {
+ if (charCol>maxx) maxx=charCol;
+ if (
+ charCol + x <14 &&
+ charCol + x >=0 &&
+ charRow + y <8 &&
+ charRow + y >=0
+ ) {
+ LedSign::Set(charCol + x, charRow+y, set);
+ }
+ i+=2;
+
+ charCol = pgm_read_byte_near(character + i);
+ charRow = pgm_read_byte_near(character + 1 + i);
+ }
+ return maxx+2;
+}
+
+
+/* ----------------------------------------------------------------- */
+/** Draw a figure in the other direction (rotated 90°)
+ * @param figure is the figure [0-9]
+ * @param x,y coordinates,
+ * @param set is 1 or 0 to draw or clear it
+*/
+uint8_t Font::Draw90(unsigned char letter,int x,int y,int set) {
+ uint16_t maxx=0;
+
+ uint8_t charCol;
+ uint8_t charRow;
+
+ prog_uchar* character;
+ if (letter==' ') return 3+2;
+ if (letter<fontMin || letter>fontMax) {
+ return 0;
+ }
+
+// if (letter>90) {
+// character = font2[letter-90];
+// } else {
+ character = font[letter-fontMin];
+// }
+
+ int i=0;
+
+ charCol = pgm_read_byte_near(character);
+ charRow = pgm_read_byte_near(character + 1);
+
+ while (charRow!=9) {
+ if (charCol>maxx) maxx=charCol;
+ if (
+ charRow + x <14 &&
+ charRow + x >=0 &&
+ charCol + y <8 &&
+ charCol + y >=0
+ ) {
+ LedSign::Set(7 - charRow + x, charCol + y, set);
+ }
+ i+=2;
+
+ charCol = pgm_read_byte_near(character + i);
+ charRow = pgm_read_byte_near(character + 1 + i);
+ }
+ return maxx+2;
+
+}
+
+
+
+
+
diff --git a/Matrix_9x14/libraries/Charliplexing/.svn/text-base/Font.h.svn-base b/Matrix_9x14/libraries/Charliplexing/.svn/text-base/Font.h.svn-base
new file mode 100644
index 0000000..84dd77a
--- /dev/null
+++ b/Matrix_9x14/libraries/Charliplexing/.svn/text-base/Font.h.svn-base
@@ -0,0 +1,40 @@
+/*
+ Font drawing library
+
+ Copyright 2009/2010 Benjamin Sonntag <benjamin@sonntag.fr> http://benjamin.sonntag.fr/
+
+ History:
+ 2010-01-01 - V0.0 Initial code at Berlin after 26C3
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef Font_h
+#define Font_h
+
+#include <inttypes.h>
+
+namespace Font
+{
+
+extern uint8_t Draw(unsigned char letter,int x,int y,int set=1);
+
+extern uint8_t Draw90(unsigned char letter,int x,int y,int set=1);
+
+}
+
+#endif
+
diff --git a/Matrix_9x14/libraries/Charliplexing/.svn/text-base/keywords.txt.svn-base b/Matrix_9x14/libraries/Charliplexing/.svn/text-base/keywords.txt.svn-base
new file mode 100644
index 0000000..99c8d02
--- /dev/null
+++ b/Matrix_9x14/libraries/Charliplexing/.svn/text-base/keywords.txt.svn-base
@@ -0,0 +1,14 @@
+LedSign KEYWORD1
+Init KEYWORD2
+Set KEYWORD2
+Flip KEYWORD2
+Clear KEYWORD2
+Horizontal KEYWORD2
+Vertical KEYWORD2
+Figure KEYWORD1
+Draw KEYWORD2
+Draw90 KEYWORD2
+Scroll90 KEYWORD2
+Font KEYWORD1
+Draw KEYWORD2
+Draw90 KEYWORD2
diff --git a/Matrix_9x14/libraries/Charliplexing/Charliplexing.cpp b/Matrix_9x14/libraries/Charliplexing/Charliplexing.cpp
new file mode 100644
index 0000000..d68b209
--- /dev/null
+++ b/Matrix_9x14/libraries/Charliplexing/Charliplexing.cpp
@@ -0,0 +1,502 @@
+/*
+ Charliplexing.cpp - Using timer2 with 1ms resolution
+
+ Alex Wenger <a.wenger@gmx.de> http://arduinobuch.wordpress.com/
+ Matt Mets <mahto@cibomahto.com> http://cibomahto.com/
+
+ Timer init code from MsTimer2 - Javier Valencia <javiervalencia80@gmail.com>
+ Misc functions from Benjamin Sonnatg <benjamin@sonntag.fr>
+
+ History:
+ 2009-12-30 - V0.0 wrote the first version at 26C3/Berlin
+ 2010-01-01 - V0.1 adding misc utility functions
+ (Clear, Vertical, Horizontal) comment are Doxygen complaints now
+ 2010-05-27 - V0.2 add double-buffer mode
+ 2010-08-18 - V0.9 Merge brightness and grayscale
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#if defined(ARDUINO) && ARDUINO >= 100
+#include "Arduino.h"
+#else
+#include "WProgram.h"
+#endif
+#include <inttypes.h>
+#include <math.h>
+#include <avr/interrupt.h>
+#include "Charliplexing.h"
+
+volatile unsigned int LedSign::tcnt2;
+
+
+struct videoPage {
+ uint8_t pixels[SHADES][48]; // TODO: is 48 right?
+};
+
+/* ----------------------------------------------------------------- */
+/** Table for the LED multiplexing cycles
+ * Each frame is made of 24 bytes (for the 24 display cycles)
+ * There are SHADES frames per buffer in grayscale mode (one for each brigtness)
+ * and twice that many to support double-buffered grayscale.
+ */
+videoPage leds[2];
+
+/// Determines whether the display is in single or double buffer mode
+uint8_t displayMode = SINGLE_BUFFER;
+
+/// Flag indicating that the display page should be flipped as soon as the
+/// current frame is displayed
+volatile boolean videoFlipPage = false;
+
+/// Pointer to the buffer that is currently being displayed
+videoPage* displayBuffer;
+
+/// Pointer to the buffer that should currently be drawn to
+videoPage* workBuffer;
+
+/// Flag indicating that the timer buffer should be flipped as soon as the
+/// current frame is displayed
+volatile boolean videoFlipTimer = false;
+
+
+// Timer counts to display each page for, plus off time
+typedef struct timerInfo {
+ uint8_t counts[SHADES];
+ uint8_t prescaler[SHADES];
+};
+
+// Double buffer the timing information, of course.
+timerInfo* frontTimer;
+timerInfo* backTimer;
+
+timerInfo* tempTimer;
+
+timerInfo timer[2];
+
+// Record a slow and fast prescaler for later use
+typedef struct prescalerInfo {
+ uint8_t relativeSpeed;
+ uint8_t TCCR2;
+};
+
+// TODO: Generate these based on processor type and clock speed
+prescalerInfo slowPrescaler = {1, 0x03};
+//prescalerInfo fastPrescaler = {32, 0x01};
+prescalerInfo fastPrescaler = {4, 0x02};
+
+static bool initialized = false;
+
+/// Uncomment to set analog pin 5 high during interrupts, so that an
+/// oscilloscope can be used to measure the processor time taken by it
+#define MEASURE_ISR_TIME
+#ifdef MEASURE_ISR_TIME
+uint8_t statusPIN = 19;
+#endif
+
+typedef struct LEDPosition {
+ uint8_t high;
+ uint8_t low;
+};
+
+
+/* ----------------------------------------------------------------- */
+/** Table for LED Position in leds[] ram table
+ */
+
+const LEDPosition ledMap[126] = {
+ {13, 5}, {13, 6}, {13, 7}, {13, 8}, {13, 9}, {13,10}, {13,11}, {13,12},
+ {13, 4}, { 4,13}, {13, 3}, { 3,13}, {13, 2}, { 2,13},
+ {12, 5}, {12, 6}, {12, 7}, {12, 8}, {12, 9}, {12,10}, {12,11}, {12,13},
+ {12, 4}, { 4,12}, {12, 3}, { 3,12}, {12, 2}, { 2,12},
+ {11, 5}, {11, 6}, {11, 7}, {11, 8}, {11, 9}, {11,10}, {11,12}, {11,13},
+ {11, 4}, { 4,11}, {11, 3}, { 3,11}, {11, 2}, { 2,11},
+ {10, 5}, {10, 6}, {10, 7}, {10, 8}, {10, 9}, {10,11}, {10,12}, {10,13},
+ {10, 4}, { 4,10}, {10, 3}, { 3,10}, {10, 2}, { 2,10},
+ { 9, 5}, { 9, 6}, { 9, 7}, { 9, 8}, { 9,10}, { 9,11}, { 9,12}, { 9,13},
+ { 9, 4}, { 4, 9}, { 9, 3}, { 3, 9}, { 9, 2}, { 2, 9},
+ { 8, 5}, { 8, 6}, { 8, 7}, { 8, 9}, { 8,10}, { 8,11}, { 8,12}, { 8,13},
+ { 8, 4}, { 4, 8}, { 8, 3}, { 3, 8}, { 8, 2}, { 2, 8},
+ { 7, 5}, { 7, 6}, { 7, 8}, { 7, 9}, { 7,10}, { 7,11}, { 7,12}, { 7,13},
+ { 7, 4}, { 4, 7}, { 7, 3}, { 3, 7}, { 7, 2}, { 2, 7},
+ { 6, 5}, { 6, 7}, { 6, 8}, { 6, 9}, { 6,10}, { 6,11}, { 6,12}, { 6,13},
+ { 6, 4}, { 4, 6}, { 6, 3}, { 3, 6}, { 6, 2}, { 2, 6},
+ { 5, 6}, { 5, 7}, { 5, 8}, { 5, 9}, { 5,10}, { 5,11}, { 5,12}, { 5,13},
+ { 5, 4}, { 4, 5}, { 5, 3}, { 3, 5}, { 5, 2}, { 2, 5},
+};
+
+
+/* ----------------------------------------------------------------- */
+/** Constructor : Initialize the interrupt code.
+ * should be called in setup();
+ */
+void LedSign::Init(uint8_t mode)
+{
+#ifdef MEASURE_ISR_TIME
+ pinMode(statusPIN, OUTPUT);
+ digitalWrite(statusPIN, LOW);
+#endif
+
+ float prescaler = 0.0;
+
+#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1280__)
+ TIMSK2 &= ~(1<<TOIE2);
+ TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
+ TCCR2B &= ~(1<<WGM22);
+ ASSR &= ~(1<<AS2);
+ TIMSK2 &= ~(1<<OCIE2A);
+
+ if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64
+ TCCR2B |= ((1<<CS21) | (1<<CS20));
+ TCCR2B &= ~(1<<CS22);
+ prescaler = 32.0;
+ } else if (F_CPU < 1000000UL) { // prescaler set to 8
+ TCCR2B |= (1<<CS21);
+ TCCR2B &= ~((1<<CS22) | (1<<CS20));
+ prescaler = 8.0;
+ } else { // F_CPU > 16Mhz, prescaler set to 128
+ TCCR2B |= (1<<CS22);
+ TCCR2B &= ~((1<<CS21) | (1<<CS20));
+ prescaler = 64.0;
+ }
+#elif defined (__AVR_ATmega8__)
+ TIMSK &= ~(1<<TOIE2);
+ TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
+ TIMSK &= ~(1<<OCIE2);
+ ASSR &= ~(1<<AS2);
+
+ if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64
+ TCCR2 |= (1<<CS22);
+ TCCR2 &= ~((1<<CS21) | (1<<CS20));
+ prescaler = 64.0;
+ } else if (F_CPU < 1000000UL) { // prescaler set to 8
+ TCCR2 |= (1<<CS21);
+ TCCR2 &= ~((1<<CS22) | (1<<CS20));
+ prescaler = 8.0;
+ } else { // F_CPU > 16Mhz, prescaler set to 128
+ TCCR2 |= ((1<<CS22) && (1<<CS20));
+ TCCR2 &= ~(1<<CS21);
+ prescaler = 128.0;
+ }
+#elif defined (__AVR_ATmega128__)
+ TIMSK &= ~(1<<TOIE2);
+ TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
+ TIMSK &= ~(1<<OCIE2);
+
+ if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64
+ TCCR2 |= ((1<<CS21) | (1<<CS20));
+ TCCR2 &= ~(1<<CS22);
+ prescaler = 64.0;
+ } else if (F_CPU < 1000000UL) { // prescaler set to 8
+ TCCR2 |= (1<<CS21);
+ TCCR2 &= ~((1<<CS22) | (1<<CS20));
+ prescaler = 8.0;
+ } else { // F_CPU > 16Mhz, prescaler set to 256
+ TCCR2 |= (1<<CS22);
+ TCCR2 &= ~((1<<CS21) | (1<<CS20));
+ prescaler = 256.0;
+ }
+#endif
+
+ tcnt2 = 256 - (int)((float)F_CPU * 0.0005 / prescaler);
+
+ // Record whether we are in single or double buffer mode
+ displayMode = mode;
+ videoFlipPage = false;
+
+ // Point the display buffer to the first physical buffer
+ displayBuffer = &leds[0];
+
+ // If we are in single buffered mode, point the work buffer
+ // at the same physical buffer as the display buffer. Otherwise,
+ // point it at the second physical buffer.
+ if( displayMode & DOUBLE_BUFFER ) {
+ workBuffer = &leds[1];
+ }
+ else {
+ workBuffer = displayBuffer;
+ }
+
+ // Set up the timer buffering
+ frontTimer = &timer[0];
+ backTimer = &timer[1];
+
+ videoFlipTimer = false;
+ SetBrightness(127);
+
+ // Clear the buffer and display it
+ LedSign::Clear(0);
+ LedSign::Flip(false);
+
+ // Then start the display
+ TCNT2 = tcnt2;
+#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1280__)
+ TIMSK2 |= (1<<TOIE2);
+#elif defined (__AVR_ATmega128__) || defined (__AVR_ATmega8__)
+ TIMSK |= (1<<TOIE2);
+#endif
+
+ // If we are in double-buffer mode, wait until the display flips before we
+ // return
+ if (displayMode & DOUBLE_BUFFER)
+ {
+ while (videoFlipPage) {
+ delay(1);
+ }
+ }
+
+ initialized = true;
+}
+
+
+/* ----------------------------------------------------------------- */
+/** Signal that the front and back buffers should be flipped
+ * @param blocking if true : wait for flip before returning, if false :
+ * return immediately.
+ */
+void LedSign::Flip(bool blocking)
+{
+ if (displayMode & DOUBLE_BUFFER)
+ {
+ // Just set the flip flag, the buffer will flip between redraws
+ videoFlipPage = true;
+
+ // If we are blocking, sit here until the page flips.
+ while (blocking && videoFlipPage) {
+ delay(1);
+ }
+ }
+}
+
+
+/* ----------------------------------------------------------------- */
+/** Clear the screen completely
+ * @param set if 1 : make all led ON, if not set or 0 : make all led OFF
+ */
+void LedSign::Clear(int set) {
+ for(int x=0;x<14;x++)
+ for(int y=0;y<9;y++)
+ Set(x,y,set);
+}
+
+
+/* ----------------------------------------------------------------- */
+/** Clear an horizontal line completely
+ * @param y is the y coordinate of the line to clear/light [0-8]
+ * @param set if 1 : make all led ON, if not set or 0 : make all led OFF
+ */
+void LedSign::Horizontal(int y, int set) {
+ for(int x=0;x<14;x++)
+ Set(x,y,set);
+}
+
+
+/* ----------------------------------------------------------------- */
+/** Clear a vertical line completely
+ * @param x is the x coordinate of the line to clear/light [0-13]
+ * @param set if 1 : make all led ON, if not set or 0 : make all led OFF
+ */
+void LedSign::Vertical(int x, int set) {
+ for(int y=0;y<9;y++)
+ Set(x,y,set);
+}
+
+
+/* ----------------------------------------------------------------- */
+/** Set : switch on and off the leds. All the position #for char in frameString:
+ * calculations are done here, so we don't need to do in the
+ * interrupt code
+ */
+void LedSign::Set(uint8_t x, uint8_t y, uint8_t c)
+{
+ uint8_t pin_high = ledMap[x+y*14].high;
+ uint8_t pin_low = ledMap[x+y*14].low;
+ // pin_low is directly the address in the led array (minus 2 because the
+ // first two bytes are used for RS232 communication), but
+ // as it is a two byte array we need to check pin_high also.
+ // If pin_high is bigger than 8 address has to be increased by one
+
+ uint8_t bufferNum = (pin_low-2)*2 + (pin_high / 8) + ((pin_high > 7)?24:0);
+ uint8_t work = _BV(pin_high & 0x07);
+
+ // If we aren't in grayscale mode, just map any pin brightness to max
+ if (c > 0 && !(displayMode & GRAYSCALE)) {
+ c = SHADES-1;
+ }
+
+ for (int i = 0; i < SHADES-1; i++) {
+ if( c > i ) {
+ workBuffer->pixels[i][bufferNum] |= work; // ON
+ }
+ else {
+ workBuffer->pixels[i][bufferNum] &= ~work; // OFF
+ }
+ }
+}
+
+
+/* Set the overall brightness of the screen
+ * @param brightness LED brightness, from 0 (off) to 127 (full on)
+ */
+
+void LedSign::SetBrightness(uint8_t brightness)
+{
+ // An exponential fit seems to approximate a (perceived) linear scale
+ float brightnessPercent = ((float)brightness / 127)*((float)brightness / 127);
+ uint8_t difference = 0;
+
+ /* ---- This needs review! Please review. -- thilo */
+ // set up page counts
+ // TODO: make SHADES a function parameter. This would require some refactoring.
+ int start = 15;
+ int max = 255;
+ float scale = 1.5;
+ float delta = pow( max - start , 1.0 / scale) / (SHADES - 1);
+ uint8_t pageCounts[SHADES];
+
+ pageCounts[0] = max - start;
+ for (uint8_t i=1; i<SHADES; i++) {
+ pageCounts[i] = max - ( pow( i * delta, scale ) + start );
+ }
+ Serial.end();
+
+ if (! initialized) {
+ // set front timer defaults
+ for (int i = 0; i < SHADES; i++) {
+ frontTimer->counts[i] = pageCounts[i];
+ // TODO: Generate this dynamically
+ frontTimer->prescaler[i] = slowPrescaler.TCCR2;
+ }
+ }
+
+ // Wait until the previous brightness request goes through
+ while( videoFlipTimer ) {
+ delay(1);
+ }
+
+ // Compute on time for each of the pages
+ // Use the fast timer; slow timer is only useful for < 3 shades.
+ for (uint8_t i = 0; i < SHADES - 1; i++) {
+ uint8_t interval = 255 - pageCounts[i];
+
+ backTimer->counts[i] = 255 - brightnessPercent
+ * interval
+ * fastPrescaler.relativeSpeed;
+ backTimer->prescaler[i] = fastPrescaler.TCCR2;
+ difference += backTimer->counts[i] - pageCounts[i];
+ }
+
+ // Compute off time
+ backTimer->counts[SHADES - 1] = 255 - difference;
+ backTimer->prescaler[SHADES - 1] = slowPrescaler.TCCR2;
+
+ /* ---- End of "This needs review! Please review." -- thilo */
+
+ // Have the ISR update the timer registers next run
+ videoFlipTimer = true;
+}
+
+
+/* ----------------------------------------------------------------- */
+/** The Interrupt code goes here !
+ */
+ISR(TIMER2_OVF_vect) {
+ DDRD = 0x0;
+ DDRB = 0x0;
+#ifdef MEASURE_ISR_TIME
+ digitalWrite(statusPIN, HIGH);
+#endif
+
+ // For each cycle, we have potential SHADES pages to display.
+ // Once every page has been displayed, then we move on to the next
+ // cycle.
+
+ // 24 Cycles of Matrix
+ static uint8_t cycle = 0;
+
+ // SHADES pages to display
+ static uint8_t page = 0;
+
+ TCCR2B = frontTimer->prescaler[page];
+ TCNT2 = frontTimer->counts[page];
+
+ if ( page < SHADES - 1) {
+
+ if (cycle < 6) {
+ DDRD = _BV(cycle+2) | displayBuffer->pixels[page][cycle*2];
+ PORTD = displayBuffer->pixels[page][cycle*2];
+
+ DDRB = displayBuffer->pixels[page][cycle*2+1];
+ PORTB = displayBuffer->pixels[page][cycle*2+1];
+ } else if (cycle < 12) {
+ DDRD = displayBuffer->pixels[page][cycle*2];
+ PORTD = displayBuffer->pixels[page][cycle*2];
+
+ DDRB = _BV(cycle-6) | displayBuffer->pixels[page][cycle*2+1];
+ PORTB = displayBuffer->pixels[page][cycle*2+1];
+ } else if (cycle < 18) {
+ DDRD = _BV(cycle+2-12) | displayBuffer->pixels[page][cycle*2];
+ PORTD = displayBuffer->pixels[page][cycle*2];
+
+ DDRB = displayBuffer->pixels[page][cycle*2+1];
+ PORTB = displayBuffer->pixels[page][cycle*2+1];
+ } else {
+ DDRD = displayBuffer->pixels[page][cycle*2];
+ PORTD = displayBuffer->pixels[page][cycle*2];
+
+ DDRB = _BV(cycle-6-12) | displayBuffer->pixels[page][cycle*2+1];
+ PORTB = displayBuffer->pixels[page][cycle*2+1];
+ }
+ }
+ else {
+ // Turn everything off
+ DDRD = 0x0;
+ DDRB = 0x0;
+ }
+
+ page++;
+
+ if (page >= SHADES) {
+ page = 0;
+ cycle++;
+ }
+
+ if (cycle > 24) {
+ cycle = 0;
+
+ // If the page should be flipped, do it here.
+ if (videoFlipPage && (displayMode & DOUBLE_BUFFER))
+ {
+ // TODO: is this an atomic operation?
+ videoFlipPage = false;
+
+ videoPage* temp = displayBuffer;
+ displayBuffer = workBuffer;
+ workBuffer = temp;
+ }
+
+ if (videoFlipTimer) {
+ videoFlipTimer = false;
+
+ tempTimer = frontTimer;
+ frontTimer = backTimer;
+ backTimer = tempTimer;
+ }
+ }
+
+#ifdef MEASURE_ISR_TIME
+ digitalWrite(statusPIN, LOW);
+#endif
+}
diff --git a/Matrix_9x14/libraries/Charliplexing/Charliplexing.h b/Matrix_9x14/libraries/Charliplexing/Charliplexing.h
new file mode 100644
index 0000000..6054dc4
--- /dev/null
+++ b/Matrix_9x14/libraries/Charliplexing/Charliplexing.h
@@ -0,0 +1,34 @@
+/*
+ Charliplexing.h - Library for controlling the charliplexed led board
+ from JimmiePRodgers.com
+ Created by Alex Wenger, December 30, 2009.
+ Modified by Matt Mets, May 28, 2010.
+ Released into the public domain.
+*/
+
+#ifndef Charliplexing_h
+#define Charliplexing_h
+
+#include <inttypes.h>
+
+#define SINGLE_BUFFER 0
+#define DOUBLE_BUFFER 1
+#define GRAYSCALE 2
+
+#define DISPLAY_COLS 14 // Number of columns in the display
+#define DISPLAY_ROWS 9 // Number of rows in the display
+#define SHADES 8 // Number of distinct shades to display, including black, i.e. OFF
+
+namespace LedSign
+{
+ extern void Init(uint8_t mode = SINGLE_BUFFER);
+ extern void Set(uint8_t x, uint8_t y, uint8_t c = 1);
+ extern void SetBrightness(uint8_t brightness);
+ extern volatile unsigned int tcnt2;
+ extern void Flip(bool blocking = false);
+ extern void Clear(int set=0);
+ extern void Horizontal(int y, int set=0);
+ extern void Vertical(int x, int set=0);
+};
+
+#endif
diff --git a/Matrix_9x14/libraries/Charliplexing/Figure.cpp b/Matrix_9x14/libraries/Charliplexing/Figure.cpp
new file mode 100644
index 0000000..1b8c9db
--- /dev/null
+++ b/Matrix_9x14/libraries/Charliplexing/Figure.cpp
@@ -0,0 +1,125 @@
+/*
+ Figure drawing library
+
+ Copyright 2009/2010 Benjamin Sonntag <benjamin@sonntag.fr> http://benjamin.sonntag.fr/
+
+ History:
+ 2010-01-01 - V0.0 Initial code at Berlin after 26C3
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "Charliplexing.h"
+#include "Figure.h"
+
+#if defined(ARDUINO) && ARDUINO >= 100
+#include "Arduino.h"
+#else
+#include "WProgram.h"
+#endif
+#include <inttypes.h>
+
+
+uint8_t figuresData[][14][2] = {
+{ {0,0}, {1,0}, {2,0}, {0,1}, {2,1}, {0,2}, {2,2}, {0,3}, {2,3}, {0,4}, {1,4}, {2,4}, {9,9}, {9,9} },
+{ {1,0}, {0,1}, {1,1}, {1,2}, {1,3}, {0,4}, {1,4}, {2,4}, {9,9}, {9,9}, {9,9}, {9,9}, {9,9}, {9,9} },
+{ {0,0}, {1,0}, {2,0}, {2,1}, {1,2}, {0,3}, {0,4}, {1,4}, {2,4}, {9,9}, {9,9}, {9,9}, {9,9}, {9,9} },
+{ {0,0}, {1,0}, {2,0}, {2,1}, {0,2}, {1,2}, {2,3}, {0,4}, {1,4}, {2,4}, {9,9}, {9,9}, {9,9}, {9,9} },
+{ {0,0}, {2,0}, {0,1}, {2,1}, {0,2}, {1,2}, {2,2}, {2,3}, {2,4}, {9,9}, {9,9}, {9,9}, {9,9}, {9,9} },
+{ {0,0}, {1,0}, {2,0}, {0,1}, {0,2}, {1,2}, {2,2}, {2,3}, {0,4}, {1,4}, {2,4}, {9,9}, {9,9}, {9,9} },
+{ {0,0}, {1,0}, {2,0}, {0,1}, {0,2}, {1,2}, {2,2}, {0,3}, {2,3}, {0,4}, {1,4}, {2,4}, {9,9}, {9,9} },
+{ {0,0}, {1,0}, {2,0}, {2,1}, {2,2}, {1,3}, {1,4}, {9,9}, {9,9}, {9,9}, {9,9}, {9,9}, {9,9}, {9,9} },
+{ {0,0}, {1,0}, {2,0}, {0,1}, {2,1}, {0,2}, {1,2}, {2,2}, {0,3}, {2,3}, {0,4}, {1,4}, {2,4}, {9,9} },
+{ {0,0}, {1,0}, {2,0}, {0,1}, {2,1}, {0,2}, {1,2}, {2,2}, {2,3}, {0,4}, {1,4}, {9,9}, {9,9}, {9,9} }
+};
+
+
+/* ----------------------------------------------------------------- */
+/** Draws a figure (0-9). You should call it with set=1,
+ * wait a little them call it again with set=0
+ * @param figure is the figure [0-9]
+ * @param x,y coordinates,
+ * @param set is 1 or 0 to draw or clear it
+ */
+void Figure::Draw(int figure,int x,int y,int set) {
+ for(int i=0;i<14;i++) {
+ if (figuresData[figure][i][0]==9) break;
+ if (
+ figuresData[figure][i][0]+x<13 &&
+ figuresData[figure][i][0]+x>=0 &&
+ figuresData[figure][i][1]+y<8 &&
+ figuresData[figure][i][1]+y>=0
+ ) {
+ LedSign::Set(figuresData[figure][i][0]+x,figuresData[figure][i][1]+y,set);
+ }
+ }
+}
+
+
+/* ----------------------------------------------------------------- */
+/** Draw a figure in the other direction (rotated 90°)
+ * You should call it with set=1,
+ * wait a little them call it again with set=0
+ * @param figure is the figure [0-9]
+ * @param x,y coordinates,
+ * @param set is 1 or 0 to draw or clear it
+*/
+void Figure::Draw90(int figure,int x,int y,int set) {
+ for(int i=0;i<14;i++) {
+ if (figuresData[figure][i][0]==9) break;
+ if (
+ (5-figuresData[figure][i][1])+x<13 &&
+ (5-figuresData[figure][i][1])+x>=0 &&
+ figuresData[figure][i][0]+y<8 &&
+ figuresData[figure][i][0]+y>=0
+ ) {
+ LedSign::Set((5-figuresData[figure][i][1])+x,figuresData[figure][i][0]+y,set);
+ }
+ }
+}
+
+
+/* ----------------------------------------------------------------- */
+/** Scroll a number from right to left
+ * remove unused figures (0 at the left)
+ * valid for up to 7 figures.
+ * @param value is the value to draw and scroll
+ * @param x is the coordinate where we put the top of the figure [0-13]
+*/
+void Figure::Scroll90(unsigned long value,uint8_t x) {
+ int i,j,k;
+ uint8_t figures[]={
+ (value%10000000)/1000000,
+ (value%1000000)/100000,
+ (value%100000)/10000,
+ (value%10000)/1000,
+ (value%1000)/100,
+ (value%100)/10,
+ (value%10)
+ };
+ j=0;
+ while (figures[j]==0 && j<6) j++;
+
+ for(i=0;i<9+(7-j)*5;i++) {
+ for(k=j;k<=6;k++)
+ Figure::Draw90(figures[k],3,-i+9+4*(k-j) ,1);
+ delay(100);
+ for(k=j;k<=6;k++)
+ Figure::Draw90(figures[k],3,-i+9+4*(k-j) ,0);
+ }
+}
+
+
diff --git a/Matrix_9x14/libraries/Charliplexing/Figure.h b/Matrix_9x14/libraries/Charliplexing/Figure.h
new file mode 100644
index 0000000..1b3f1fe
--- /dev/null
+++ b/Matrix_9x14/libraries/Charliplexing/Figure.h
@@ -0,0 +1,42 @@
+/*
+ Figure drawing library
+
+ Copyright 2009/2010 Benjamin Sonntag <benjamin@sonntag.fr> http://benjamin.sonntag.fr/
+
+ History:
+ 2010-01-01 - V0.0 Initial code at Berlin after 26C3
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef Figures_h
+#define Figures_h
+
+#include <inttypes.h>
+
+namespace Figure
+{
+
+extern void Draw(int figure,int x,int y,int set=1);
+
+extern void Draw90(int figure,int x,int y,int set=1);
+
+extern void Scroll90(unsigned long value,uint8_t x=3);
+
+}
+
+#endif
+
diff --git a/Matrix_9x14/libraries/Charliplexing/Font.cpp b/Matrix_9x14/libraries/Charliplexing/Font.cpp
new file mode 100644
index 0000000..441e29c
--- /dev/null
+++ b/Matrix_9x14/libraries/Charliplexing/Font.cpp
@@ -0,0 +1,219 @@
+#include <avr/pgmspace.h>
+
+/*
+ Font drawing library
+
+ Copyright 2009/2010 Benjamin Sonntag <benjamin@sonntag.fr> http://benjamin.sonntag.fr/
+
+ History:
+ 2010-01-01 - V0.0 Initial code at Berlin after 26C3
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include "Font.h"
+#include "Charliplexing.h"
+#include <inttypes.h>
+
+prog_uchar letters_71[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,1, 1,7, 2,1, 2,4, 2,7, 3,1, 3,2, 3,4, 3,5, 3,6, 3,7, 9,9 };
+prog_uchar letters_83[] PROGMEM = { 0,2, 0,3, 0,7, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,1, 3,5, 3,6, 9,9 };
+prog_uchar letters_67[] PROGMEM = { 0,2, 0,3, 0,4, 0,5, 0,6, 1,1, 1,7, 2,1, 2,7, 3,1, 3,7, 9,9 };
+prog_uchar letters_76[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,7, 2,7, 3,7, 9,9 };
+prog_uchar letters_89[] PROGMEM = { 0,1, 0,2, 1,3, 2,4, 2,5, 2,6, 2,7, 3,3, 4,1, 4,2, 9,9 };
+prog_uchar letters_82[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,1, 1,4, 2,1, 2,4, 2,5, 3,1, 3,4, 3,6, 4,2, 4,3, 4,7, 9,9 };
+prog_uchar letters_79[] PROGMEM = { 0,2, 0,3, 0,4, 0,5, 0,6, 1,1, 1,7, 2,1, 2,7, 3,2, 3,3, 3,4, 3,5, 3,6, 9,9 };
+prog_uchar letters_33[] PROGMEM = { 1,1, 1,2, 1,3, 1,4, 1,5, 1,7, 9,9 };
+prog_uchar letters_65[] PROGMEM = { 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,1, 1,4, 2,1, 2,4, 3,2, 3,3, 3,4, 3,5, 3,6, 3,7, 9,9 };
+prog_uchar letters_87[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,6, 2,5, 3,6, 4,1, 4,2, 4,3, 4,4, 4,5, 4,6, 4,7, 9,9 };
+prog_uchar letters_69[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,1, 3,4, 3,7, 9,9 };
+prog_uchar letters_80[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,1, 1,4, 2,1, 2,4, 3,2, 3,3, 9,9 };
+prog_uchar letters_50[] PROGMEM = { 0,2, 0,5, 0,6, 0,7, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,1, 3,4, 3,7, 4,2, 4,3, 4,7, 9,9 };
+prog_uchar letters_49[] PROGMEM = { 1,2, 1,7, 2,1, 2,2, 2,3, 2,4, 2,5, 2,6, 2,7, 3,7, 9,9 };
+prog_uchar letters_74[] PROGMEM = { 0,7, 1,1, 1,7, 2,1, 2,2, 2,3, 2,4, 2,5, 2,6, 3,1, 9,9 };
+prog_uchar letters_68[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,1, 1,7, 2,1, 2,7, 3,2, 3,3, 3,4, 3,5, 3,6, 9,9 };
+prog_uchar letters_90[] PROGMEM = { 0,1, 0,6, 0,7, 1,1, 1,5, 1,7, 2,1, 2,4, 2,7, 3,1, 3,3, 3,7, 4,1, 4,2, 4,7, 9,9 };
+prog_uchar letters_70[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,1, 1,4, 2,1, 2,4, 3,1, 3,4, 9,9 };
+prog_uchar letters_88[] PROGMEM = { 0,1, 0,2, 0,6, 0,7, 1,3, 1,5, 2,4, 3,3, 3,5, 4,1, 4,2, 4,6, 4,7, 9,9 };
+prog_uchar letters_75[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,4, 2,3, 2,5, 3,1, 3,2, 3,6, 3,7, 9,9 };
+prog_uchar letters_53[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,7, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,1, 3,4, 3,7, 4,1, 4,5, 4,6, 9,9 };
+prog_uchar letters_48[] PROGMEM = { 0,2, 0,3, 0,4, 0,5, 0,6, 1,1, 1,7, 2,1, 2,7, 3,1, 3,7, 4,2, 4,3, 4,4, 4,5, 4,6, 9,9 };
+prog_uchar letters_77[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,2, 2,3, 3,2, 4,1, 4,2, 4,3, 4,4, 4,5, 4,6, 4,7, 9,9 };
+prog_uchar letters_54[] PROGMEM = { 0,2, 0,3, 0,4, 0,5, 0,6, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,1, 3,4, 3,7, 4,2, 4,5, 4,6, 9,9 };
+prog_uchar letters_39[] PROGMEM = { 1,3, 2,1, 2,2, 9,9 };
+prog_uchar letters_85[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 1,7, 2,7, 3,1, 3,2, 3,3, 3,4, 3,5, 3,6, 9,9 };
+prog_uchar letters_57[] PROGMEM = { 0,2, 0,3, 0,7, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,1, 3,4, 3,7, 4,2, 4,3, 4,4, 4,5, 4,6, 9,9 };
+prog_uchar letters_78[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,2, 2,3, 3,4, 4,1, 4,2, 4,3, 4,4, 4,5, 4,6, 4,7, 9,9 };
+prog_uchar letters_84[] PROGMEM = { 0,1, 1,1, 1,2, 1,3, 1,4, 1,5, 1,6, 1,7, 2,1, 9,9 };
+prog_uchar letters_81[] PROGMEM = { 0,2, 0,3, 0,4, 0,5, 0,6, 1,1, 1,7, 2,1, 2,5, 2,7, 3,1, 3,6, 4,2, 4,3, 4,4, 4,5, 4,7, 9,9 };
+prog_uchar letters_51[] PROGMEM = { 0,2, 0,6, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,1, 3,4, 3,7, 4,2, 4,3, 4,5, 4,6, 9,9 };
+prog_uchar letters_86[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 1,6, 2,7, 3,6, 4,1, 4,2, 4,3, 4,4, 4,5, 9,9 };
+prog_uchar letters_72[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,4, 2,4, 3,1, 3,2, 3,3, 3,4, 3,5, 3,6, 3,7, 9,9 };
+prog_uchar letters_73[] PROGMEM = { 0,1, 0,7, 1,1, 1,2, 1,3, 1,4, 1,5, 1,6, 1,7, 2,1, 2,7, 9,9 };
+prog_uchar letters_44[] PROGMEM = { 1,7, 2,5, 2,6, 9,9 };
+prog_uchar letters_56[] PROGMEM = { 0,2, 0,3, 0,5, 0,6, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,1, 3,4, 3,7, 4,2, 4,3, 4,5, 4,6, 9,9 };
+prog_uchar letters_66[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,2, 3,3, 3,5, 3,6, 9,9 };
+prog_uchar letters_52[] PROGMEM = { 0,4, 0,5, 1,3, 1,5, 2,2, 2,5, 3,1, 3,2, 3,3, 3,4, 3,5, 3,6, 3,7, 4,5, 9,9 };
+prog_uchar letters_55[] PROGMEM = { 0,1, 1,1, 2,1, 2,5, 2,6, 2,7, 3,1, 3,3, 3,4, 4,1, 4,2, 9,9 };
+
+prog_uchar* font[] = { letters_33 /*!*/, 0, 0, 0, 0, 0, letters_39 /*'*/, 0, 0, 0, 0, letters_44 /*,*/, 0, 0, 0,
+letters_48 /*0*/, letters_49 /*1*/, letters_50 /*2*/, letters_51 /*3*/, letters_52 /*4*/, letters_53 /*5*/,
+letters_54 /*6*/, letters_55 /*7*/, letters_56 /*8*/, letters_57 /*9*/, 0, 0, 0, 0, 0, 0, 0, letters_65 /*A*/,
+letters_66 /*B*/, letters_67 /*C*/, letters_68 /*D*/, letters_69 /*E*/, letters_70 /*F*/, letters_71 /*G*/,
+letters_72 /*H*/, letters_73 /*I*/, letters_74 /*J*/, letters_75 /*K*/, letters_76 /*L*/, letters_77 /*M*/,
+letters_78 /*N*/, letters_79 /*O*/, letters_80 /*P*/, letters_81 /*Q*/, letters_82 /*R*/, letters_83 /*S*/,
+letters_84 /*T*/, letters_85 /*U*/, letters_86 /*V*/, letters_87 /*W*/, letters_88 /*X*/, letters_89 /*Y*/,
+letters_90 /*Z*/
+};
+
+
+uint16_t fontMin=33;
+uint16_t fontMax=90;
+
+#if 0
+
+// This section of the font works now, but doesn't appear to be correct.
+
+prog_uchar letters_117[] PROGMEM = { 0,4, 0,5, 0,6, 1,7, 2,7, 3,4, 3,5, 3,6, 3,7, 9,9 };
+prog_uchar letters_104[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,4, 2,4, 3,5, 3,6, 3,7, 9,9 };
+prog_uchar letters_109[] PROGMEM = { 0,4, 0,5, 0,6, 0,7, 1,4, 2,5, 2,6, 2,7, 3,4, 4,5, 4,6, 4,7, 9,9 };
+prog_uchar letters_114[] PROGMEM = { 0,4, 0,5, 0,6, 0,7, 1,4, 2,4, 9,9 };
+prog_uchar letters_108[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 9,9 };
+prog_uchar letters_116[] PROGMEM = { 0,2, 1,1, 1,2, 1,3, 1,4, 1,5, 1,6, 1,7, 2,2, 2,7, 3,7, 9,9 };
+prog_uchar letters_107[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,5, 2,4, 2,6, 3,3, 3,7, 9,9 };
+prog_uchar letters_118[] PROGMEM = { 0,4, 0,5, 1,6, 2,7, 3,6, 4,4, 4,5, 9,9 };
+prog_uchar letters_98[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,4, 1,7, 2,4, 2,7, 3,5, 3,6, 9,9 };
+prog_uchar letters_120[] PROGMEM = { 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,5, 2,4, 2,6, 3,3, 3,7, 9,9 };
+prog_uchar letters_119[] PROGMEM = { 0,4, 0,5, 1,6, 1,7, 2,4, 2,5, 3,6, 3,7, 4,4, 4,5, 9,9 };
+prog_uchar letters_111[] PROGMEM = { 0,5, 0,6, 1,4, 1,7, 2,4, 2,7, 3,5, 3,6, 9,9 };
+prog_uchar letters_105[] PROGMEM = { 0,1, 0,3, 0,4, 0,5, 0,6, 0,7, 9,9 };
+prog_uchar letters_110[] PROGMEM = { 0,4, 0,5, 0,6, 0,7, 1,4, 2,4, 3,5, 3,6, 3,7, 9,9 };
+prog_uchar letters_113[] PROGMEM = { 0,4, 0,5, 1,3, 1,6, 2,3, 2,6, 3,3, 3,4, 3,5, 3,6, 3,7, 3,8, 9,9 };
+prog_uchar letters_100[] PROGMEM = { 0,2, 0,3, 1,1, 1,4, 1,7, 2,1, 2,4, 2,7, 3,1, 3,2, 3,3, 3,4, 3,5, 3,6, 9,9 };
+prog_uchar letters_103[] PROGMEM = { 0,3, 0,4, 0,8, 1,2, 1,5, 1,8, 2,2, 2,5, 2,8, 3,2, 3,3, 3,4, 3,5, 3,6, 3,7, 9,9 };
+prog_uchar letters_112[] PROGMEM = { 0,3, 0,4, 0,5, 0,6, 0,7, 0,8, 1,3, 1,6, 2,3, 2,6, 3,4, 3,5, 9,9 };
+prog_uchar letters_101[] PROGMEM = { 0,4, 0,5, 0,6, 1,3, 1,5, 1,7, 2,3, 2,5, 2,7, 3,4, 3,5, 3,7, 9,9 };
+prog_uchar letters_102[] PROGMEM = { 0,5, 1,1, 1,2, 1,3, 1,4, 1,5, 1,6, 1,7, 2,1, 2,5, 3,1, 9,9 };
+prog_uchar letters_115[] PROGMEM = { 0,3, 0,4, 0,7, 1,3, 1,5, 1,7, 2,3, 2,5, 2,7, 3,3, 3,5, 3,6, 3,7, 9,9 };
+prog_uchar letters_99[] PROGMEM = { 0,5, 0,6, 1,4, 1,7, 2,4, 2,7, 3,4, 3,7, 9,9 };
+prog_uchar letters_106[] PROGMEM = { 0,8, 1,2, 1,4, 1,5, 1,6, 1,7, 1,8, 9,9 };
+prog_uchar letters_97[] PROGMEM = { 0,6, 0,7, 1,3, 1,5, 1,7, 2,3, 2,5, 2,7, 3,4, 3,5, 3,6, 3,7, 9,9 };
+
+prog_uchar* font2[] = { 0, 0, 0, 0, 0, 0, letters_97 /*a*/, letters_98 /*b*/, letters_99 /*c*/, letters_100 /*d*/, letters_101 /*e*/, letters_102 /*f*/, letters_103 /*g*/, letters_104 /*h*/, letters_105 /*i*/, letters_106 /*j*/, letters_107 /*k*/, letters_108 /*l*/, letters_109 /*m*/, letters_110 /*n*/, letters_111 /*o*/, letters_112 /*p*/, letters_113 /*q*/, letters_114 /*r*/, letters_115 /*s*/, letters_116 /*t*/, letters_117 /*u*/, letters_118 /*v*/, letters_119 /*w*/, letters_120 /*x*/ };
+*/
+
+#endif
+
+/* ----------------------------------------------------------------- */
+/** Draws a figure (0-9). You should call it with set=1,
+ * wait a little them call it again with set=0
+ * @param figure is the figure [0-9]
+ * @param x,y coordinates,
+ * @param set is 1 or 0 to draw or clear it
+ */
+uint8_t Font::Draw(unsigned char letter,int x,int y,int set) {
+ uint16_t maxx=0;
+
+ uint8_t charCol;
+ uint8_t charRow;
+
+ prog_uchar* character;
+ if (letter==' ') return 3+2;
+ if (letter<fontMin || letter>fontMax) {
+ return 0;
+ }
+
+// if (letter>90) {
+// character = font2[letter-90];
+// } else {
+ character = font[letter-fontMin];
+// }
+
+ int i=0;
+
+ charCol = pgm_read_byte_near(character);
+ charRow = pgm_read_byte_near(character + 1);
+
+ while (charRow!=9) {
+ if (charCol>maxx) maxx=charCol;
+ if (
+ charCol + x <14 &&
+ charCol + x >=0 &&
+ charRow + y <8 &&
+ charRow + y >=0
+ ) {
+ LedSign::Set(charCol + x, charRow+y, set);
+ }
+ i+=2;
+
+ charCol = pgm_read_byte_near(character + i);
+ charRow = pgm_read_byte_near(character + 1 + i);
+ }
+ return maxx+2;
+}
+
+
+/* ----------------------------------------------------------------- */
+/** Draw a figure in the other direction (rotated 90°)
+ * @param figure is the figure [0-9]
+ * @param x,y coordinates,
+ * @param set is 1 or 0 to draw or clear it
+*/
+uint8_t Font::Draw90(unsigned char letter,int x,int y,int set) {
+ uint16_t maxx=0;
+
+ uint8_t charCol;
+ uint8_t charRow;
+
+ prog_uchar* character;
+ if (letter==' ') return 3+2;
+ if (letter<fontMin || letter>fontMax) {
+ return 0;
+ }
+
+// if (letter>90) {
+// character = font2[letter-90];
+// } else {
+ character = font[letter-fontMin];
+// }
+
+ int i=0;
+
+ charCol = pgm_read_byte_near(character);
+ charRow = pgm_read_byte_near(character + 1);
+
+ while (charRow!=9) {
+ if (charCol>maxx) maxx=charCol;
+ if (
+ charRow + x <14 &&
+ charRow + x >=0 &&
+ charCol + y <8 &&
+ charCol + y >=0
+ ) {
+ LedSign::Set(7 - charRow + x, charCol + y, set);
+ }
+ i+=2;
+
+ charCol = pgm_read_byte_near(character + i);
+ charRow = pgm_read_byte_near(character + 1 + i);
+ }
+ return maxx+2;
+
+}
+
+
+
+
+
diff --git a/Matrix_9x14/libraries/Charliplexing/Font.h b/Matrix_9x14/libraries/Charliplexing/Font.h
new file mode 100644
index 0000000..84dd77a
--- /dev/null
+++ b/Matrix_9x14/libraries/Charliplexing/Font.h
@@ -0,0 +1,40 @@
+/*
+ Font drawing library
+
+ Copyright 2009/2010 Benjamin Sonntag <benjamin@sonntag.fr> http://benjamin.sonntag.fr/
+
+ History:
+ 2010-01-01 - V0.0 Initial code at Berlin after 26C3
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef Font_h
+#define Font_h
+
+#include <inttypes.h>
+
+namespace Font
+{
+
+extern uint8_t Draw(unsigned char letter,int x,int y,int set=1);
+
+extern uint8_t Draw90(unsigned char letter,int x,int y,int set=1);
+
+}
+
+#endif
+