gobot.io/x/gobot/v2@v2.1.0/drivers/gpio/tm1638_driver.go (about)

     1  package gpio
     2  
     3  import (
     4  	"math"
     5  
     6  	"strings"
     7  
     8  	"gobot.io/x/gobot/v2"
     9  )
    10  
    11  // Colors of the display
    12  const (
    13  	TM1638None = iota
    14  	TM1638Red
    15  	TM1638Green
    16  )
    17  
    18  // Commands of the driver
    19  const (
    20  	TM1638DataCmd  = 0x40
    21  	TM1638DispCtrl = 0x80
    22  	TM1638AddrCmd  = 0xC0
    23  
    24  	TM1638WriteDisp = 0x00
    25  	TM1638ReadKeys  = 0x02
    26  	TM1638FixedAddr = 0x04
    27  )
    28  
    29  // TM1638Driver is the gobot driver for modules based on the TM1638, which has 8 7-segment displays, 8 LEDs and 8 buttons
    30  // Buttons are not supported
    31  //
    32  // Datasheet EN: https://retrocip.cz/files/tm1638.pdf
    33  // Datasheet CN: http://www.datasheetspdf.com/pdf/775356/TitanMicro/TM1638/1
    34  //
    35  // Ported from the Arduino driver https://github.com/rjbatista/tm1638-library
    36  type TM1638Driver struct {
    37  	pinClock   *DirectPinDriver
    38  	pinData    *DirectPinDriver
    39  	pinStrobe  *DirectPinDriver
    40  	fonts      map[string]byte
    41  	name       string
    42  	connection gobot.Connection
    43  	gobot.Commander
    44  }
    45  
    46  // NewTM1638Driver return a new TM1638Driver given a gobot.Connection and the clock, data and strobe pins
    47  func NewTM1638Driver(a gobot.Connection, clockPin string, dataPin string, strobePin string) *TM1638Driver {
    48  	t := &TM1638Driver{
    49  		name:       gobot.DefaultName("TM1638"),
    50  		pinClock:   NewDirectPinDriver(a, clockPin),
    51  		pinData:    NewDirectPinDriver(a, dataPin),
    52  		pinStrobe:  NewDirectPinDriver(a, strobePin),
    53  		fonts:      NewTM1638Fonts(),
    54  		connection: a,
    55  		Commander:  gobot.NewCommander(),
    56  	}
    57  
    58  	/* TODO : Add commands */
    59  
    60  	return t
    61  }
    62  
    63  // Start initializes the tm1638, it uses a SPI-like communication protocol
    64  func (t *TM1638Driver) Start() (err error) {
    65  
    66  	t.pinStrobe.On()
    67  	t.pinClock.On()
    68  
    69  	t.sendCommand(TM1638DataCmd)
    70  	t.sendCommand(TM1638DispCtrl | 8 | 7)
    71  
    72  	t.pinStrobe.Off()
    73  	t.send(TM1638AddrCmd)
    74  	for i := 0; i < 16; i++ {
    75  		t.send(TM1638WriteDisp)
    76  	}
    77  	t.pinStrobe.On()
    78  
    79  	return
    80  }
    81  
    82  // Halt implements the Driver interface
    83  func (t *TM1638Driver) Halt() (err error) { return }
    84  
    85  // Name returns the TM1638Drivers name
    86  func (t *TM1638Driver) Name() string { return t.name }
    87  
    88  // SetName sets the TM1638Drivers name
    89  func (t *TM1638Driver) SetName(n string) { t.name = n }
    90  
    91  // Connection returns the TM1638Driver Connection
    92  func (t *TM1638Driver) Connection() gobot.Connection {
    93  	return t.connection
    94  }
    95  
    96  // sendCommand is an auxiliary function to send commands to the TM1638 module
    97  func (t *TM1638Driver) sendCommand(cmd byte) {
    98  	t.pinStrobe.Off()
    99  	t.send(cmd)
   100  	t.pinStrobe.On()
   101  }
   102  
   103  // send writes data on the module
   104  func (t *TM1638Driver) send(data byte) {
   105  	for i := 0; i < 8; i++ {
   106  		t.pinClock.Off()
   107  
   108  		if (data & 1) > 0 {
   109  			t.pinData.On()
   110  		} else {
   111  			t.pinData.Off()
   112  		}
   113  		data >>= 1
   114  
   115  		t.pinClock.On()
   116  	}
   117  }
   118  
   119  // sendData is an auxiliary function to send data to the TM1638 module
   120  func (t *TM1638Driver) sendData(address byte, data byte) {
   121  	t.sendCommand(TM1638DataCmd | TM1638FixedAddr)
   122  	t.pinStrobe.Off()
   123  	t.send(TM1638AddrCmd | address)
   124  	t.send(data)
   125  	t.pinStrobe.On()
   126  }
   127  
   128  // SetLED changes the color (TM1638None, TM1638Red, TM1638Green) of the specific LED
   129  func (t *TM1638Driver) SetLED(color byte, pos byte) {
   130  	if pos > 7 {
   131  		return
   132  	}
   133  	t.sendData((pos<<1)+1, color)
   134  }
   135  
   136  // SetDisplay cuts and sends a byte array to the display (without dots)
   137  func (t *TM1638Driver) SetDisplay(data []byte) {
   138  	minLength := int(math.Min(8, float64(len(data))))
   139  	for i := 0; i < minLength; i++ {
   140  		t.SendChar(byte(i), data[i], false)
   141  	}
   142  }
   143  
   144  // SetDisplayText cuts and sends a string to the display (without dots)
   145  func (t *TM1638Driver) SetDisplayText(text string) {
   146  	data := t.fromStringToByteArray(text)
   147  	minLength := int(math.Min(8, float64(len(data))))
   148  	for i := 0; i < minLength; i++ {
   149  		t.SendChar(byte(i), data[i], false)
   150  	}
   151  }
   152  
   153  // SendChar sends one byte to the specific position in the display
   154  func (t *TM1638Driver) SendChar(pos byte, data byte, dot bool) {
   155  	if pos > 7 {
   156  		return
   157  	}
   158  	var dotData byte
   159  	if dot {
   160  		dotData = TM1638DispCtrl
   161  	}
   162  	t.sendData(pos<<1, data|(dotData))
   163  }
   164  
   165  // fromStringToByteArray translates a string to a byte array with the corresponding representation for the 7-segment LCD, return and empty character if the font is not available
   166  func (t *TM1638Driver) fromStringToByteArray(str string) []byte {
   167  	chars := strings.Split(str, "")
   168  	data := make([]byte, len(chars))
   169  
   170  	for index, char := range chars {
   171  		if val, ok := t.fonts[char]; ok {
   172  			data[index] = val
   173  		}
   174  	}
   175  	return data
   176  }
   177  
   178  // AddFonts adds new custom fonts or modify the representation of existing ones
   179  func (t *TM1638Driver) AddFonts(fonts map[string]byte) {
   180  	for k, v := range fonts {
   181  		t.fonts[k] = v
   182  	}
   183  }
   184  
   185  // ClearFonts removes all the fonts from the driver
   186  func (t *TM1638Driver) ClearFonts() {
   187  	t.fonts = make(map[string]byte)
   188  }
   189  
   190  // NewTM1638Fonts returns a map with fonts and their corresponding byte for proper representation on the 7-segment LCD
   191  func NewTM1638Fonts() map[string]byte {
   192  	return map[string]byte{
   193  		" ":  0x00,
   194  		"!":  0x86,
   195  		"'":  0x22,
   196  		"#":  0x7E,
   197  		"$":  0x6D,
   198  		"%":  0x00,
   199  		"&":  0x00,
   200  		"\"": 0x02,
   201  		"(":  0x30,
   202  		")":  0x06,
   203  		"*":  0x63,
   204  		"+":  0x00,
   205  		",":  0x04,
   206  		"-":  0x40,
   207  		".":  0x80,
   208  		"/":  0x52,
   209  		"0":  0x3F,
   210  		"1":  0x06,
   211  		"2":  0x5B,
   212  		"3":  0x4F,
   213  		"4":  0x66,
   214  		"5":  0x6D,
   215  		"6":  0x7D,
   216  		"7":  0x27,
   217  		"8":  0x7F,
   218  		"9":  0x6F,
   219  		":":  0x00,
   220  		";":  0x00,
   221  		"<":  0x00,
   222  		"=":  0x48,
   223  		">":  0x00,
   224  		"?":  0x53,
   225  		"@":  0x5F,
   226  		"A":  0x77,
   227  		"B":  0x7F,
   228  		"C":  0x39,
   229  		"D":  0x3F,
   230  		"E":  0x79,
   231  		"F":  0x71,
   232  		"G":  0x3D,
   233  		"H":  0x76,
   234  		"I":  0x06,
   235  		"J":  0x1F,
   236  		"K":  0x69,
   237  		"L":  0x38,
   238  		"M":  0x15,
   239  		"N":  0x37,
   240  		"O":  0x3F,
   241  		"P":  0x73,
   242  		"Q":  0x67,
   243  		"R":  0x31,
   244  		"S":  0x6D,
   245  		"T":  0x78,
   246  		"U":  0x3E,
   247  		"V":  0x2A,
   248  		"W":  0x1D,
   249  		"X":  0x76,
   250  		"Y":  0x6E,
   251  		"Z":  0x5B,
   252  		"[":  0x39,
   253  		"\\": 0x64, // (this can't be the last char on a line, even in comment or it'll concat)
   254  		"]":  0x0F,
   255  		"^":  0x00,
   256  		"_":  0x08,
   257  		"`":  0x20,
   258  		"a":  0x5F,
   259  		"b":  0x7C,
   260  		"c":  0x58,
   261  		"d":  0x5E,
   262  		"e":  0x7B,
   263  		"f":  0x31,
   264  		"g":  0x6F,
   265  		"h":  0x74,
   266  		"i":  0x04,
   267  		"j":  0x0E,
   268  		"k":  0x75,
   269  		"l":  0x30,
   270  		"m":  0x55,
   271  		"n":  0x54,
   272  		"o":  0x5C,
   273  		"p":  0x73,
   274  		"q":  0x67,
   275  		"r":  0x50,
   276  		"s":  0x6D,
   277  		"t":  0x78,
   278  		"u":  0x1C,
   279  		"v":  0x2A,
   280  		"w":  0x1D,
   281  		"x":  0x76,
   282  		"y":  0x6E,
   283  		"z":  0x47,
   284  		"{":  0x46,
   285  		"|":  0x06,
   286  		"}":  0x70,
   287  		"~":  0x01,
   288  	}
   289  }