-
Notifications
You must be signed in to change notification settings - Fork 10
/
charlieplex.h
83 lines (70 loc) · 2.03 KB
/
charlieplex.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#ifndef CHARLIEPLEX_H
#define CHARLIEPLEX_H
#include <Arduino.h>
#define CHARLIE_PORT PORTB
#define CHARLIE_DDR DDRB
template <int SIZE>
class Charlieplex {
unsigned char _mask;
unsigned char _port[SIZE * (SIZE-1)];
unsigned char _ddr[SIZE * (SIZE-1)];
unsigned char _pins[SIZE * (SIZE-1)];
void _define_pin(int pin, int maskHigh, int maskLow) {
_ddr[pin] = maskLow | maskHigh;
_port[pin] = maskHigh;
}
public:
Charlieplex(int masks[SIZE])
: _mask(0) {
for ( int i = 0; i < SIZE; i++ ) {
int m = masks[i];
_mask |= m;
}
/*
Define order of LEDs. They proceed in pairs using the same pair of pins. With the first
LED in the pair being that one that would be lit be bring the first pin high and the second
pin low
*/
int pin = 0;
for ( int i = 0 ; i < SIZE; i++ ) {
for ( int j = i+1; j < SIZE; j++ ) {
int maski = masks[i];
int maskj = masks[j];
_define_pin(pin, maski, maskj);
pin++;
_define_pin(pin, maskj, maski);
pin++;
}
}
}
int size() {
return SIZE * (SIZE-1);
}
void clear() {
for ( int i = 0; i < SIZE * (SIZE-1); i++ ) {
_pins[i] = 0;
}
}
void pin(int pinNum, int pinVal) {
_pins[pinNum] = pinVal;
}
void display() {
int num = size();
for ( int pin = 0; pin < num; pin++ ) {
if ( _pins[pin] ) {
// first turn off everything before changing
// pin direction - on ATtiny when not not doing this
// was getting extra LEDs lit, when two different LEDs
// were lit
CHARLIE_PORT = (CHARLIE_PORT & ~_mask);
CHARLIE_DDR = (CHARLIE_DDR & ~_mask) | _ddr[pin];
CHARLIE_PORT = CHARLIE_PORT | _port[pin];
}
delayMicroseconds(1);
}
/** turn off all LEDs **/
CHARLIE_DDR = CHARLIE_DDR & ~_mask;
CHARLIE_PORT = CHARLIE_PORT & ~_mask;
}
};
#endif // CHARLIEPLEX_H