Initial support for RGB led matrix, usually called hub75

This commit is contained in:
Daniel Esteban
2019-04-25 11:36:59 +02:00
committed by Ron Evans
parent 59db5fef76
commit 38e0d39f48
4 changed files with 520 additions and 0 deletions
+1
View File
@@ -62,6 +62,7 @@ func main() {
| [DS3231 real time clock](https://datasheets.maximintegrated.com/en/ds/DS3231.pdf) | I2C |
| ["Easystepper" stepper motor controller](https://en.wikipedia.org/wiki/Stepper_motor) | GPIO |
| [ESP8266/ESP32 AT Command set for WiFi/TCP/UDP](https://github.com/espressif/esp32-at) | UART |
| [HUB75 RGB led matrix](https://cdn-learn.adafruit.com/downloads/pdf/32x16-32x32-rgb-led-matrix.pdf) | SPI |
| [LIS3DH accelerometer](https://www.st.com/resource/en/datasheet/lis3dh.pdf) | I2C |
| [MAG3110 magnetometer](https://www.nxp.com/docs/en/data-sheet/MAG3110.pdf) | I2C |
| [MMA8653 accelerometer](https://www.nxp.com/docs/en/data-sheet/MMA8653FC.pdf) | I2C |
+142
View File
@@ -0,0 +1,142 @@
package gopherimg
import "image/color"
var ImageArray = []uint32{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6015176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 0,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 0,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215,
16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176,
16777215, 16777215, 0, 0, 0, 0, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 6015176, 6015176, 6015176,
6015176, 16777215, 16777215, 16777215, 0, 0, 0, 0, 0, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 6015176,
6015176, 6015176, 16777215, 16777215, 16777215, 16777215, 0, 0, 0, 0, 0, 16777215, 16777215, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0,
0, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 16777215, 0, 0, 0, 0, 0, 16777215, 16777215,
16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 16777215, 16777215, 0,
0, 0, 16777215, 16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215,
16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 16777215, 16777215,
16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 6015176, 6015176, 6015176, 6015176,
6015176, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215,
16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215,
16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215,
16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 8145949, 8145949, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 6015176, 6015176, 6015176,
8145949, 8145949, 8145949, 8145949, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215,
16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 8145949, 8145949, 8145949, 8145949, 8145949, 16777215,
16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 8145949, 8145949, 8145949, 8145949, 8145949, 15267831, 16645886, 16777215, 16777215, 6015176, 6015176,
6015176, 6015176, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 8145949, 8145949, 8145949, 8145949, 16777215,
16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 0, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0,
8145949, 8145949, 8145949, 8145949, 6868429, 7786961, 7327695, 6015176, 6015176, 6015176, 6015176, 6015176, 0,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 8145949, 8145949, 8145949, 8145949, 16777215, 16777215,
16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 0, 0,
8145949, 8145949, 8145949, 8145949, 15530489, 16121084, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 0,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 0, 0, 0, 0, 16777215,
6015176, 6015176, 6015176, 8145949, 8145949, 8145949, 8145949, 8145949, 16777215, 16777215, 16777215, 6015176,
6015176, 6015176, 6015176, 6015176, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215,
16777215, 0, 0, 0, 0, 0, 16777215, 16777215, 6015176, 6015176, 6015176, 8145949, 8145949, 8145949, 8145949,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 16777215, 16777215, 16777215, 0, 0, 0, 0, 0, 16777215, 16777215, 6015176, 6015176, 6015176,
6015176, 8145949, 8145949, 8145949, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 0, 0, 0, 0, 0, 16777215,
16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215,
16777215, 16777215, 16777215, 0, 0, 16777215, 16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 6015176, 6015176,
6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215,
16777215, 16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215,
16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 0, 0, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215,
16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 6015176, 6015176, 6015176, 6015176,
6015176, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 16777215,
16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 6015176, 6015176,
6015176, 6015176, 6015176, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 16777215, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 16777215, 16777215, 16777215,
16777215, 16777215, 16777215, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0,
0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0,
0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 0,
0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0, 6015176,
6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176,
6015176, 6015176, 6015176, 0, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 6015176, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6015176, 6015176, 6015176, 6015176,
6015176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}
func Int2Color(intColor uint32) (col color.RGBA) {
blue := uint8(intColor & 0xFF)
green := uint8((intColor >> 8) & 0xFF)
red := uint8((intColor >> 16) & 0xFF)
return color.RGBA{R: red, G: green, B: blue}
}
+103
View File
@@ -0,0 +1,103 @@
package main
import (
"machine"
"image/color"
"time"
"github.com/tinygo-org/drivers/examples/hub75/gopherimg"
"github.com/tinygo-org/drivers/hub75"
)
var display hub75.Device
func main() {
machine.SPI0.Configure(machine.SPIConfig{
Frequency: 8000000,
Mode: 0},
)
display = hub75.New(machine.SPI0, 11, 12, 6, 10, 18, 20)
display.Configure(hub75.Config{
Width: 64,
Height: 32,
RowPattern: 16,
ColorDepth: 6,
})
colors := []color.RGBA{
{255, 0, 0, 255},
{255, 255, 0, 255},
{0, 255, 0, 255},
{0, 255, 255, 255},
{0, 0, 255, 255},
{255, 0, 255, 255},
{255, 255, 255, 255},
}
display.ClearDisplay()
display.SetBrightness(100)
step := 0
then := time.Now()
size := int16(8)
x := int16(0)
y := int16(0)
dx := int16(1)
dy := int16(1)
c := 0
for {
if time.Since(then).Nanoseconds() > 800000000 {
then = time.Now()
step++
if step < 23 {
showRect(size, x*size, y*size, colors[c])
c = (c + 1) % 7
x += dx
y += dy
if x >= (64 / size) {
dx = -1
x += 2 * dx
}
if y >= (32 / size) {
dy = -1
y += 2 * dy
}
if x < 0 {
dx = 1
x += 2 * dx
}
if y < 0 {
dy = 1
y += 2 * dy
}
} else if step == 23 {
showGopher()
} else if step == 30 {
display.ClearDisplay()
step = 0
x = 0
y = 0
}
}
display.Display()
}
}
func showGopher() {
for i := int16(0); i < 64; i++ {
for j := int16(0); j < 32; j++ {
display.SetPixel(i, j, gopherimg.Int2Color(gopherimg.ImageArray[32*i+j]))
}
}
}
func showRect(size int16, x int16, y int16, c color.RGBA) {
for i := x; i < x+size; i++ {
for j := y; j < y+size; j++ {
display.SetPixel(i, j, c)
}
}
}
+274
View File
@@ -0,0 +1,274 @@
// Package hub75 implements a driver for the HUB75 LED matrix.
//
// Guide: https://cdn-learn.adafruit.com/downloads/pdf/32x16-32x32-rgb-led-matrix.pdf
// This driver was inspired by https://github.com/2dom/PxMatrix
package hub75
import (
"image/color"
"machine"
"time"
)
type Config struct {
Width int16
Height int16
ColorDepth uint16
RowPattern int16
Brightness uint8
FastUpdate bool
}
type Device struct {
bus machine.SPI
a machine.GPIO
b machine.GPIO
c machine.GPIO
d machine.GPIO
oe machine.GPIO
lat machine.GPIO
width int16
height int16
brightness uint8
fastUpdate bool
colorDepth uint16
colorStep uint16
colorHalfStep uint16
colorThirdStep uint16
colorTwoThirdStep uint16
rowPattern int16
rowsPerBuffer int16
panelWidth int16
panelWidthBytes int16
pixelCounter uint32
lineCounter uint32
patternColorBytes uint8
rowSetsPerBuffer uint8
sendBufferSize uint16
rowOffset []uint32
buffer [][]uint8 // [ColorDepth][(width * height * 3(rgb)) / 8]uint8
displayColor uint16
}
// New returns a new HUB75 driver. Pass in a fully configured SPI bus.
func New(b machine.SPI, latPin uint8, oePin uint8, aPin uint8, bPin uint8, cPin uint8, dPin uint8) Device {
pinA := machine.GPIO{aPin}
pinA.Configure(machine.GPIOConfig{Mode: machine.GPIO_OUTPUT})
pinB := machine.GPIO{bPin}
pinB.Configure(machine.GPIOConfig{Mode: machine.GPIO_OUTPUT})
pinC := machine.GPIO{cPin}
pinC.Configure(machine.GPIOConfig{Mode: machine.GPIO_OUTPUT})
pinD := machine.GPIO{dPin}
pinD.Configure(machine.GPIOConfig{Mode: machine.GPIO_OUTPUT})
pinOE := machine.GPIO{oePin}
pinOE.Configure(machine.GPIOConfig{Mode: machine.GPIO_OUTPUT})
pinLAT := machine.GPIO{latPin}
pinLAT.Configure(machine.GPIOConfig{Mode: machine.GPIO_OUTPUT})
return Device{
bus: b,
a: pinA,
b: pinB,
c: pinC,
d: pinD,
oe: pinOE,
lat: pinLAT,
}
}
// Configure sets up the device.
func (d *Device) Configure(cfg Config) {
if cfg.Width != 0 {
d.width = cfg.Width
} else {
d.width = 64
}
if cfg.Height != 0 {
d.height = cfg.Height
} else {
d.height = 32
}
if cfg.ColorDepth != 0 {
d.colorDepth = cfg.ColorDepth
} else {
d.colorDepth = 8
}
if cfg.RowPattern != 0 {
d.rowPattern = cfg.RowPattern
} else {
d.rowPattern = 16
}
if cfg.Brightness != 0 {
d.brightness = cfg.Brightness
} else {
d.brightness = 255
}
d.fastUpdate = cfg.FastUpdate
d.rowsPerBuffer = d.height / 2
d.panelWidth = 1
d.panelWidthBytes = (d.width / d.panelWidth) / 8
d.rowOffset = make([]uint32, d.height)
d.patternColorBytes = uint8((d.height / d.rowPattern) * (d.width / 8))
d.rowSetsPerBuffer = uint8(d.rowsPerBuffer / d.rowPattern)
d.sendBufferSize = uint16(d.patternColorBytes) * 3
d.colorStep = 256 / d.colorDepth
d.colorHalfStep = d.colorStep / 2
d.colorThirdStep = d.colorStep / 3
d.colorTwoThirdStep = 2 * d.colorThirdStep
d.buffer = make([][]uint8, d.colorDepth)
for i := range d.buffer {
d.buffer[i] = make([]uint8, (d.width*d.height*3)/8)
}
d.colorHalfStep = d.colorStep / 2
d.colorThirdStep = d.colorStep / 3
d.colorTwoThirdStep = 2 * d.colorThirdStep
d.a.Low()
d.b.Low()
d.c.Low()
d.d.Low()
d.oe.High()
var i uint32
for i = 0; i < uint32(d.height); i++ {
d.rowOffset[i] = (i%uint32(d.rowPattern))*uint32(d.sendBufferSize) + uint32(d.sendBufferSize) - 1
}
}
// SetPixel modifies the internal buffer in a single pixel.
func (d *Device) SetPixel(x int16, y int16, c color.RGBA) {
d.fillMatrixBuffer(x, y, c.R, c.G, c.B)
}
// fillMatrixBuffer modifies a pixel in the internal buffer given position and RGB values
func (d *Device) fillMatrixBuffer(x int16, y int16, r uint8, g uint8, b uint8) {
if x < 0 || x >= d.width || y < 0 || y >= d.height {
return
}
x = d.width - 1 - x
var offsetR uint32
var offsetG uint32
var offsetB uint32
vertIndexInBuffer := uint8((int32(y) % int32(d.rowsPerBuffer)) / int32(d.rowPattern))
whichBuffer := uint8(y / d.rowsPerBuffer)
xByte := x / 8
whichPanel := uint8(xByte / d.panelWidthBytes)
inRowByteOffset := uint8(xByte % d.panelWidthBytes)
offsetR = d.rowOffset[y] - uint32(inRowByteOffset) - uint32(d.panelWidthBytes)*
(uint32(d.rowSetsPerBuffer)*(uint32(d.panelWidth)*uint32(whichBuffer)+uint32(whichPanel))+uint32(vertIndexInBuffer))
offsetG = offsetR - uint32(d.patternColorBytes)
offsetB = offsetG - uint32(d.patternColorBytes)
bitSelect := uint8(x % 8)
for c := uint16(0); c < d.colorDepth; c++ {
colorTresh := uint8(c*d.colorStep + d.colorHalfStep)
if r > colorTresh {
d.buffer[c][offsetR] |= 1 << bitSelect
} else {
d.buffer[c][offsetR] = d.buffer[c][offsetR] &^ 1 << bitSelect
}
if g > colorTresh {
d.buffer[(c+d.colorThirdStep)%d.colorDepth][offsetG] |= 1 << bitSelect
} else {
d.buffer[(c+d.colorThirdStep)%d.colorDepth][offsetG] &^= 1 << bitSelect
}
if b > colorTresh {
d.buffer[(c+d.colorTwoThirdStep)%d.colorDepth][offsetB] |= 1 << bitSelect
} else {
d.buffer[(c+d.colorTwoThirdStep)%d.colorDepth][offsetB] &^= 1 << bitSelect
}
}
}
// Display sends the buffer (if any) to the screen.
func (d *Device) Display() error {
rp := uint16(d.rowPattern)
for i := uint16(0); i < rp; i++ {
// FAST UPDATES (only if brightness = 255)
if d.fastUpdate && d.brightness == 255 {
d.setMux((i + rp - 1) % rp)
d.lat.High()
d.oe.Low()
d.lat.Low()
time.Sleep(1 * time.Microsecond)
d.bus.Tx(d.buffer[d.displayColor][i*d.sendBufferSize:(i+1)*d.sendBufferSize], nil)
time.Sleep(10 * time.Microsecond)
d.oe.High()
} else { // NO FAST UPDATES
d.setMux(i)
d.bus.Tx(d.buffer[d.displayColor][i*d.sendBufferSize:(i+1)*d.sendBufferSize], nil)
d.latch((255 * uint16(d.brightness)) / 255)
}
}
d.displayColor++
if d.displayColor >= d.colorDepth {
d.displayColor = 0
}
return nil
}
func (d *Device) latch(showTime uint16) {
d.lat.High()
d.lat.Low()
d.oe.Low()
time.Sleep(time.Duration(showTime) * time.Microsecond)
d.oe.High()
}
func (d *Device) setMux(value uint16) {
if (value & 0x01) == 0x01 {
d.a.High()
} else {
d.a.Low()
}
if (value & 0x02) == 0x02 {
d.b.High()
} else {
d.b.Low()
}
if (value & 0x04) == 0x04 {
d.c.High()
} else {
d.c.Low()
}
if (value & 0x08) == 0x08 {
d.d.High()
} else {
d.d.Low()
}
}
// FlushDisplay flushes the display
func (d *Device) FlushDisplay() {
var i uint16
for i = 0; i < d.sendBufferSize; i++ {
d.bus.Tx([]byte{0x00}, nil)
}
}
// SetBrightness changes the brightness of the display
func (d *Device) SetBrightness(brightness uint8) {
d.brightness = brightness
}
// ClearDisplay erases the internal buffer
func (d *Device) ClearDisplay() {
bufferSize := (d.width * d.height * 3) / 8
for c := uint16(0); c < d.colorDepth; c++ {
for j := int16(0); j < bufferSize; j++ {
d.buffer[c][j] = 0
}
}
}
// Size returns the current size of the display.
func (d *Device) Size() (w, h int16) {
return d.width, d.height
}