206 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			206 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package mt12232a
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"io"
 | 
						|
	"log"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"gitea.unprism.ru/yotia/display-test/pkg/parallel8bit"
 | 
						|
	"github.com/stianeikeland/go-rpio/v4"
 | 
						|
)
 | 
						|
 | 
						|
type mt12232a struct {
 | 
						|
	logger *log.Logger
 | 
						|
 | 
						|
	dev parallel8bit.Device
 | 
						|
 | 
						|
	pinCS  rpio.Pin
 | 
						|
	pinRES rpio.Pin
 | 
						|
}
 | 
						|
 | 
						|
type Device interface {
 | 
						|
	PowerOn() error
 | 
						|
	SetPixel(x, y byte, c bool) error
 | 
						|
 | 
						|
	WriteCodeL(c byte) error
 | 
						|
	WriteCodeR(c byte) error
 | 
						|
	WriteDataL(b byte) error
 | 
						|
	WriteDataR(b byte) error
 | 
						|
 | 
						|
	ReadDataL() (byte, error)
 | 
						|
	ReadDataR() (byte, error)
 | 
						|
	ReadStatus(cs rpio.State) byte
 | 
						|
 | 
						|
	io.Closer
 | 
						|
}
 | 
						|
 | 
						|
func New(logger *log.Logger) (Device, error) {
 | 
						|
	rpio.Open()
 | 
						|
 | 
						|
	d := mt12232a{
 | 
						|
		logger: logger,
 | 
						|
 | 
						|
		dev: parallel8bit.New(logger, parallel8bit.DevicePins{
 | 
						|
			PinA0: rpio.Pin(18),
 | 
						|
			PinRW: rpio.Pin(17),
 | 
						|
			PinE:  rpio.Pin(27),
 | 
						|
 | 
						|
			PinDB0: rpio.Pin(22),
 | 
						|
			PinDB1: rpio.Pin(10),
 | 
						|
			PinDB2: rpio.Pin(9), // From 21
 | 
						|
			PinDB3: rpio.Pin(11),
 | 
						|
			PinDB4: rpio.Pin(12),
 | 
						|
			PinDB5: rpio.Pin(16), // From 32
 | 
						|
			PinDB6: rpio.Pin(20), // From 31
 | 
						|
			PinDB7: rpio.Pin(13), // From 33
 | 
						|
 | 
						|
		}),
 | 
						|
 | 
						|
		pinCS:  rpio.Pin(19),
 | 
						|
		pinRES: rpio.Pin(21),
 | 
						|
	}
 | 
						|
	d.pinCS.Output()
 | 
						|
	d.pinRES.Output()
 | 
						|
	d.dev.Reset()
 | 
						|
 | 
						|
	return &d, nil
 | 
						|
}
 | 
						|
 | 
						|
func (d *mt12232a) Close() error {
 | 
						|
	return rpio.Close()
 | 
						|
}
 | 
						|
 | 
						|
func (d *mt12232a) SetPixel(x, y byte, c bool) error {
 | 
						|
	// var c8 byte
 | 
						|
	// var mask byte
 | 
						|
 | 
						|
	// Check bounds
 | 
						|
	if x > 127 || y > 63 {
 | 
						|
		return fmt.Errorf("positions out of bounds")
 | 
						|
	}
 | 
						|
 | 
						|
	if x < 64 { // Left crystal
 | 
						|
		d.WriteCodeL(0xB8 | (y >> 3)) // Set page
 | 
						|
		d.WriteCodeL(0x40 | x)        // Set addr
 | 
						|
		// c8=ReadDataL(); // ?? ok
 | 
						|
		// c8=ReadDataL(); // Read byte
 | 
						|
		// m8=1<<(y&0x07);//Вычислить маску нужного бита в байте
 | 
						|
		// if (c==1)	//Зажигать точку?
 | 
						|
		// 	c8|=m8//Установить нужный бит в байте
 | 
						|
		// else		//Или гасить точку?
 | 
						|
		// 	c8&=~m8;//Сбросить нужный бит в байте
 | 
						|
		// WriteCodeL(0x40|x);//Снова установить адрес нужного байта
 | 
						|
		d.WriteDataL(0x34) // Write byte
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (d *mt12232a) PowerOn() error {
 | 
						|
	d.logger.Println(d.ReadStatus(0)) // Should be 0
 | 
						|
	d.logger.Println("Reset")
 | 
						|
	d.pinRES.Low()
 | 
						|
	time.Sleep(time.Microsecond)
 | 
						|
	d.logger.Println(d.ReadStatus(0)) // Should be 48 (power off and reset)
 | 
						|
	d.pinRES.High()
 | 
						|
	time.Sleep(10 * time.Microsecond)
 | 
						|
	d.logger.Println(d.ReadStatus(0)) // Should be 32 (power off)
 | 
						|
 | 
						|
	// Module is reset and should be turned off
 | 
						|
	if d.ReadStatus(0) == 0 || d.ReadStatus(1) == 0 {
 | 
						|
		return fmt.Errorf("no response from display(or it is possible that it is turned on but...)")
 | 
						|
	}
 | 
						|
 | 
						|
	d.logger.Println("Power on")
 | 
						|
	d.WriteCodeL(0xE2) // Reset
 | 
						|
	d.WriteCodeR(0xE2) // Reset
 | 
						|
	d.WriteCodeL(0xEE) // ReadModifyWrite off
 | 
						|
	d.WriteCodeR(0xEE) // ReadModifyWrite off
 | 
						|
	d.WriteCodeL(0xA4) // Turn on common mode
 | 
						|
	d.WriteCodeR(0xA4) // Turn on common mode
 | 
						|
	d.WriteCodeL(0xA9) // Multiplex 1/32
 | 
						|
	d.WriteCodeR(0xA9) // Multiplex 1/32
 | 
						|
	d.WriteCodeL(0xC0) // Top line to 0
 | 
						|
	d.WriteCodeR(0xC0) // Top line to 0
 | 
						|
	d.WriteCodeL(0xA1) // Invert scan RAM
 | 
						|
	d.WriteCodeR(0xA0) // NonInvert scan RAM
 | 
						|
 | 
						|
	d.logger.Println("Display on")
 | 
						|
	d.WriteCodeL(0xAF) // Display on
 | 
						|
	d.WriteCodeR(0xAF) // Display on
 | 
						|
 | 
						|
	// Check that crystals are turned on
 | 
						|
	if (d.ReadStatus(0) & (1 << 5)) != 0 {
 | 
						|
		return fmt.Errorf("Left cristal is still off")
 | 
						|
	}
 | 
						|
	if (d.ReadStatus(1) & (1 << 5)) != 0 {
 | 
						|
		return fmt.Errorf("Right cristal is still off")
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// Write codes
 | 
						|
 | 
						|
func (d *mt12232a) WriteCodeL(c byte) error {
 | 
						|
	return d.writeByte(c, 0, 0)
 | 
						|
}
 | 
						|
 | 
						|
func (d *mt12232a) WriteCodeR(c byte) error {
 | 
						|
	return d.writeByte(c, 0, 1)
 | 
						|
}
 | 
						|
 | 
						|
// Write data as byte
 | 
						|
 | 
						|
func (d *mt12232a) WriteDataL(b byte) error {
 | 
						|
	return d.writeByte(b, 1, 0)
 | 
						|
}
 | 
						|
 | 
						|
func (d *mt12232a) WriteDataR(b byte) error {
 | 
						|
	return d.writeByte(b, 1, 1)
 | 
						|
}
 | 
						|
 | 
						|
// Read data
 | 
						|
 | 
						|
func (d *mt12232a) ReadDataL() (byte, error) {
 | 
						|
	return d.readByte(1, 0)
 | 
						|
}
 | 
						|
 | 
						|
func (d *mt12232a) ReadDataR() (byte, error) {
 | 
						|
	return d.readByte(1, 1)
 | 
						|
}
 | 
						|
 | 
						|
// Low level functions
 | 
						|
 | 
						|
func (d *mt12232a) writeByte(b byte, cd, cs rpio.State) error {
 | 
						|
	// d.logger.Println("Write byte", b, cd, l, r)
 | 
						|
	if err := d.waitReady(cs); err != nil {
 | 
						|
		return fmt.Errorf("wait ready: %w", err)
 | 
						|
	}
 | 
						|
	d.pinCS.Write(cs) // Select cristals
 | 
						|
 | 
						|
	d.dev.WriteByte(b, cd)
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (d *mt12232a) readByte(cd, cs rpio.State) (byte, error) {
 | 
						|
	// Setup
 | 
						|
	if err := d.waitReady(cs); err != nil {
 | 
						|
		return 0, fmt.Errorf("wait ready: %w", err)
 | 
						|
	}
 | 
						|
	d.pinCS.Write(cs) // Select cristals
 | 
						|
 | 
						|
	return d.dev.ReadByte(cd), nil
 | 
						|
}
 | 
						|
 | 
						|
// Wait, checking status byte
 | 
						|
func (d *mt12232a) waitReady(cs rpio.State) error {
 | 
						|
	d.pinCS.Write(cs) // Select cristals
 | 
						|
	return d.dev.WaitReady()
 | 
						|
}
 | 
						|
 | 
						|
func (d *mt12232a) ReadStatus(cs rpio.State) byte {
 | 
						|
	d.pinCS.Write(cs) // Select cristals
 | 
						|
	return d.dev.ReadByte(1)
 | 
						|
}
 |