Add: separated mt-12864a lib

This commit is contained in:
Andrey Egorov 2024-08-28 14:14:55 +03:00
parent 26edd24fef
commit 65b2135c20
7 changed files with 471 additions and 229 deletions

View File

@ -1,253 +1,43 @@
package display package display
import ( import (
"fmt"
"image" "image"
"log" "log"
"time"
"gitea.unprism.ru/yotia/display-test/pkg/mt12864a"
"github.com/stianeikeland/go-rpio/v4" "github.com/stianeikeland/go-rpio/v4"
) )
const ( type displayMt12864a struct {
adressWriteTimeout = 140 * time.Nanosecond
dataStrobeTimeout = 250 * time.Nanosecond // (Data transfer)
)
type mt12864a struct {
logger *log.Logger logger *log.Logger
// GPIO pins // GPIO pins
pinA0 rpio.Pin dev mt12864a.Device
pinRW rpio.Pin
pinE rpio.Pin
pinDB0 rpio.Pin
pinDB1 rpio.Pin
pinDB2 rpio.Pin
pinDB3 rpio.Pin
pinDB4 rpio.Pin
pinDB5 rpio.Pin
pinDB6 rpio.Pin
pinDB7 rpio.Pin
pinE1 rpio.Pin
pinE2 rpio.Pin
pinRES rpio.Pin
} }
func newMt12864a(logger *log.Logger) (Display, error) { func newMt12864a(logger *log.Logger) (Display, error) {
rpio.Open() dev, err := mt12864a.New(log.New(logger.Writer(), "display-mt12864 : ", log.LstdFlags))
if err != nil {
d := mt12864a{ return nil, fmt.Errorf("mt12864 create: %w", err)
logger: logger,
pinA0: rpio.Pin(7),
pinRW: rpio.Pin(11),
pinE: rpio.Pin(13),
pinDB0: rpio.Pin(15),
pinDB1: rpio.Pin(19),
pinDB2: rpio.Pin(21),
pinDB3: rpio.Pin(23),
pinDB4: rpio.Pin(27),
pinDB5: rpio.Pin(29),
pinDB6: rpio.Pin(31),
pinDB7: rpio.Pin(33),
pinE1: rpio.Pin(35),
pinE2: rpio.Pin(37),
pinRES: rpio.Pin(40),
} }
d.initLCD() dev.PowerOn()
d := displayMt12864a{
logger: logger,
dev: dev,
}
return &d, nil return &d, nil
} }
func (d *mt12864a) GetBounds() image.Rectangle { func (d *displayMt12864a) GetBounds() image.Rectangle {
return image.Rectangle{} return image.Rectangle{}
} }
func (d *mt12864a) Flush(img *image.Gray) error { func (d *displayMt12864a) Flush(img *image.Gray) error {
return nil return nil
} }
func (d *mt12864a) Close() error { func (d *displayMt12864a) Close() error {
return rpio.Close() return rpio.Close()
} }
func (d *mt12864a) initLCD() {
// Set All to output
d.pinA0.Output()
d.pinRW.Output()
d.pinE.Output()
d.pinE1.Output()
d.pinE2.Output()
d.pinRES.Output()
d.busOutput()
d.logger.Println("sdljfsldkf")
// d.pinA0.Low()
// d.logger.Println("pinA0 set low")
// d.pinRW.Low()
// d.logger.Println("pinRW set low")
// d.pinE.Low()
// d.logger.Println("pinE set low")
// d.pinDB0.Low()
// d.logger.Println("pinDB0 set low")
// d.pinDB1.Low()
// d.logger.Println("pinDB1 set low")
// d.pinDB2.Low()
// d.logger.Println("pinDB2 set low")
// d.pinDB3.Low()
// d.logger.Println("pinDB3 set low")
// d.pinDB4.Low()
// d.logger.Println("pinDB4 set low")
// d.pinDB5.Low()
// d.logger.Println("pinDB5 set low")
// d.pinDB6.Low()
// d.logger.Println("pinDB6 set low")
// d.pinDB7.Low()
// d.logger.Println("pinDB7 set low")
// d.pinE1.Low()
// d.logger.Println("pinE1 set low")
// d.pinE2.Low()
// d.logger.Println("pinE2 set low")
// d.pinRES.Low()
// d.logger.Println("pinRES set low")
// d.pinE.Low()
// d.pinRES.Low()
// time.Sleep(time.Microsecond)
// d.pinRES.High()
// time.Sleep(10 * time.Microsecond)
// d.writeCodeL(0xC0) // Top line to 0
// d.writeCodeR(0xC0)
// d.writeCodeL(0x3F) // Display on
// d.writeCodeR(0x3F)
}
func (d *mt12864a) writeCodeL(c byte) {
d.writeByte(c, 0, 1, 0)
}
func (d *mt12864a) writeCodeR(c byte) {
d.writeByte(c, 0, 0, 1)
}
func (d *mt12864a) writeDataL(b byte) {
d.writeByte(b, 1, 1, 0)
}
func (d *mt12864a) writeDataR(b byte) {
d.writeByte(b, 1, 0, 1)
}
func (d *mt12864a) readDataL() byte {
return d.readByte(1, 1, 0)
}
func (d *mt12864a) readDataR() byte {
return d.readByte(1, 0, 1)
}
func (d *mt12864a) writeByte(b byte, cd, l, r rpio.State) {
if l == rpio.High && r == rpio.High {
d.logger.Println("L and R are high!!!")
return
}
d.waitReady(l, r)
d.busOutput()
d.pinRW.Low() // We write
d.pinA0.Write(cd)
d.pinE1.Write(l) // Select cristals
d.pinE2.Write(r) // Select cristals
// Write bus
d.pinDB0.Write(rpio.State((b >> 0) & 1))
d.pinDB1.Write(rpio.State((b >> 1) & 1))
d.pinDB2.Write(rpio.State((b >> 2) & 1))
d.pinDB3.Write(rpio.State((b >> 3) & 1))
d.pinDB4.Write(rpio.State((b >> 4) & 1))
d.pinDB5.Write(rpio.State((b >> 5) & 1))
d.pinDB6.Write(rpio.State((b >> 6) & 1))
d.pinDB7.Write(rpio.State((b >> 7) & 1))
// Strobe start
d.pinE.High()
time.Sleep(dataStrobeTimeout)
// Strobe end
d.pinE.Low()
time.Sleep(time.Millisecond - dataStrobeTimeout - adressWriteTimeout)
}
func (d *mt12864a) readByte(cd, l, r rpio.State) byte {
if l == rpio.High && r == rpio.High {
d.logger.Println("L and R are high!!!")
return 0
}
var b byte
d.waitReady(l, r)
d.busOutput()
d.pinRW.High() // We write
d.pinA0.Write(cd)
d.pinE1.Write(l) // Select cristals
d.pinE2.Write(r) // Select cristals
// Strobe start
d.pinE.High()
time.Sleep(dataStrobeTimeout)
// Read
b = uint8(d.pinDB0.Read()) |
(uint8(d.pinDB1.Read()) << 1) |
(uint8(d.pinDB2.Read()) << 2) |
(uint8(d.pinDB3.Read()) << 3) |
(uint8(d.pinDB4.Read()) << 4) |
(uint8(d.pinDB5.Read()) << 5) |
(uint8(d.pinDB6.Read()) << 6) |
(uint8(d.pinDB7.Read()) << 7)
// Strobe end
d.pinE.Low()
time.Sleep(time.Millisecond - dataStrobeTimeout - adressWriteTimeout)
return b
}
// Wait, checking status byte
func (d *mt12864a) waitReady(l, r rpio.State) {
d.busInput() // Set bus to input
d.pinRW.High() // We read
d.pinA0.Low() // Data
d.pinE1.Write(l) // Select cristals
d.pinE2.Write(r) // Select cristals
time.Sleep(adressWriteTimeout)
// Strobe start
d.pinE.High()
time.Sleep(dataStrobeTimeout)
// Wait status flag drop
counter := 0
for d.pinDB7.Read() == rpio.High && counter < 100 {
counter++
}
// Strobe end
d.pinE.Low()
time.Sleep(time.Millisecond - dataStrobeTimeout - adressWriteTimeout)
}
// Set bus pins to output
func (d *mt12864a) busOutput() {
d.pinDB0.Output()
d.pinDB1.Output()
d.pinDB2.Output()
d.pinDB3.Output()
d.pinDB4.Output()
// d.pinDB5.Output()
d.pinDB6.Output()
d.pinDB7.Output()
}
func (d *mt12864a) busInput() {
d.pinDB0.Input()
d.pinDB1.Input()
d.pinDB2.Input()
d.pinDB3.Input()
d.pinDB4.Input()
d.pinDB5.Input()
d.pinDB6.Input()
d.pinDB7.Input()
}

View File

@ -1,10 +1,11 @@
package drawer package drawer
import ( import (
"display-test/display"
"image" "image"
"sync" "sync"
"gitea.unprism.ru/yotia/display-test/display"
"golang.org/x/image/font" "golang.org/x/image/font"
"golang.org/x/image/font/inconsolata" "golang.org/x/image/font/inconsolata"
) )

2
go.mod
View File

@ -1,4 +1,4 @@
module display-test module gitea.unprism.ru/yotia/display-test
go 1.22.5 go 1.22.5

View File

@ -2,8 +2,6 @@ package main
import ( import (
"context" "context"
"display-test/display"
"display-test/drawer"
"fmt" "fmt"
"log" "log"
"os" "os"
@ -11,6 +9,9 @@ import (
"syscall" "syscall"
"time" "time"
"gitea.unprism.ru/yotia/display-test/display"
"gitea.unprism.ru/yotia/display-test/drawer"
"gitea.unprism.ru/KRBL/sim-modem/api/modem" "gitea.unprism.ru/KRBL/sim-modem/api/modem"
) )
@ -162,6 +163,7 @@ func mainE(ctx context.Context) error {
logger = log.New(os.Stdout, "main : ", log.LstdFlags) logger = log.New(os.Stdout, "main : ", log.LstdFlags)
// //
disp, _ := display.New(logger, display.MT12864A) disp, _ := display.New(logger, display.MT12864A)
time.Sleep(2 * time.Second)
defer disp.Close() defer disp.Close()
// if err := Init(ctx); err != nil { // if err := Init(ctx); err != nil {
// return err // return err

414
pkg/mt12864a/mt12864a.go Normal file
View File

@ -0,0 +1,414 @@
package mt12864a
import (
"io"
"log"
"time"
"github.com/stianeikeland/go-rpio/v4"
)
const (
adressWriteTimeout = 140 * time.Nanosecond
dataStrobeTimeout = 250 * time.Nanosecond // (Data transfer)
maxWaitCycles = 100
)
type mt12864a struct {
logger *log.Logger
// GPIO pins
pinA0 rpio.Pin
pinRW rpio.Pin
pinE rpio.Pin
pinDB0 rpio.Pin
pinDB1 rpio.Pin
pinDB2 rpio.Pin
pinDB3 rpio.Pin
pinDB4 rpio.Pin
pinDB5 rpio.Pin
pinDB6 rpio.Pin
pinDB7 rpio.Pin
pinE1 rpio.Pin
pinE2 rpio.Pin
pinRES rpio.Pin
}
type Device interface {
PowerOn()
WriteCodeL(c byte)
WriteCodeR(c byte)
WriteDataL(b byte)
WriteDataR(b byte)
WriteDataArrayL(b []byte)
WriteDataArrayR(b []byte)
ReadDataL() byte
ReadDataR() byte
ReadDataArrayL() []byte
ReadDataArrayR() []byte
io.Closer
}
func New(logger *log.Logger) (Device, error) {
rpio.Open()
d := mt12864a{
logger: logger,
pinA0: rpio.Pin(7),
pinRW: rpio.Pin(11),
pinE: rpio.Pin(13),
pinDB0: rpio.Pin(15),
pinDB1: rpio.Pin(19),
pinDB2: rpio.Pin(21),
pinDB3: rpio.Pin(23),
pinDB4: rpio.Pin(27),
pinDB5: rpio.Pin(32),
pinDB6: rpio.Pin(31),
pinDB7: rpio.Pin(33),
// Reverted
// pinDB7: rpio.Pin(15),
// pinDB6: rpio.Pin(19),
// pinDB5: rpio.Pin(21),
// pinDB4: rpio.Pin(23),
// pinDB3: rpio.Pin(27),
// pinDB2: rpio.Pin(32),
// pinDB1: rpio.Pin(31),
// pinDB0: rpio.Pin(33),
pinE1: rpio.Pin(35),
pinE2: rpio.Pin(37),
pinRES: rpio.Pin(40),
}
d.AllOutput()
d.PrintPins()
return &d, nil
}
func (d *mt12864a) Close() error {
return rpio.Close()
}
func (d *mt12864a) PowerOn() {
d.pinA0.PullOff()
d.pinRW.PullOff()
d.pinE.PullOff()
d.pinDB0.PullOff()
d.pinDB1.PullOff()
d.pinDB2.PullOff()
d.pinDB3.PullOff()
d.pinDB4.PullOff()
d.pinDB5.PullOff()
d.pinDB6.PullOff()
d.pinDB7.PullOff()
d.pinE1.PullOff()
d.pinE2.PullOff()
d.pinRES.PullOff()
d.pinA0.Low()
d.pinRW.Low()
d.pinE.Low()
d.pinDB0.Low()
d.pinDB1.Low()
d.pinDB2.Low()
d.pinDB3.Low()
d.pinDB4.Low()
d.pinDB5.Low()
d.pinDB6.Low()
d.pinDB7.Low()
d.pinE1.Low()
d.pinE2.Low()
d.pinRES.Low()
d.PrintPins()
d.logger.Println("Power on")
d.PrintPins()
d.pinE.Low()
d.PrintPins()
d.pinRES.Low()
d.PrintPins()
time.Sleep(time.Microsecond)
d.pinRES.High()
time.Sleep(10 * time.Microsecond)
d.PrintPins()
d.logger.Println("Display on")
d.WriteCodeL(0x3F) // Display on
d.PrintPins()
d.logger.Println("Top line to 0")
d.WriteCodeL(0xC0) // Top line to 0
d.PrintPins()
}
// Write codes
func (d *mt12864a) WriteCodeL(c byte) {
d.writeByte(c, 0, 1, 0)
}
func (d *mt12864a) WriteCodeR(c byte) {
d.writeByte(c, 0, 0, 1)
}
// Write data as byte
func (d *mt12864a) WriteDataL(b byte) {
d.writeByte(b, 1, 1, 0)
}
func (d *mt12864a) WriteDataR(b byte) {
d.writeByte(b, 1, 0, 1)
}
// Write data as byte array
func (d *mt12864a) WriteDataArrayL(b []byte) {
d.writeByteArray(b, 1, 1, 0)
}
func (d *mt12864a) WriteDataArrayR(b []byte) {
d.writeByteArray(b, 1, 0, 1)
}
// Read data
func (d *mt12864a) ReadDataL() byte {
return d.readByte(1, 1, 0)
}
func (d *mt12864a) ReadDataR() byte {
return d.readByte(1, 0, 1)
}
// Read data array
func (d *mt12864a) ReadDataArrayL() []byte {
return d.readByteArray(1, 1, 0)
}
func (d *mt12864a) ReadDataArrayR() []byte {
return d.readByteArray(1, 0, 1)
}
// Low level functions
func (d *mt12864a) writeByte(b byte, cd, l, r rpio.State) {
d.logger.Println("Write byte", b, cd, l, r)
if l == rpio.High && r == rpio.High {
d.logger.Println("L and R are high!!!")
return
}
d.waitReady(l, r)
d.busOutput()
d.pinRW.Low() // We write
d.pinA0.Write(cd)
d.pinE1.Write(l) // Select cristals
d.pinE2.Write(r) // Select cristals
// Write bus
d.pinDB0.Write(rpio.State((b >> 0) & 1))
d.pinDB1.Write(rpio.State((b >> 1) & 1))
d.pinDB2.Write(rpio.State((b >> 2) & 1))
d.pinDB3.Write(rpio.State((b >> 3) & 1))
d.pinDB4.Write(rpio.State((b >> 4) & 1))
d.pinDB5.Write(rpio.State((b >> 5) & 1))
d.pinDB6.Write(rpio.State((b >> 6) & 1))
d.pinDB7.Write(rpio.State((b >> 7) & 1))
// Strobe start
d.pinE.High()
time.Sleep(dataStrobeTimeout)
// Strobe end
d.pinE.Low()
time.Sleep(time.Millisecond - dataStrobeTimeout - adressWriteTimeout)
}
func (d *mt12864a) writeByteArray(b []byte, cd, l, r rpio.State) {
d.logger.Println("Write byte", b, cd, l, r)
if len(b) != 8 {
d.logger.Println("invalid b len")
return
}
if l == rpio.High && r == rpio.High {
d.logger.Println("L and R are high!!!")
return
}
d.waitReady(l, r)
d.busOutput()
d.pinRW.Low() // We write
d.pinA0.Write(cd)
d.pinE1.Write(l) // Select cristals
d.pinE2.Write(r) // Select cristals
// Write bus
d.pinDB0.Write(rpio.State(b[0]))
d.pinDB1.Write(rpio.State(b[1]))
d.pinDB2.Write(rpio.State(b[2]))
d.pinDB3.Write(rpio.State(b[3]))
d.pinDB4.Write(rpio.State(b[4]))
d.pinDB5.Write(rpio.State(b[5]))
d.pinDB6.Write(rpio.State(b[6]))
d.pinDB7.Write(rpio.State(b[7]))
// Strobe start
d.pinE.High()
time.Sleep(dataStrobeTimeout)
// Strobe end
d.pinE.Low()
time.Sleep(time.Millisecond - dataStrobeTimeout - adressWriteTimeout)
}
func (d *mt12864a) readByte(cd, l, r rpio.State) byte {
if l == rpio.High && r == rpio.High {
d.logger.Println("L and R are high!!!")
return 0
}
var b byte
d.waitReady(l, r)
d.busOutput()
d.pinRW.High() // We write
d.pinA0.Write(cd)
d.pinE1.Write(l) // Select cristals
d.pinE2.Write(r) // Select cristals
// Strobe start
d.pinE.High()
time.Sleep(dataStrobeTimeout)
// Read
b = uint8(d.pinDB0.Read()) |
(uint8(d.pinDB1.Read()) << 1) |
(uint8(d.pinDB2.Read()) << 2) |
(uint8(d.pinDB3.Read()) << 3) |
(uint8(d.pinDB4.Read()) << 4) |
(uint8(d.pinDB5.Read()) << 5) |
(uint8(d.pinDB6.Read()) << 6) |
(uint8(d.pinDB7.Read()) << 7)
// Strobe end
d.pinE.Low()
time.Sleep(time.Millisecond - dataStrobeTimeout - adressWriteTimeout)
return b
}
func (d *mt12864a) readByteArray(cd, l, r rpio.State) []byte {
if l == rpio.High && r == rpio.High {
d.logger.Println("L and R are high!!!")
return nil
}
b := make([]byte, 8)
d.waitReady(l, r)
d.busOutput()
d.pinRW.High() // We write
d.pinA0.Write(cd)
d.pinE1.Write(l) // Select cristals
d.pinE2.Write(r) // Select cristals
// Strobe start
d.pinE.High()
time.Sleep(dataStrobeTimeout)
// Read
b[0] = (uint8(d.pinDB0.Read()) << 0)
b[1] = (uint8(d.pinDB1.Read()) << 1)
b[2] = (uint8(d.pinDB2.Read()) << 2)
b[3] = (uint8(d.pinDB3.Read()) << 3)
b[4] = (uint8(d.pinDB4.Read()) << 4)
b[5] = (uint8(d.pinDB5.Read()) << 5)
b[6] = (uint8(d.pinDB6.Read()) << 6)
b[7] = (uint8(d.pinDB7.Read()) << 7)
// Strobe end
d.pinE.Low()
time.Sleep(time.Millisecond - dataStrobeTimeout - adressWriteTimeout)
return nil
}
// Wait, checking status byte
func (d *mt12864a) waitReady(l, r rpio.State) {
d.logger.Println("Wait ready", l, r)
d.busInput() // Set bus to input
d.pinRW.High() // We read
d.pinA0.Low() // Data
d.pinE1.Write(l) // Select cristals
d.pinE2.Write(r) // Select cristals
time.Sleep(adressWriteTimeout)
// Strobe start
d.pinE.High()
time.Sleep(dataStrobeTimeout)
// Wait status flag drop
counter := 0
for counter < maxWaitCycles {
d.busInput() // Set bus to input
if d.pinDB7.Read() != rpio.High {
break
}
d.PrintPins()
counter++
}
if counter == maxWaitCycles {
log.Println("TIMEOUT!!!!!!!!!!!!!")
}
// Strobe end
d.pinE.Low()
time.Sleep(time.Millisecond - dataStrobeTimeout - adressWriteTimeout)
d.logger.Println("Ready")
}
func (d *mt12864a) PrintPins() {
d.AllInput()
d.logger.Printf("A0:%d RW:%d E:%d BUS:%d%d%d%d%d%d%d%d E1:%d E2:%d RES:%d\n", d.pinA0.Read(), d.pinRW.Read(), d.pinE.Read(), d.pinDB0.Read(), d.pinDB1.Read(), d.pinDB2.Read(), d.pinDB3.Read(), d.pinDB4.Read(), d.pinDB5.Read(), d.pinDB6.Read(), d.pinDB7.Read(), d.pinE1.Read(), d.pinE2.Read(), d.pinRES.Read())
d.AllOutput()
}
func (d *mt12864a) AllOutput() {
d.pinA0.Output()
d.pinRW.Output()
d.pinE.Output()
d.pinE1.Output()
d.pinE2.Output()
d.pinRES.Output()
d.busOutput()
}
func (d *mt12864a) AllInput() {
d.pinA0.Input()
d.pinRW.Input()
d.pinE.Input()
d.pinE1.Input()
d.pinE2.Input()
d.pinRES.Input()
d.busInput()
}
// Set bus pins to output
func (d *mt12864a) busOutput() {
d.pinDB0.Output()
d.pinDB1.Output()
d.pinDB2.Output()
d.pinDB3.Output()
d.pinDB4.Output()
d.pinDB5.Output()
d.pinDB6.Output()
d.pinDB7.Output()
}
func (d *mt12864a) busInput() {
d.pinDB0.Input()
d.pinDB1.Input()
d.pinDB2.Input()
d.pinDB3.Input()
d.pinDB4.Input()
d.pinDB5.Input()
d.pinDB6.Input()
d.pinDB7.Input()
}

35
readme.md Normal file
View File

@ -0,0 +1,35 @@
## ssd1306
res: 128x32
iface: i2c
u: 3v
pins:
1. VCC => 1
2. GND => 9
3. SCK => 3
4. SDA => 5
## MT-12864A
[Doc](https://www.melt.com.ru/docs/MT-12864A.pdf)
res: 128x64
u: 3v
pins:
1. GND => 9
2. UCC => 17
3. U0 -W
4. A0 => 7
5. R/W => 11
6. E => 13
7. DB0 => 15
8. DB1 => 19
9. DB2 => 21
10. DB3 => 23
11. DB4 => 27
12. DB5 => (29 does not work) =>
13. DB6 => 31
14. DB7 => 33
15. E1 => 35
16. E2 => 37
17. RES => 40
18. Uee => rheostat => U0 (contrast settings)
19. A (light+) ??
20. K (light-) ??