-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathCoreMax72xx.cpp
More file actions
219 lines (186 loc) · 5.03 KB
/
CoreMax72xx.cpp
File metadata and controls
219 lines (186 loc) · 5.03 KB
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/*
*
* CoreMax72xx this is the class for direct interaction with a controller MAX72xx
*
* @author Valeriy V Dmitriev aka valmat <ufabiz@gmail.com>, http://valmat.ru/
* @licenses MIT https://opensource.org/licenses/MIT
* @repo https://github.com/valmat/LedMatrix
*
*
* Software SPI and main core functionality implemented
* by Eberhard Fahle aka wayoda <e.fahle@wayoda.org>
* https://github.com/wayoda/LedControl
* http://wayoda.github.io/LedControl/
*
*/
#include "CoreMax72xx.h"
#include <SPI.h>
//the opcodes for the MAX7221 and MAX7219
namespace
{
constexpr uint8_t OP_NOOP = 0;
constexpr uint8_t OP_DIGIT0 = 1;
constexpr uint8_t OP_DIGIT1 = 2;
constexpr uint8_t OP_DIGIT2 = 3;
constexpr uint8_t OP_DIGIT3 = 4;
constexpr uint8_t OP_DIGIT4 = 5;
constexpr uint8_t OP_DIGIT5 = 6;
constexpr uint8_t OP_DIGIT6 = 7;
constexpr uint8_t OP_DIGIT7 = 8;
constexpr uint8_t OP_DECODEMODE = 9;
constexpr uint8_t OP_INTENSITY = 10;
constexpr uint8_t OP_SCANLIMIT = 11;
constexpr uint8_t OP_SHUTDOWN = 12;
constexpr uint8_t OP_DISPLAYTEST = 15;
}
// Software-SPI constructor
CoreMax72xx::CoreMax72xx(uint8_t data, uint8_t clk, uint8_t cs, uint8_t ind, uint16_t cascadeSize) :
_pins(data, clk, cs),
_index(ind),
_cascadeSize(cascadeSize)
{
_initialize();
}
// HardWare-SPI constructor
CoreMax72xx::CoreMax72xx(uint8_t cs, uint8_t ind, uint16_t cascadeSize, bool) :
_pins(cs),
_index(ind),
_cascadeSize(cascadeSize),
_isHardwareSPI(true)
{
// initialize SPI:
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
SPI.begin();
_initialize();
}
// Initialize the chip
void CoreMax72xx::_initialize()
{
_pins.latch();
_spiTransfer(OP_DISPLAYTEST, 0);
//scanlimit is set to max on startup
_setScanLimit(_limit - uint8_t(1));
//decode is done in source
_spiTransfer(OP_DECODEMODE, 0);
// Clear display on startup
// and fill the _status array by zeros
clear();
//we go into wakeup-mode on startup
wakeup();
}
// Set the shutdown (power saving) mode for the device
void CoreMax72xx::shutdown() const
{
_spiTransfer(OP_SHUTDOWN, 0);
}
// Set the wakeup mode for the device
void CoreMax72xx::wakeup() const
{
_spiTransfer(OP_SHUTDOWN, 1);
}
// Set the brightness of the display.
void CoreMax72xx::setIntensity(uint8_t intensity) const
{
_spiTransfer(OP_INTENSITY, intensity % _maxIntensity);
}
// Switch all LEDs on the display to off.
void CoreMax72xx::clear()
{
for(auto &row: _rows) {
_status[row] = 0;
_spiTransfer(row + 1, _status[row]);
}
}
// Switch all LEDs on the display to on.
void CoreMax72xx::fill()
{
for(auto &row: _rows) {
_status[row] = 0b11111111;
_spiTransfer(row + 1, _status[row]);
}
}
//
// Setters:
//
// Set the status of a single LED.
void CoreMax72xx::set(const Row &row, const Col &col, bool state)
{
_status[row][col] = state;
_spiTransfer(row + 1, _status[row]);
}
// Set all LEDs in a row to a new state
void CoreMax72xx::setRow(const Row &row, buint8_t value)
{
_status[row] = value;
_spiTransfer(row + 1, _status[row]);
}
// Set all LEDs in a column to a new state
void CoreMax72xx::setCol(const Col &col, buint8_t value)
{
for(auto &row: _rows) {
set(row, col, value[row]);
}
}
//
// Getters:
//
// Get state of LED point on matrix
bool CoreMax72xx::get(const Row &row, const Col &col) const
{
// Return binary value at the intersection of row and column
return _status[row][col];
}
// Get the values on row of LED-matrix
buint8_t CoreMax72xx::getRow(const Row &row) const
{
return _status[row];
}
// Get the values on colomn of LED-matrix
buint8_t CoreMax72xx::getCol(const Col &col) const
{
buint8_t rez = 0;
for(auto &row: _rows) {
rez[row] = get(row, col);
}
return rez;
}
//
// Private methods:
//
// SPI transaction
void CoreMax72xx::_spiTransfer(uint8_t opcode, uint8_t data) const
{
//Create an array with the data to shift out
const uint8_t offset = _index * 2;
const uint16_t maxbytes = _cascadeSize * 2;
// The array for shifting the data to the devices
uint8_t _spidata[maxbytes];
for(uint8_t i = 0; i < maxbytes; i++) {
_spidata[i] = 0;
}
//put our device data into the array
_spidata[offset+1] = opcode;
_spidata[offset] = data;
//enable the line
_pins.enable();
//Shift out the data
if(_isHardwareSPI) {
SPI.beginTransaction(SPISettings(100000000, MSBFIRST, SPI_MODE0));
for(uint8_t i = maxbytes; i > 0; i--) {
SPI.transfer(_spidata[i-1]);
}
SPI.endTransaction();
} else {
for(uint8_t i = maxbytes; i > 0; i--) {
// Software SPI transfer
_pins.transfer(_spidata[i-1]);
}
}
//latch the data onto the display
_pins.latch();
}
void CoreMax72xx::_setScanLimit(uint8_t limit) const
{
_spiTransfer(OP_SCANLIMIT, max(limit, uint8_t(_limit - 1) ));
}