tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/tm1637/tm1637.go (about) 1 // Package tm1637 provides a driver for the TM1637 4-digit 7-segment LED display. 2 // 3 // Datasheet: https://www.mcielectronics.cl/website_MCI/static/documents/Datasheet_TM1637.pdf 4 package tm1637 5 6 import ( 7 "machine" 8 "time" 9 ) 10 11 // Device wraps the pins of the TM1637. 12 type Device struct { 13 clk machine.Pin 14 dio machine.Pin 15 brightness uint8 16 } 17 18 // New creates a new TM1637 device. 19 func New(clk machine.Pin, dio machine.Pin, brightness uint8) Device { 20 return Device{clk: clk, dio: dio, brightness: brightness} 21 } 22 23 // Configure sets up the pins. 24 func (d *Device) Configure() { 25 pinMode(d.clk, false) 26 pinMode(d.dio, false) 27 d.clk.Low() // required for future pull-down 28 d.dio.Low() // required for future pull-down 29 } 30 31 // Brightness sets the brightness of the display (0-7). 32 func (d *Device) Brightness(brightness uint8) { 33 if brightness > 7 { 34 brightness = 7 35 } 36 d.brightness = brightness 37 d.writeCmd() 38 d.writeDsp() 39 } 40 41 // ClearDisplay clears the display. 42 func (d *Device) ClearDisplay() { 43 d.writeData([]byte{0, 0, 0, 0}, 0) 44 } 45 46 // DisplayText shows a text on the display. 47 // 48 // Only the first 4 letters in the array text would be shown. 49 func (d *Device) DisplayText(text []byte) { 50 var sequences []byte 51 for i, t := range text { 52 if i > 3 { 53 break 54 } 55 sequences = append(sequences, encodeChr(t)) 56 } 57 d.writeData(sequences, 0) 58 } 59 60 // DisplayChr shows a single character (A-Z, a-z) 61 // on the display at position 0-3. 62 func (d *Device) DisplayChr(chr byte, pos uint8) { 63 if pos > 3 { 64 pos = 3 65 } 66 d.writeData([]byte{encodeChr(chr)}, pos) 67 } 68 69 // DisplayNumber shows a number on the display. 70 // 71 // Only 4 rightmost digits of the number would be shown. 72 // 73 // For negative numbers, only -999 to -1 would be 74 // shown with a negaive sign. 75 func (d *Device) DisplayNumber(num int16) { 76 var sequences []byte 77 var start int16 78 if num < 0 { 79 sequences = append(sequences, segments[37]) 80 num *= -1 81 start = 100 82 num %= 1000 83 } else { 84 start = 1000 85 num %= 10000 86 } 87 for i := start; i >= 1; i /= 10 { 88 if num >= i { 89 n := (num / int16(i)) % 10 90 sequences = append(sequences, segments[n]) 91 } else { 92 if i == 1 && num == 0 { 93 sequences = append(sequences, segments[0]) 94 } else { 95 sequences = append(sequences, 0) 96 } 97 } 98 } 99 d.writeData(sequences, 0) 100 } 101 102 // DisplayDigit shows a single-digit number (0-9) 103 // at position 0-3. 104 func (d *Device) DisplayDigit(digit uint8, pos uint8) { 105 digit %= 10 106 d.writeData([]byte{segments[digit]}, pos) 107 } 108 109 // DisplayClock allows you to display hour and minute numbers 110 // together with the colon on/off. 111 func (d *Device) DisplayClock(num1 uint8, num2 uint8, colon bool) { 112 var sequences []byte 113 num := []uint8{num1 % 100, num2 % 100} 114 for k := 0; k < 2; k++ { 115 for i := 10; i >= 1; i /= 10 { 116 n := (num[k] / uint8(i)) % 10 117 sequences = append(sequences, segments[n]) 118 } 119 } 120 if colon { 121 sequences[1] |= 1 << 7 122 } 123 d.writeData(sequences, 0) 124 } 125 126 func encodeChr(c byte) byte { 127 r := rune(c) 128 switch { 129 case r == 32: 130 return segments[36] // space 131 case r == 42: 132 return segments[38] // star/degrees 133 case r == 45: 134 return segments[37] // dash 135 case r >= 65 && r <= 90: 136 return segments[r-55] // uppercase A-Z 137 case r >= 97 && r <= 122: 138 return segments[r-87] // lowercase a-z 139 case r >= 48 && r <= 57: 140 return segments[r-48] // 0-9 141 default: 142 return byte(0) 143 } 144 } 145 146 func delaytm() { 147 time.Sleep(time.Microsecond * time.Duration(TM1637_DELAY)) 148 } 149 150 func pinMode(pin machine.Pin, mode bool) { 151 // TM1637 has internal pull-up resistors for both CLK and DIO pins. 152 // Set them to input mode will pull them high, 153 // and set them to output mode will pull them down 154 // (since we did so in the beginning.) 155 // The High()/Low() method don't work on some boards. 156 if mode { 157 pin.Configure(machine.PinConfig{Mode: machine.PinInput}) 158 } else { 159 pin.Configure(machine.PinConfig{Mode: machine.PinOutput}) 160 } 161 } 162 163 func (d *Device) start() { 164 pinMode(d.dio, false) 165 delaytm() 166 pinMode(d.clk, false) 167 } 168 169 func (d *Device) stop() { 170 pinMode(d.dio, false) 171 delaytm() 172 pinMode(d.clk, true) 173 delaytm() 174 pinMode(d.dio, true) 175 } 176 177 func (d *Device) writeByte(data uint8) { 178 for i := 0; i < 8; i++ { 179 pinMode(d.dio, data&(1<<i) > 0) // send bits from LSB to MSB 180 delaytm() 181 pinMode(d.clk, true) 182 delaytm() 183 pinMode(d.clk, false) 184 delaytm() 185 } 186 pinMode(d.clk, false) 187 delaytm() 188 pinMode(d.clk, true) 189 delaytm() 190 pinMode(d.clk, false) 191 } 192 193 func (d *Device) writeCmd() { 194 d.start() 195 d.writeByte(TM1637_CMD1) 196 d.stop() 197 } 198 199 func (d *Device) writeDsp() { 200 d.start() 201 d.writeByte(TM1637_CMD3 | TM1637_DSP_ON | d.brightness) 202 d.stop() 203 } 204 205 func (d *Device) writeData(segments []byte, position uint8) { 206 d.writeCmd() 207 d.start() 208 d.writeByte(TM1637_CMD2 | position) 209 for _, seg := range segments { 210 d.writeByte(seg) 211 } 212 d.stop() 213 d.writeDsp() 214 }