tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/ssd1289/ssd1289.go (about)

     1  // Package ssd1289 implements a driver for the SSD1289 led matrix controller as packaged on the TFT_320QVT board
     2  //
     3  // Datasheet: http://aitendo3.sakura.ne.jp/aitendo_data/product_img/lcd/tft2/M032C1289TP/3.2-SSD1289.pdf
     4  package ssd1289
     5  
     6  import (
     7  	"image/color"
     8  	"machine"
     9  	"time"
    10  )
    11  
    12  type Bus interface {
    13  	Set(data uint16)
    14  }
    15  
    16  type Device struct {
    17  	rs  machine.Pin
    18  	wr  machine.Pin
    19  	cs  machine.Pin
    20  	rst machine.Pin
    21  	bus Bus
    22  }
    23  
    24  const width = int16(240)
    25  const height = int16(320)
    26  
    27  func New(rs machine.Pin, wr machine.Pin, cs machine.Pin, rst machine.Pin, bus Bus) Device {
    28  	d := Device{
    29  		rs:  rs,
    30  		wr:  wr,
    31  		cs:  cs,
    32  		rst: rst,
    33  		bus: bus,
    34  	}
    35  
    36  	rs.Configure(machine.PinConfig{Mode: machine.PinOutput})
    37  	wr.Configure(machine.PinConfig{Mode: machine.PinOutput})
    38  	cs.Configure(machine.PinConfig{Mode: machine.PinOutput})
    39  	rst.Configure(machine.PinConfig{Mode: machine.PinOutput})
    40  
    41  	cs.High()
    42  	rst.High()
    43  	wr.High()
    44  
    45  	return d
    46  }
    47  
    48  func (d *Device) lcdWriteCom(cmd Command) {
    49  	d.rs.Low()
    50  	d.lcdWriteBusInt(uint16(cmd))
    51  }
    52  
    53  func (d *Device) lcdWriteDataInt(data uint16) {
    54  	d.rs.High()
    55  	d.lcdWriteBusInt(data)
    56  }
    57  
    58  func (d *Device) lcdWriteComData(cmd Command, data uint16) {
    59  	d.lcdWriteCom(cmd)
    60  	d.lcdWriteDataInt(data)
    61  }
    62  
    63  func (d *Device) tx() {
    64  	d.wr.Low()
    65  	d.wr.High()
    66  }
    67  
    68  func (d *Device) lcdWriteBusInt(data uint16) {
    69  	d.bus.Set(data)
    70  	d.tx()
    71  }
    72  
    73  func (d *Device) Configure() {
    74  	d.rst.High()
    75  	time.Sleep(time.Millisecond * 5)
    76  	d.rst.Low()
    77  	time.Sleep(time.Millisecond * 15)
    78  	d.rst.High()
    79  	time.Sleep(time.Millisecond * 15)
    80  	d.cs.Low()
    81  
    82  	//Power supply setting
    83  	d.lcdWriteComData(POWERCONTROL1, 0xA8A4)
    84  	d.lcdWriteComData(POWERCONTROL2, 0x0000)
    85  	d.lcdWriteComData(POWERCONTROL3, 0x080C)
    86  	d.lcdWriteComData(POWERCONTROL4, 0x2B00)
    87  	d.lcdWriteComData(POWERCONTROL5, 0x00B7)
    88  
    89  	//Set R07h at 0021h
    90  	d.lcdWriteComData(DISPLAYCONTROL, 0x021)
    91  
    92  	//Set R00h at 0001h
    93  	d.lcdWriteComData(OSCILLATIONSTART, 0x0001)
    94  
    95  	//Set R07h at 0021h
    96  	d.lcdWriteComData(DISPLAYCONTROL, 0x023)
    97  
    98  	//Set R10h at 0000h, Exit sleep mode
    99  	d.lcdWriteComData(SLEEPMODE, 0x0000)
   100  
   101  	//Wait 30ms
   102  	time.Sleep(time.Millisecond * 30)
   103  
   104  	//Set R07h at 0033h
   105  	d.lcdWriteComData(DISPLAYCONTROL, 0x033)
   106  
   107  	//Entry Mode setting (R11h)
   108  	//DFM   11 --> 65k
   109  	//TRANS  0
   110  	//OEDEF  0
   111  	//WMODE  0 --> Normal data bus
   112  	//DMODE 00 --> Ram
   113  	//TY    01 --> 262k Type A not used as we are in 65k mode.
   114  	//ID    11 --> Horizontal & Vertical increment
   115  	//AM     0 --> Horizontal
   116  	//LG   000 --> No compare register usage
   117  	d.lcdWriteComData(ENTRYMODE, 0x6030)
   118  
   119  	//LCD Driver AC Setting
   120  	//I couldn't make sense of the documentation fortunately 0 seems to
   121  	//FLD 0 --> Normal driving
   122  	//ENWS 0 --> POR mode
   123  	//BC   1 --> Less flicker
   124  	//EOR  1 --> Less stripey
   125  	//WSMD 0 --> not used in POR mode
   126  	//NW   0 --> Least flicker
   127  	d.lcdWriteComData(LCDDRIVEACCONTROL, 0x0600)
   128  
   129  	//End of documented init
   130  
   131  	//RL    0 --> Output shift direction
   132  	//REV   1 --> Reverse colors
   133  	//CAD   0 --> Cs on common
   134  	//BGR   0 --> use RGB color assignment
   135  	//SM    0 --> standard gate scan sequence
   136  	//TB    1 --> Display is mirrored with 0
   137  	//MUX 319 --> Number of lines in display
   138  	d.lcdWriteComData(DRIVEROUTPUTCONTROL, 0x233F)
   139  
   140  	d.cs.High()
   141  
   142  }
   143  
   144  func (d *Device) setXY(x1 uint16, y1 uint16, x2 uint16, y2 uint16) {
   145  	d.lcdWriteComData(HORIZONTALRAMADDRESSPOSITION, (x2<<8)+x1)
   146  	d.lcdWriteComData(VERTICALRAMADDRESSSTARTPOSITION, y1)
   147  	d.lcdWriteComData(VERTICALRAMADDRESSENDPOSITION, y2)
   148  	d.lcdWriteComData(SETGDDRAMXADDRESSCOUNTER, x1)
   149  	d.lcdWriteComData(SETGDDRAMYADDRESSCOUNTER, y1)
   150  	d.lcdWriteCom(RAMDATAREADWRITE)
   151  }
   152  
   153  func (d *Device) ClearDisplay() {
   154  	d.FillDisplay(color.RGBA{0, 0, 0, 255})
   155  }
   156  
   157  func (d *Device) FillDisplay(c color.RGBA) {
   158  	d.FillRect(0, 0, width, height, c)
   159  }
   160  
   161  func encodeColor(c color.RGBA) uint16 {
   162  	encoded := (uint16(c.B)&248)<<8 | (uint16(c.G)&252)<<3 | (uint16(c.R)&248)>>3
   163  	return encoded
   164  }
   165  
   166  func (d *Device) SetPixel(x, y int16, c color.RGBA) {
   167  
   168  	encoded := encodeColor(c)
   169  
   170  	d.cs.Low()
   171  	d.setXY(uint16(x), uint16(y), uint16(x), uint16(y))
   172  	d.rs.High()
   173  	d.lcdWriteBusInt(encoded)
   174  	d.cs.High()
   175  }
   176  
   177  func (d *Device) FillRect(x, y, w, h int16, c color.RGBA) {
   178  	encoded := encodeColor(c)
   179  
   180  	d.cs.Low()
   181  	d.setXY(uint16(x), uint16(y), uint16(x+(w-1)), uint16(y+(h-1)))
   182  	d.rs.High()
   183  	d.bus.Set(encoded)
   184  	for i := int64(0); i < int64(w)*int64(h); i++ {
   185  		d.tx()
   186  	}
   187  	d.cs.High()
   188  	d.rs.Low()
   189  
   190  }
   191  
   192  func (d *Device) Display() error {
   193  	//Not enough memory to store an entire screen on most microcontrollers
   194  	return nil
   195  }
   196  
   197  func (d *Device) Size() (x, y int16) {
   198  	return width, height
   199  }