23 static constexpr uint8_t REG_NOOP = 0x00;
24 static constexpr uint8_t REG_DIGIT0 = 0x01;
25 static constexpr uint8_t REG_DIGIT7 = 0x08;
26 static constexpr uint8_t REG_DECODE_MODE = 0x09;
27 static constexpr uint8_t REG_INTENSITY = 0x0A;
28 static constexpr uint8_t REG_SCAN_LIMIT = 0x0B;
29 static constexpr uint8_t REG_SHUTDOWN = 0x0C;
30 static constexpr uint8_t REG_DISPLAY_TEST = 0x0F;
35 std::perror(
"CS GPIO is not initialized");
38 for (
auto& chip : framebuffer_) {
42 thread_ = std::thread(&Max7219::RefreshThread,
this);
44 std::this_thread::sleep_for(std::chrono::milliseconds(100));
49 void RefreshThread() {
54 std::this_thread::sleep_for(std::chrono::milliseconds(5));
60 for (
size_t i = 0; i < N; ++i) {
61 WriteToChip(i, REG_SHUTDOWN, 0x00);
63 WriteToChip(i, REG_DISPLAY_TEST, 0x00);
64 WriteToChip(i, REG_DECODE_MODE, 0x00);
65 WriteToChip(i, REG_SCAN_LIMIT, 0x07);
66 WriteToChip(i, REG_INTENSITY, 0x03);
67 WriteToChip(i, REG_SHUTDOWN, 0x01);
74 void SetIntensity(uint8_t value) {
79 WriteAll(REG_INTENSITY, value);
85 for (
auto& chip : framebuffer_) {
94 void DrawPixel(
size_t chip_index, uint8_t row, uint8_t col,
bool on) {
95 if (chip_index >= N || row >= 8 || col >= 8) {
99 framebuffer_[chip_index][7 - row] |= (1 << col);
101 framebuffer_[chip_index][7 - row] &= ~(1 << col);
107 void DrawPixelMatrix2(uint8_t row, uint8_t col,
bool on) {
108 if (row >= 16 || col >= 32) {
113 static constexpr int CHIP_INDEX_MAP[] = {0, 2, 1, 3};
116 size_t chip_index = (row / 8) + (col / 8) * 2;
118 chip_index = CHIP_INDEX_MAP[chip_index % 4] + (chip_index - chip_index % 4);
119 uint8_t local_row = row % 8;
120 uint8_t local_col = col % 8;
122 DrawPixel(chip_index, local_row, local_col, on);
128 for (uint8_t row = 0; row < 8; ++row) {
129 std::array<uint8_t, N> regs;
130 std::array<uint8_t, N> data;
131 regs.fill(REG_DIGIT0 + row);
132 for (
size_t i = 0; i < N; ++i) {
133 data[i] = framebuffer_[i][row];
135 WriteCommandRaw(regs, data);
141 void WriteToChip(
size_t index, uint8_t addr, uint8_t data) {
142 std::array<uint8_t, N> regs;
143 std::array<uint8_t, N> data_all;
150 data_all[index] = data;
151 WriteCommandRaw(regs, data_all);
155 void TestEachChip() {
158 for (
int i = 0; i < 16; ++i) {
159 DrawPixelMatrix2(i, 0,
true);
160 std::this_thread::sleep_for(std::chrono::milliseconds(5));
164 for (
int i = 0; i < 16; ++i) {
165 DrawPixelMatrix2(15, i,
true);
166 std::this_thread::sleep_for(std::chrono::milliseconds(5));
170 for (
int i = 0; i < 16; ++i) {
171 DrawPixelMatrix2(i, 16,
true);
172 std::this_thread::sleep_for(std::chrono::milliseconds(5));
176 for (
int i = 16; i < 32; ++i) {
177 DrawPixelMatrix2(15, i,
true);
178 std::this_thread::sleep_for(std::chrono::milliseconds(5));
182 for (
int i = 15; i > 0; --i) {
183 DrawPixelMatrix2(i, 31,
true);
184 std::this_thread::sleep_for(std::chrono::milliseconds(5));
188 for (
int i = 31; i > 16; --i) {
189 DrawPixelMatrix2(0, i,
true);
190 std::this_thread::sleep_for(std::chrono::milliseconds(5));
194 for (
int i = 15; i > 0; --i) {
195 DrawPixelMatrix2(i, 15,
true);
196 std::this_thread::sleep_for(std::chrono::milliseconds(5));
200 for (
int i = 15; i > 0; --i) {
201 DrawPixelMatrix2(0, i,
true);
202 std::this_thread::sleep_for(std::chrono::milliseconds(5));
214 void SetLight(uint8_t light){
222 std::array<std::array<uint8_t, 8>, N> framebuffer_;
227 void WriteAll(uint8_t addr, uint8_t value) {
228 std::array<uint8_t, N> data;
230 WriteCommand(addr, data);
234 void WriteCommand(uint8_t addr,
const std::array<uint8_t, N>& data) {
235 std::array<uint8_t, N> regs;
237 WriteCommandRaw(regs, data);
241 void WriteCommandRaw(
const std::array<uint8_t, N>& regs,
242 const std::array<uint8_t, N>& data) {
243 std::array<uint8_t, N * 2> tx_buf{};
244 for (
size_t i = 0; i < N; ++i) {
245 const size_t HW_INDEX = N - 1 - i;
246 tx_buf[i * 2] = regs[HW_INDEX];
247 tx_buf[i * 2 + 1] = data[HW_INDEX];
250 spi_ioc_transfer transfer{};
251 transfer.tx_buf =
reinterpret_cast<uint64_t
>(tx_buf.data());
252 transfer.len = tx_buf.size();
253 transfer.speed_hz = 1000000;
254 transfer.bits_per_word = 8;
255 transfer.delay_usecs = 10;
261 if (ioctl(spi_.Fd(), SPI_IOC_MESSAGE(1), &transfer) < 0) {
263 std::perror(
"SPI transfer failed");