gobot.io/x/gobot@v1.16.0/drivers/gpio/tm1638_driver.go (about)

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