tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/pcd8544/pcd8544.go (about) 1 // Package pcd8544 implements a driver for the PCD8544 48x84 pixels matrix LCD, used in Nokia's 5110 and 3310 phones. 2 // 3 // Datasheet: http://eia.udg.edu/~forest/PCD8544_1.pdf 4 package pcd8544 // import "tinygo.org/x/drivers/pcd8544" 5 6 import ( 7 "errors" 8 "image/color" 9 "machine" 10 "time" 11 12 "tinygo.org/x/drivers" 13 ) 14 15 // Device wraps an SPI connection. 16 type Device struct { 17 bus drivers.SPI 18 dcPin machine.Pin 19 rstPin machine.Pin 20 scePin machine.Pin 21 buffer []byte 22 width int16 23 height int16 24 bufferSize int16 25 } 26 27 type Config struct { 28 Width int16 29 Height int16 30 } 31 32 // New creates a new PCD8544 connection. The SPI bus must already be configured. 33 func New(bus drivers.SPI, dcPin, rstPin, scePin machine.Pin) *Device { 34 return &Device{ 35 bus: bus, 36 dcPin: dcPin, 37 rstPin: rstPin, 38 scePin: scePin, 39 } 40 } 41 42 // Configure initializes the display with default configuration 43 func (d *Device) Configure(cfg Config) { 44 if cfg.Width != 0 { 45 d.width = cfg.Width 46 } else { 47 d.width = 84 48 } 49 if cfg.Height != 0 { 50 d.height = cfg.Height 51 } else { 52 d.height = 48 53 } 54 d.bufferSize = d.width * d.height / 8 55 d.buffer = make([]byte, d.bufferSize) 56 57 d.rstPin.Low() 58 time.Sleep(100 * time.Nanosecond) 59 d.rstPin.High() 60 d.SendCommand(FUNCTIONSET | EXTENDEDINSTRUCTION) // H = 1 61 d.SendCommand(SETVOP | 0x3f) // 0x3f : Vop6 = 0, Vop5 to Vop0 = 1 62 d.SendCommand(SETTEMP | 0x03) // Experimentally determined 63 d.SendCommand(SETBIAS | 0x03) // Experimentally determined 64 d.SendCommand(FUNCTIONSET) // H = 0 65 d.SendCommand(DISPLAYCONTROL | DISPLAYNORMAL) 66 } 67 68 // ClearBuffer clears the image buffer 69 func (d *Device) ClearBuffer() { 70 d.buffer = make([]byte, d.bufferSize) 71 } 72 73 // ClearDisplay clears the image buffer and clear the display 74 func (d *Device) ClearDisplay() { 75 d.ClearBuffer() 76 d.Display() 77 } 78 79 // Display sends the whole buffer to the screen 80 func (d *Device) Display() error { 81 d.SendCommand(FUNCTIONSET) // H = 0 82 d.SendCommand(SETXADDR) 83 d.SendCommand(SETYADDR) 84 85 for i := int16(0); i < d.bufferSize; i++ { 86 d.SendData(d.buffer[i]) 87 } 88 return nil 89 } 90 91 // sendDataCommand sends image data or a command to the screen 92 func (d *Device) sendDataCommand(isCommand bool, data uint8) { 93 if isCommand { 94 d.dcPin.Low() 95 } else { 96 d.dcPin.High() 97 } 98 d.scePin.Low() 99 d.bus.Transfer(data) 100 d.scePin.High() 101 } 102 103 // SetPixel enables or disables a pixel in the buffer 104 // color.RGBA{0, 0, 0, 255} is consider transparent, anything else 105 // with enable a pixel on the screen 106 func (d *Device) SetPixel(x int16, y int16, c color.RGBA) { 107 if x < 0 || x >= d.width || y < 0 || y >= d.height { 108 return 109 } 110 byteIndex := x + (y/8)*d.width 111 if c.R != 0 || c.G != 0 || c.B != 0 { 112 d.buffer[byteIndex] |= 1 << uint8(y%8) 113 } else { 114 d.buffer[byteIndex] &^= 1 << uint8(y%8) 115 } 116 } 117 118 // GetPixel returns if the specified pixel is on (true) or off (false) 119 func (d *Device) GetPixel(x int16, y int16) bool { 120 if x < 0 || x >= d.width || y < 0 || y >= d.height { 121 return false 122 } 123 byteIndex := x + (y/8)*d.width 124 return (d.buffer[byteIndex] >> uint8(y%8) & 0x1) == 1 125 } 126 127 // SetBuffer changes the whole buffer at once 128 func (d *Device) SetBuffer(buffer []byte) error { 129 if int16(len(buffer)) != d.bufferSize { 130 //return ErrBuffer 131 return errors.New("wrong size buffer") 132 } 133 for i := int16(0); i < d.bufferSize; i++ { 134 d.buffer[i] = buffer[i] 135 } 136 return nil 137 } 138 139 // SendCommand sends a command to the display 140 func (d *Device) SendCommand(command uint8) { 141 d.sendDataCommand(true, command) 142 } 143 144 // SendData sends a data byte to the display 145 func (d *Device) SendData(data uint8) { 146 d.sendDataCommand(false, data) 147 } 148 149 // Size returns the current size of the display. 150 func (d *Device) Size() (w, h int16) { 151 return d.width, d.height 152 }