summaryrefslogtreecommitdiffstats
path: root/LoLShield/Charliplexing.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'LoLShield/Charliplexing.cpp')
-rw-r--r--LoLShield/Charliplexing.cpp185
1 files changed, 185 insertions, 0 deletions
diff --git a/LoLShield/Charliplexing.cpp b/LoLShield/Charliplexing.cpp
new file mode 100644
index 0000000..5211a84
--- /dev/null
+++ b/LoLShield/Charliplexing.cpp
@@ -0,0 +1,185 @@
+ /*
+ Charliplexing.h - Using timer2 with 1ms resolution
+
+ Alex Wenger <a.wenger@gmx.de> http://arduinobuch.wordpress.com/
+
+ Timer init code from MsTimer2 - Javier Valencia <javiervalencia80@gmail.com>
+
+ History:
+ 30/Dez/09 - V0.0 wrote the first version at 26C3/Berlin
+
+ 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
+*/
+
+#include "WProgram.h"
+#include <inttypes.h>
+#include <avr/interrupt.h>
+#include "Charliplexing.h"
+
+
+volatile unsigned int LedSign::tcnt2;
+
+// Table for the LED multiplexing cycles, containing 12 cycles made out of two bytes
+uint8_t leds[24];
+
+
+// Table for LED Position in leds[] ram table
+const uint8_t ledMap[252] = {
+ 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 / init interrupt
+void LedSign::Init(void)
+{
+ 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<<CS22);
+ TCCR2B &= ~((1<<CS21) | (1<<CS20));
+ prescaler = 64.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) | (1<<CS20));
+ TCCR2B &= ~(1<<CS21);
+ prescaler = 128.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.001 / prescaler);
+
+#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1280__)
+ TCNT2 = tcnt2;
+ TIMSK2 |= (1<<TOIE2);
+#elif defined (__AVR_ATmega128__)
+ TCNT2 = tcnt2;
+ TIMSK |= (1<<TOIE2);
+#elif defined (__AVR_ATmega8__)
+ TCNT2 = tcnt2;
+ TIMSK |= (1<<TOIE2);
+#endif
+}
+
+// Function to switch on and off the leds. All the position
+// 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_low = ledMap[x*2+y*28+1];
+ uint8_t pin_high = ledMap[x*2+y*28+0];
+ // pin_low ist directly the adress 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 adress has to be increased by one
+ if (c == 1) {
+ leds[(pin_low-2)*2 + (pin_high / 8)] |= _BV(pin_high & 0x07); // ON
+ }
+ else {
+ leds[(pin_low-2)*2 + (pin_high / 8)] &= ~_BV(pin_high & 0x07); // OFF
+ }
+}
+
+
+ISR(TIMER2_OVF_vect) {
+#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1280__)
+ TCNT2 = LedSign::tcnt2;
+#elif defined (__AVR_ATmega128__)
+ TCNT2 = LedSign::tcnt2;
+#elif defined (__AVR_ATmega8__)
+ TCNT2 = LedSign::tcnt2;
+#endif
+
+ // 12 Cycles of Matrix
+ static uint8_t i;
+
+ i++;
+ if (i > 12) i = 0;
+
+ if (i < 6) {
+ DDRD = _BV(i+2) | leds[i*2];
+ PORTD = leds[i*2];
+
+ DDRB = leds[i*2+1];
+ PORTB = leds[i*2+1];
+ } else {
+ DDRD = leds[i*2];
+ PORTD = leds[i*2];
+
+ DDRB = _BV(i-6) | leds[i*2+1];
+ PORTB = leds[i*2+1];
+ }
+ /*
+ PORTB = 0xff;
+ PORTD = i;
+ DDRB = 0xff;
+ DDRD = 0xff;
+ */
+}
+