package parallel8bit import ( "fmt" "log" "time" "github.com/stianeikeland/go-rpio/v4" ) const ( adressWriteTimeout = 140 * time.Nanosecond dataStrobeTimeout = 250 * time.Nanosecond // (Data transfer) maxWaitCycles = 100 ) // Interface for MT displays (do not set cristals bits) type Device interface { Reset() WriteByte(b byte, cd rpio.State) WriteBytes(b []byte, cd rpio.State) ReadByte(cd rpio.State) byte Pins() DevicePins WaitReady() error } type DevicePins struct { // 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 struct { logger *log.Logger isBusOutput bool DevicePins } func New(logger *log.Logger, pins DevicePins) Device { return &device{ logger: logger, DevicePins: pins, } } func (d *device) Pins() DevicePins { return d.DevicePins } func (d *device) Reset() { d.PinA0.Output() d.PinRW.Output() d.PinE.Output() d.PinRES.Output() d.busOutput() d.PinE.Low() } func (d *device) WriteByte(b byte, cd rpio.State) { // d.logger.Println("Write byte", b, cd, l, r) d.busOutput() d.PinRW.Low() // We write d.PinA0.Write(cd) // 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 *device) WriteBytes(b []byte, cd rpio.State) { // d.logger.Println("Write byte", b, cd, l, r) d.busOutput() d.PinRW.Low() // We write d.PinA0.Write(cd) // 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 *device) ReadByte(cd rpio.State) byte { // Setup var b byte d.busOutput() d.PinRW.High() // We write d.PinA0.Write(cd) // 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 *device) WaitReady() error { d.busInput() // Set bus to input d.PinRW.High() // We read d.PinA0.Low() // Status time.Sleep(adressWriteTimeout) // Strobe start d.PinE.High() time.Sleep(dataStrobeTimeout) // Wait status flag drop ok := false d.busInput() // Set bus to input for counter := 0; counter < maxWaitCycles; counter++ { if d.PinDB7.Read() != rpio.High { //d.logger.Printf("BUS:%d%d%d%d%d%d%d%d\n", d.pinDB0.Read(), d.pinDB1.Read(), d.pinDB2.Read(), d.pinDB3.Read(), d.pinDB4.Read(), d.pinDB5.Read(), d.pinDB6.Read(), d.pinDB7.Read()) ok = true break } } if !ok { return fmt.Errorf("busy timeout") } // Strobe end d.PinE.Low() time.Sleep(time.Millisecond - dataStrobeTimeout - adressWriteTimeout) // d.logger.Println("Ready") return nil } // Set bus pins to output func (d *device) busOutput() { // if d.isBusOutput { // return // } d.PinDB0.Output() d.PinDB1.Output() d.PinDB2.Output() d.PinDB3.Output() d.PinDB4.Output() d.PinDB5.Output() d.PinDB6.Output() d.PinDB7.Output() d.isBusOutput = true } func (d *device) busInput() { //if !d.isBusOutput { // return //} d.PinDB0.Input() d.PinDB1.Input() d.PinDB2.Input() d.PinDB3.Input() d.PinDB4.Input() d.PinDB5.Input() d.PinDB6.Input() d.PinDB7.Input() d.isBusOutput = false }