-
Notifications
You must be signed in to change notification settings - Fork 35
/
TM1640Anode.cpp
158 lines (138 loc) · 5.62 KB
/
TM1640Anode.cpp
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
TM1640Anode.cpp - Library implementation for TM1640 with Common Anode up to 8 digits of 16 segments.
5241BS - 2 digits of 14 segments plus dot:
|---A---|
|\ | /|
F H J K B
| \|/ |
|-G1-G2-|
| /|\ |
E N M L C
|/ | \|
|---D---| DP
1
Pinout (bottom side up)
| | | | | | | | | Index Segment Pin Index Segment Pin
| | | | | | | | | [0] A 12 [ 7] DP 8
1 2 3 4 5 6 7 8 9 [1] B 10 [ 9] H 17
+-|-|-|-|-|-|-|-|-|-+ [2] C 9 [10] J 15
| o o o o o o o o o | [3] D 7 [11] K 14
| | [4] E 1 [12] L 5
| 5241BS (Com.An.) | [5] F 18 [13] M 4
| | [6] G1 13 [14] N 2
| o o o o o o o o o | [8] G2 6
+-|-|-|-|-|-|-|-|-|-+
1 1 1 1 1 1 1 1 1 Pin 3 is not connected
8 7 6 5 4 3 2 1 0 Anode digit 1 is on pin 16
| | | | | | | | | Anode digit 2 is on pin 11
Made by Maxint R&D, partly based on TM1638Anode class. See https://github.com/maxint-rd/
*/
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "TM1640Anode.h"
TM1640Anode::TM1640Anode(byte dataPin, byte clockPin, byte numDigits, bool activateDisplay, byte intensity)
: TM1640(dataPin, clockPin, numDigits, activateDisplay, intensity)
{
_maxSegments=TM1640Anode_MAX_SEG; // On the 5241BS LED display modules the 15 segments are connected to the GRD1-GRD16 lines of the TM1640.
// The display has the two common anode digits connected to the SEG lines, resulting in max. 8 digits.
_maxDisplays=TM1640Anode_MAX_POS;
clearDisplay();
setupDisplay(activateDisplay, intensity);
}
void TM1640Anode::sendAsciiChar(byte pos, char c, bool fDot)
{ // Method to send an Ascii character to the display.
// This method is also called by TM16xxDisplay.print() to display characters.
// The base class uses the default 7-segment font to find the LED pattern.
// Derived classes for multi-segment displays or alternate layout displays can override this method.
uint16_t uSegments= pgm_read_word(TM16XX_FONT_15SEG+(c - 32));
setSegments16(uSegments | (fDot ? 0b10000000 : 0), pos);
}
void TM1640Anode::setSegments(byte segments, byte position)
{ // Set regular 7-segment segments on the 15-segment display. This allows for using the regular 7-segment font.
// On the 5241BS 15-segment display, segment G is split into G1 and G2. Assume these to be segments 6 and 8, having DP on segment 7 (index 0)
uint16_t segments16=segments;
if(segments16&bit(6))
segments16|=bit(8); // duplicate G1 to G2
this->setSegments16((uint16_t)segments16, position);
}
void TM1640Anode::setSegmentMap(const byte aMap[])
{ // Set a segment map to be used in subsequent setting of segments
// Example map for easy breadboard wiring of TM1650 to 5241BS (TM1640 pin 1 right-top, 5241BS pin 1 left bottom)
// byte aSegmentMap[]={12,11, 8, 6, 1, 9,13, 7, 5,10,15,14, 4, 3, 2, 0}; // mapping for TM1640 left of 5241BS with streight wiring
pSegmentMap=aMap;
}
uint16_t TM1640Anode::mapSegments16(uint16_t segments)
{ // Map the segments to another location if that's requested.
// The segment map is an array of _maxSegments long of which each element specfies the remapped position.
// Usually segment A is mapped to pin GRID1 of the TM1640. Using segmentmapping this can become any other pin.
if(pSegmentMap)
{
/*
Serial.print(F("SegmentMapping: "));
Serial.print(segments, HEX);
Serial.print("->");
*/
uint16_t nSegmentsMapped=0;
for(byte n=0; n<_maxSegments; n++)
{
//nSegmentsMapped|=(bit(pSegmentMap[n])&(segments&bit(n)));
nSegmentsMapped|=((segments&bit(n))?bit(pSegmentMap[n]):0);
}
segments=nSegmentsMapped;
// Serial.println(segments, HEX);
}
return(segments);
}
void TM1640Anode::setSegments16(uint16_t segments, byte position)
{ // Set 16 leds on common grd as specified
// TM1640 uses 8 SEGs for 16 GRIDs one byte address per GRID
// For the 15-segment displays in common anode configuration one SEG per display position is used.
// When used as a 8-segment display, the G segment is translated to G1/G2.
// Note: For 15-segment characters the sendAsciiChar function is redefined.
// Map segments if specified for alternative segment wiring.
segments=mapSegments16(segments);
//if(position<_maxDisplays)
if(position<TM1640Anode_MAX_POS)
{
//update our memory bitmap
this->bitmap[position]=segments;
// Transpose the segments/positions to counter Common Anode connections and send the whole bitmap
for (byte nSeg = 0; nSeg < _maxSegments; nSeg++)
{
byte nVal=0;
for(byte nPos=0; nPos < TM1640Anode_MAX_POS; nPos++)
{
// Assume 1st digit to be connected to SEG1, 2nd digit connected to SEG2 etc
nVal |= (((this->bitmap[nPos] >> nSeg) & 1) << (nPos));
}
sendData(nSeg, nVal);
}
}
}
void TM1640Anode::clearDisplay()
{
/*
Serial.print(F("pre-clr:"));
for(byte nPos=0; nPos<TM1640Anode_MAX_POS; nPos++)
{
Serial.print(nPos);
Serial.print(":");
Serial.print(this->bitmap[nPos], HEX);
Serial.print(" ");
}
Serial.println(". ");
*/
memset(this->bitmap, 0, TM1640Anode_MAX_POS*sizeof(uint16_t));
for(byte nPos=0; nPos<TM1640Anode_MAX_POS; nPos++)
{
// all OFF
sendData(nPos << 1, 0);
sendData((nPos << 1) | 1, 0);
// all ON
//sendData(nPos << 1, 0b11111111);
//sendData((nPos << 1) | 1, 0b00000011);
}
}