2 * Copyright 2017 Jonathan McDowell <noodles@earth.li>
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "espmissingincludes.h"
30 /* This is a small 8x4 font */
31 #include "font-atari.h"
33 /* The number of 8x8 displays we have daisy chained together */
34 #define MAX7219_WIDTH 4
56 uint8_t buf[8 * MAX7219_WIDTH];
60 static struct max7219_ctx ctx;
62 static void ICACHE_FLASH_ATTR max7219_write_reg(uint8_t reg, uint8_t data)
67 gpio_output_set(0, ctx.cs, ctx.cs, 0);
68 for (block = 0; block < ctx.width; block++) {
72 /* Set CS high to latch data into MAX7219 */
73 gpio_output_set(ctx.cs, 0, ctx.cs, 0);
77 void ICACHE_FLASH_ATTR max7219_set_pixel(unsigned int x, unsigned int y,
86 ctx.buf[y + block] |= 1 << x;
88 ctx.buf[y + block] &= ~(1 << x);
92 void ICACHE_FLASH_ATTR max7219_blit(unsigned int x, unsigned int y,
93 const uint8_t *data, unsigned int width, unsigned int height)
95 unsigned int block = x & 0x38;
96 unsigned int left_shift = x & 7;
97 bool twoblocks = ((left_shift + width) > 8) &&
98 ((x + width) < (ctx.width * 8));
99 unsigned int right_shift;
102 if (block >= (ctx.width << 3)) {
103 /* We're off the right hand side; do nothing */
108 if (block > (ctx.width << 3)) {
109 /* 2nd block is off the edge; ignore it */
112 right_shift = (8 - left_shift);
116 for (row = 0; row < height; row++)
121 ctx.buf[y + row + block] |= ((data[row] << left_shift) & 0xFF);
123 ctx.buf[y + row + (block + 8)] |=
124 (data[row] >> right_shift);
129 void ICACHE_FLASH_ATTR max7219_clear(void)
133 for (i = 0; i < ctx.width * 8;i++)
137 void ICACHE_FLASH_ATTR max7219_show(void)
142 for (y = 0; y < 8; y++) {
144 gpio_output_set(0, ctx.cs, ctx.cs, 0);
145 for (block = ctx.width - 1; block >= 0; block--) {
146 data[0] = 8 - y; /* Row reg */
147 data[1] = ctx.buf[y + (block << 3)]; /* Pixel val */
150 /* Set CS high to latch data into MAX7219 */
151 gpio_output_set(ctx.cs, 0, ctx.cs, 0);
156 void ICACHE_FLASH_ATTR max7219_print(const char *str)
161 while ((cur = (unsigned char) *str++) && x < (ctx.width * 8)) {
162 if ((cur > 31) && (cur < 127)) {
164 max7219_blit(x, 0, font[cur].bitmap,
166 x += font[cur].width + 1;
171 void ICACHE_FLASH_ATTR max7219_init(unsigned int cs)
173 ctx.width = MAX7219_WIDTH;
176 max7219_write_reg(SHUTDOWN, 0);
177 max7219_write_reg(DISPLAYTEST, 0);
178 max7219_write_reg(SCANLIMIT, 7);
179 max7219_write_reg(DECODEMODE, 0);
180 max7219_write_reg(INTENSITY, 0);
181 max7219_write_reg(SHUTDOWN, 1);