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 }