package parallel8bit import ( "fmt" "log" "time" "github.com/stianeikeland/go-rpio/v4" ) const ( adressWriteTimeout = 50 * time.Nanosecond // 40 dataStrobeTimeout = 200 * time.Nanosecond // (Data transfer) 160 dataReadTimeout = 400 * time.Nanosecond // 300 gapTimeout = 2000 * time.Nanosecond // TIM // 2000 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 } 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.busOutput() d.PinA0.Low() d.PinRW.Low() d.PinE.High() d.PinDB0.Low() d.PinDB1.Low() d.PinDB2.Low() d.PinDB3.Low() d.PinDB4.Low() d.PinDB5.Low() d.PinDB6.Low() d.PinDB7.Low() } func (d *device) WriteByte(b byte, cd rpio.State) { 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)) time.Sleep(adressWriteTimeout) d.PinE.Low() // Strobe start time.Sleep(dataStrobeTimeout) d.PinE.High() // Strobe end time.Sleep(gapTimeout - dataStrobeTimeout - adressWriteTimeout) } func (d *device) WriteBytes(b []byte, cd rpio.State) { 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])) time.Sleep(adressWriteTimeout) d.PinE.Low() // Strobe start time.Sleep(dataStrobeTimeout) d.PinE.High() // Strobe end time.Sleep(gapTimeout - dataStrobeTimeout - adressWriteTimeout) } func (d *device) ReadByte(cd rpio.State) byte { // Setup var b byte d.PinA0.Write(cd) d.PinRW.High() // We read d.busInput() // Strobe start time.Sleep(adressWriteTimeout) d.PinE.Low() time.Sleep(dataReadTimeout) // 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.High() time.Sleep(gapTimeout - dataReadTimeout - adressWriteTimeout) return b } func (d *device) WaitReady() error { d.busInput() // Set bus to input d.PinA0.Low() // Status d.PinRW.High() // We read time.Sleep(adressWriteTimeout) // Strobe start d.PinE.Low() time.Sleep(dataReadTimeout) // Wait status flag drop ok := false 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 } fmt.Print(".") } if !ok { return fmt.Errorf("busy timeout") } // Strobe end d.PinE.High() time.Sleep(gapTimeout - dataReadTimeout - 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 }