mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-11 18:33:43 +00:00
microbitmatrix: harmonize v1 and v2 implementation
This commit is contained in:
committed by
Ron Evans
parent
a106fd48ce
commit
8a39bb7aae
@@ -8,9 +8,12 @@ package microbitmatrix // import "tinygo.org/x/drivers/microbitmatrix"
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"machine"
|
"machine"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 4 rotation orientations (0, 90, 180, 270), CW (clock wise)
|
||||||
|
// 5 rows
|
||||||
|
// 5 cols
|
||||||
|
// target coordinates in machine rows (y) and cols (x)
|
||||||
var matrixRotations = [4][5][5][2]uint8{
|
var matrixRotations = [4][5][5][2]uint8{
|
||||||
{ // 0
|
{ // 0
|
||||||
{{0, 0}, {1, 3}, {0, 1}, {1, 4}, {0, 2}},
|
{{0, 0}, {1, 3}, {0, 1}, {1, 4}, {0, 2}},
|
||||||
@@ -19,7 +22,7 @@ var matrixRotations = [4][5][5][2]uint8{
|
|||||||
{{0, 7}, {0, 6}, {0, 5}, {0, 4}, {0, 3}},
|
{{0, 7}, {0, 6}, {0, 5}, {0, 4}, {0, 3}},
|
||||||
{{2, 2}, {1, 6}, {2, 0}, {1, 5}, {2, 1}},
|
{{2, 2}, {1, 6}, {2, 0}, {1, 5}, {2, 1}},
|
||||||
},
|
},
|
||||||
{ // 90 CCW
|
{ // 90 CW
|
||||||
{{0, 2}, {2, 7}, {1, 0}, {0, 3}, {2, 1}},
|
{{0, 2}, {2, 7}, {1, 0}, {0, 3}, {2, 1}},
|
||||||
{{1, 4}, {2, 6}, {2, 8}, {0, 4}, {1, 5}},
|
{{1, 4}, {2, 6}, {2, 8}, {0, 4}, {1, 5}},
|
||||||
{{0, 1}, {2, 5}, {1, 2}, {0, 5}, {2, 0}},
|
{{0, 1}, {2, 5}, {1, 2}, {0, 5}, {2, 0}},
|
||||||
@@ -42,65 +45,33 @@ var matrixRotations = [4][5][5][2]uint8{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
ledRows = 3
|
||||||
|
ledCols = 9
|
||||||
|
)
|
||||||
|
|
||||||
type Device struct {
|
type Device struct {
|
||||||
pin [12]machine.Pin
|
pin [ledCols + ledRows]machine.Pin
|
||||||
buffer [3][9]bool
|
buffer [ledRows][ledCols]bool
|
||||||
rotation uint8
|
rotation uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure sets up the device.
|
func (d *Device) assignPins() {
|
||||||
func (d *Device) Configure(cfg Config) {
|
d.pin[0] = machine.LED_COL_1
|
||||||
d.SetRotation(cfg.Rotation)
|
d.pin[1] = machine.LED_COL_2
|
||||||
|
d.pin[2] = machine.LED_COL_3
|
||||||
|
d.pin[3] = machine.LED_COL_4
|
||||||
|
d.pin[4] = machine.LED_COL_5
|
||||||
|
d.pin[5] = machine.LED_COL_6
|
||||||
|
d.pin[6] = machine.LED_COL_7
|
||||||
|
d.pin[7] = machine.LED_COL_8
|
||||||
|
d.pin[8] = machine.LED_COL_9
|
||||||
|
|
||||||
for i := machine.LED_COL_1; i <= machine.LED_ROW_3; i++ {
|
d.pin[9] = machine.LED_ROW_1
|
||||||
d.pin[i-machine.LED_COL_1] = i
|
d.pin[10] = machine.LED_ROW_2
|
||||||
d.pin[i-machine.LED_COL_1].Configure(machine.PinConfig{Mode: machine.PinOutput})
|
d.pin[11] = machine.LED_ROW_3
|
||||||
}
|
|
||||||
d.ClearDisplay()
|
|
||||||
d.DisableAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display sends the buffer (if any) to the screen.
|
for i := 0; i < len(d.pin); i++ {
|
||||||
func (d *Device) Display() error {
|
d.pin[i].Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
for row := 0; row < 3; row++ {
|
|
||||||
d.DisableAll()
|
|
||||||
d.pin[9+row].High()
|
|
||||||
|
|
||||||
for col := 0; col < 9; col++ {
|
|
||||||
if d.buffer[row][col] {
|
|
||||||
d.pin[col].Low()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
time.Sleep(time.Millisecond * 2)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClearDisplay erases the internal buffer
|
|
||||||
func (d *Device) ClearDisplay() {
|
|
||||||
for row := 0; row < 3; row++ {
|
|
||||||
for col := 0; col < 9; col++ {
|
|
||||||
d.buffer[row][col] = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DisableAll disables all the LEDs without modifying the buffer
|
|
||||||
func (d *Device) DisableAll() {
|
|
||||||
for i := machine.LED_COL_1; i <= machine.LED_COL_9; i++ {
|
|
||||||
d.pin[i-machine.LED_COL_1].High()
|
|
||||||
}
|
|
||||||
for i := machine.LED_ROW_1; i <= machine.LED_ROW_3; i++ {
|
|
||||||
d.pin[i-machine.LED_COL_1].Low()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnableAll enables all the LEDs without modifying the buffer
|
|
||||||
func (d *Device) EnableAll() {
|
|
||||||
for i := machine.LED_COL_1; i <= machine.LED_COL_9; i++ {
|
|
||||||
d.pin[i-machine.LED_COL_1].Low()
|
|
||||||
}
|
|
||||||
for i := machine.LED_ROW_1; i <= machine.LED_ROW_3; i++ {
|
|
||||||
d.pin[i-machine.LED_COL_1].High()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,50 +8,55 @@ package microbitmatrix // import "tinygo.org/x/drivers/microbitmatrix"
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"machine"
|
"machine"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 4 rotation orientations (0, 90, 180, 270), CW (clock wise)
|
||||||
|
// 5 rows
|
||||||
|
// 5 cols
|
||||||
|
// target coordinates in machine rows (y) and cols (x)
|
||||||
var matrixRotations = [4][5][5][2]uint8{
|
var matrixRotations = [4][5][5][2]uint8{
|
||||||
{ // 0
|
{ // 0
|
||||||
{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}},
|
|
||||||
{{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}},
|
|
||||||
{{0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}},
|
|
||||||
{{0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}},
|
|
||||||
{{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}},
|
|
||||||
},
|
|
||||||
{ // 90 CCW
|
|
||||||
{{4, 0}, {4, 1}, {4, 2}, {4, 3}, {4, 4}},
|
|
||||||
{{3, 0}, {3, 1}, {3, 2}, {3, 3}, {3, 4}},
|
|
||||||
{{2, 0}, {2, 1}, {2, 2}, {2, 3}, {2, 4}},
|
|
||||||
{{1, 0}, {1, 1}, {1, 2}, {1, 3}, {1, 4}},
|
|
||||||
{{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}},
|
{{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}},
|
||||||
|
{{1, 0}, {1, 1}, {1, 2}, {1, 3}, {1, 4}},
|
||||||
|
{{2, 0}, {2, 1}, {2, 2}, {2, 3}, {2, 4}},
|
||||||
|
{{3, 0}, {3, 1}, {3, 2}, {3, 3}, {3, 4}},
|
||||||
|
{{4, 0}, {4, 1}, {4, 2}, {4, 3}, {4, 4}},
|
||||||
|
},
|
||||||
|
{ // 90 CW
|
||||||
|
{{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}},
|
||||||
|
{{0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}},
|
||||||
|
{{0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}},
|
||||||
|
{{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}},
|
||||||
|
{{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}},
|
||||||
},
|
},
|
||||||
{ // 180
|
{ // 180
|
||||||
{{4, 4}, {3, 4}, {2, 4}, {1, 4}, {0, 4}},
|
{{4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}},
|
||||||
{{4, 3}, {3, 3}, {2, 3}, {1, 3}, {0, 3}},
|
{{3, 4}, {3, 3}, {3, 2}, {3, 1}, {3, 0}},
|
||||||
{{4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}},
|
{{2, 4}, {2, 3}, {2, 2}, {2, 1}, {2, 0}},
|
||||||
{{4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}},
|
{{1, 4}, {1, 3}, {1, 2}, {1, 1}, {1, 0}},
|
||||||
{{4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}},
|
{{0, 4}, {0, 3}, {0, 2}, {0, 1}, {0, 0}},
|
||||||
},
|
},
|
||||||
{ // 270
|
{ // 270
|
||||||
{{0, 4}, {0, 3}, {0, 2}, {0, 1}, {0, 0}},
|
{{4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}},
|
||||||
{{1, 4}, {1, 3}, {1, 2}, {1, 1}, {1, 0}},
|
{{4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}},
|
||||||
{{2, 4}, {2, 3}, {2, 2}, {2, 1}, {2, 0}},
|
{{4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}},
|
||||||
{{3, 4}, {3, 3}, {3, 2}, {3, 1}, {3, 0}},
|
{{4, 3}, {3, 3}, {2, 3}, {1, 3}, {0, 3}},
|
||||||
{{4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}},
|
{{4, 4}, {3, 4}, {2, 4}, {1, 4}, {0, 4}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
ledRows = 5
|
||||||
|
ledCols = 5
|
||||||
|
)
|
||||||
|
|
||||||
type Device struct {
|
type Device struct {
|
||||||
pin [10]machine.Pin
|
pin [ledCols + ledRows]machine.Pin
|
||||||
buffer [5][5]bool
|
buffer [ledRows][ledCols]bool
|
||||||
rotation uint8
|
rotation uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure sets up the device.
|
func (d *Device) assignPins() {
|
||||||
func (d *Device) Configure(cfg Config) {
|
|
||||||
d.SetRotation(cfg.Rotation)
|
|
||||||
|
|
||||||
d.pin[0] = machine.LED_COL_1
|
d.pin[0] = machine.LED_COL_1
|
||||||
d.pin[1] = machine.LED_COL_2
|
d.pin[1] = machine.LED_COL_2
|
||||||
d.pin[2] = machine.LED_COL_3
|
d.pin[2] = machine.LED_COL_3
|
||||||
@@ -64,53 +69,7 @@ func (d *Device) Configure(cfg Config) {
|
|||||||
d.pin[8] = machine.LED_ROW_4
|
d.pin[8] = machine.LED_ROW_4
|
||||||
d.pin[9] = machine.LED_ROW_5
|
d.pin[9] = machine.LED_ROW_5
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < len(d.pin); i++ {
|
||||||
d.pin[i].Configure(machine.PinConfig{Mode: machine.PinOutput})
|
d.pin[i].Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
}
|
}
|
||||||
|
|
||||||
d.ClearDisplay()
|
|
||||||
d.DisableAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display sends the buffer (if any) to the screen.
|
|
||||||
func (d *Device) Display() error {
|
|
||||||
for x := 0; x < 5; x++ {
|
|
||||||
d.DisableAll()
|
|
||||||
d.pin[x].Low()
|
|
||||||
|
|
||||||
for y := 0; y < 5; y++ {
|
|
||||||
if d.buffer[x][y] {
|
|
||||||
d.pin[5+y].High()
|
|
||||||
} else {
|
|
||||||
d.pin[5+y].Low()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
time.Sleep(time.Millisecond * 4)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClearDisplay erases the internal buffer
|
|
||||||
func (d *Device) ClearDisplay() {
|
|
||||||
for row := 0; row < 5; row++ {
|
|
||||||
for col := 0; col < 5; col++ {
|
|
||||||
d.buffer[row][col] = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DisableAll disables all the LEDs without modifying the buffer
|
|
||||||
func (d *Device) DisableAll() {
|
|
||||||
for i := 0; i < 5; i++ {
|
|
||||||
d.pin[i].High()
|
|
||||||
d.pin[5+i].Low()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnableAll enables all the LEDs without modifying the buffer
|
|
||||||
func (d *Device) EnableAll() {
|
|
||||||
for i := 0; i < 5; i++ {
|
|
||||||
d.pin[i].Low()
|
|
||||||
d.pin[5+i].High()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +1,132 @@
|
|||||||
// Package microbitmatrix implements a driver for the BBC micro:bit's LED matrix.
|
|
||||||
//
|
|
||||||
// Schematic: https://github.com/bbcmicrobit/hardware/blob/master/SCH_BBC-Microbit_V1.3B.pdf
|
|
||||||
package microbitmatrix // import "tinygo.org/x/drivers/microbitmatrix"
|
package microbitmatrix // import "tinygo.org/x/drivers/microbitmatrix"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"image/color"
|
"image/color"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
// Rotation of the LED matrix.
|
||||||
|
//
|
||||||
|
// Valid values:
|
||||||
|
//
|
||||||
|
// 0: regular orientation, (0 degree rotation)
|
||||||
|
// 1: 90 degree rotation clock wise
|
||||||
|
// 2: 180 degree rotation clock wise
|
||||||
|
// 3: 270 degree rotation clock wise
|
||||||
Rotation uint8
|
Rotation uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
RotationNormal = 0
|
||||||
|
Rotation90 = 1
|
||||||
|
Rotation180 = 2
|
||||||
|
Rotation270 = 3
|
||||||
|
)
|
||||||
|
|
||||||
// New returns a new microbitmatrix driver.
|
// New returns a new microbitmatrix driver.
|
||||||
func New() Device {
|
func New() Device {
|
||||||
return Device{}
|
return Device{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetRotation changes the rotation of the LED matrix
|
// Configure sets up the device.
|
||||||
|
func (d *Device) Configure(cfg Config) {
|
||||||
|
d.SetRotation(cfg.Rotation)
|
||||||
|
|
||||||
|
d.assignPins()
|
||||||
|
|
||||||
|
d.ClearDisplay()
|
||||||
|
d.DisableAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetRotation changes the rotation of the LED matrix.
|
||||||
|
//
|
||||||
|
// Valid values for rotation:
|
||||||
|
//
|
||||||
|
// 0: regular orientation, (0 degree rotation)
|
||||||
|
// 1: 90 degree rotation clock wise
|
||||||
|
// 2: 180 degree rotation clock wise
|
||||||
|
// 3: 270 degree rotation clock wise
|
||||||
func (d *Device) SetRotation(rotation uint8) {
|
func (d *Device) SetRotation(rotation uint8) {
|
||||||
d.rotation = rotation % 4
|
d.rotation = rotation % 4
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
rowIdx = 0
|
||||||
|
colIdx = 1
|
||||||
|
)
|
||||||
|
|
||||||
// SetPixel modifies the internal buffer in a single pixel.
|
// SetPixel modifies the internal buffer in a single pixel.
|
||||||
func (d *Device) SetPixel(x int16, y int16, c color.RGBA) {
|
func (d *Device) SetPixel(x int16, y int16, c color.RGBA) {
|
||||||
if x < 0 || x >= 5 || y < 0 || y >= 5 {
|
if x < 0 || x >= 5 || y < 0 || y >= 5 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
col := x
|
||||||
|
row := y
|
||||||
if c.R != 0 || c.G != 0 || c.B != 0 {
|
if c.R != 0 || c.G != 0 || c.B != 0 {
|
||||||
d.buffer[matrixRotations[d.rotation][y][x][0]][matrixRotations[d.rotation][y][x][1]] = true
|
d.buffer[matrixRotations[d.rotation][row][col][rowIdx]][matrixRotations[d.rotation][row][col][colIdx]] = true
|
||||||
} else {
|
} else {
|
||||||
d.buffer[matrixRotations[d.rotation][y][x][0]][matrixRotations[d.rotation][y][x][1]] = false
|
d.buffer[matrixRotations[d.rotation][row][col][rowIdx]][matrixRotations[d.rotation][row][col][colIdx]] = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPixel returns if the specific pixels is enabled
|
// GetPixel returns if the specific pixels is enabled.
|
||||||
func (d *Device) GetPixel(x int16, y int16) bool {
|
func (d *Device) GetPixel(x int16, y int16) bool {
|
||||||
if x < 0 || x >= 5 || y < 0 || y >= 5 {
|
if x < 0 || x >= 5 || y < 0 || y >= 5 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return d.buffer[matrixRotations[d.rotation][y][x][0]][matrixRotations[d.rotation][y][x][1]]
|
col := x
|
||||||
|
row := y
|
||||||
|
return d.buffer[matrixRotations[d.rotation][row][col][rowIdx]][matrixRotations[d.rotation][row][col][colIdx]]
|
||||||
|
}
|
||||||
|
|
||||||
|
const displayRefreshDelay = 8 * time.Millisecond
|
||||||
|
|
||||||
|
// Display sends the buffer (if any) to the screen.
|
||||||
|
func (d *Device) Display() error {
|
||||||
|
for row := 0; row < ledRows; row++ {
|
||||||
|
d.DisableAll()
|
||||||
|
d.pin[ledCols+row].Low()
|
||||||
|
|
||||||
|
for col := 0; col < ledCols; col++ {
|
||||||
|
if d.buffer[row][col] {
|
||||||
|
d.pin[col].High()
|
||||||
|
} else {
|
||||||
|
d.pin[col].Low()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time.Sleep(time.Millisecond * 4)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearDisplay erases the internal buffer.
|
||||||
|
func (d *Device) ClearDisplay() {
|
||||||
|
for row := 0; row < ledRows; row++ {
|
||||||
|
for col := 0; col < ledCols; col++ {
|
||||||
|
d.buffer[row][col] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DisableAll disables all the LEDs without modifying the buffer.
|
||||||
|
func (d *Device) DisableAll() {
|
||||||
|
for i := 0; i < ledCols; i++ {
|
||||||
|
d.pin[i].High()
|
||||||
|
}
|
||||||
|
for i := 0; i < ledRows; i++ {
|
||||||
|
d.pin[ledCols+i].Low()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnableAll enables all the LEDs without modifying the buffer.
|
||||||
|
func (d *Device) EnableAll() {
|
||||||
|
for i := 0; i < ledCols; i++ {
|
||||||
|
d.pin[i].Low()
|
||||||
|
}
|
||||||
|
for i := 0; i < ledRows; i++ {
|
||||||
|
d.pin[ledCols+i].High()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size returns the current size of the display.
|
// Size returns the current size of the display.
|
||||||
|
|||||||
Reference in New Issue
Block a user