pi-tm1638  1.0
TM1638 library for Raspberry Pi
 All Data Structures Files Functions Variables Typedefs
tm1638.c
Go to the documentation of this file.
1 
70 #include <stdio.h>
71 #include <stdlib.h>
72 #include <stdint.h>
73 #include <stdbool.h>
74 
75 #include <wiringPi.h>
76 
77 #include "tm1638.h"
78 
85 struct tm1638_tag
86 {
87  uint8_t data;
88  uint8_t clock;
89  uint8_t strobe;
91  uint8_t intensity;
92  bool enable;
93 };
94 
95 static void tm1638_send_raw(const tm1638_p t, uint8_t x);
96 static uint8_t tm1638_receive_raw(const tm1638_p t);
97 static void tm1638_send_command(const tm1638_p t, uint8_t x);
98 static void tm1638_send_data(const tm1638_p t, uint8_t addr, uint8_t data);
99 static void tm1638_send_config(const tm1638_p t);
100 static uint8_t tm1638_calc_config(const tm1638_p t);
101 
102 /* See tm1638.h */
103 tm1638_p tm1638_alloc(uint8_t data, uint8_t clock, uint8_t strobe)
104 {
105  /* The delays in this code are somewhat arbitrary: they work for me
106  but I make no claims that they are optimal or robust */
107 
108  tm1638_p t = malloc(sizeof(tm1638));
109  if (!t)
110  return NULL;
111 
112  t->data = data;
113  t->clock = clock;
114  t->strobe = strobe;
115 
116  t->intensity = 7;
117  t->enable = true;
118 
119  pinMode(t->data, OUTPUT);
120  pinMode(t->clock, OUTPUT);
121  pinMode(t->strobe, OUTPUT);
122 
123  digitalWrite(t->strobe, HIGH);
124  digitalWrite(t->clock, HIGH);
125  delayMicroseconds(1);
126 
128 
129  tm1638_send_cls(t);
130 
131  return t;
132 }
133 
134 /* See tm1638.h */
136 {
137  free(*t);
138  *t = NULL;
139 }
140 
141 /* See tm1638.h */
142 void tm1638_enable(tm1638_p t, bool enable)
143 {
144  t->enable = enable;
146 }
147 
148 /* See tm1638.h */
149 void tm1638_set_intensity(tm1638_p t, uint8_t intensity)
150 {
151  /* maximum intensity is 7 */
152  if (intensity > 7)
153  intensity = 7;
154 
155  t->intensity = intensity;
156 
158 }
159 
166 static void tm1638_send_config(const tm1638_p t)
167 {
169 }
170 
179 static uint8_t tm1638_calc_config(const tm1638_p t)
180 {
181  return 0x80 | (t->enable ? 8 : 0) | t->intensity;
182 }
183 
191 static void tm1638_send_raw(const tm1638_p t, uint8_t x)
192 {
193  /* The delays in this code are somewhat arbitrary: they work for me
194  but I make no claims that they are optimal or robust */
195  for(int i = 0; i < 8; i++)
196  {
197  digitalWrite(t->clock, LOW);
198  delayMicroseconds(1);
199 
200  digitalWrite(t->data, x & 1 ? HIGH : LOW);
201  delayMicroseconds(1);
202 
203  x >>= 1;
204  digitalWrite(t->clock, HIGH);
205  delayMicroseconds(1);
206  }
207 }
208 
217 static uint8_t tm1638_receive_raw(const tm1638_p t)
218 {
219  /* The delays in this code are somewhat arbitrary: they work for me
220  but I make no claims that they are optimal or robust */
221 
222  uint8_t x = 0;
223 
224  /* Turn GPIO pin into an input */
225  pinMode (t->data, INPUT);
226 
227  for(int i = 0; i < 8; i++)
228  {
229  x <<= 1;
230 
231  digitalWrite(t->clock, LOW);
232  delayMicroseconds(1);
233 
234  uint8_t y = digitalRead(t->data);
235 
236  if (y & 1)
237  x |= 1;
238  delayMicroseconds(1);
239 
240  digitalWrite(t->clock, HIGH);
241  delayMicroseconds(1);
242  }
243 
244  /* Turn GPIO pin back into an output */
245  pinMode (t->data, OUTPUT);
246 
247  return x;
248 }
249 
257 static void tm1638_send_command(const tm1638_p t, uint8_t x)
258 {
259  /* The delays in this code are somewhat arbitrary: they work for me
260  but I make no claims that they are optimal or robust */
261  digitalWrite(t->strobe, LOW);
262  delayMicroseconds(1);
263 
264  tm1638_send_raw(t, x);
265 
266  digitalWrite(t->strobe, HIGH);
267  delayMicroseconds(1);
268 }
269 
278 static void tm1638_send_data(const tm1638_p t, uint8_t addr, uint8_t data)
279 {
280  /* The delays in this code are somewhat arbitrary: they work for me
281  but I make no claims that they are optimal or robust */
282  tm1638_send_command(t, 0x44);
283 
284  digitalWrite(t->strobe, LOW);
285  delayMicroseconds(1);
286 
287  tm1638_send_raw(t, 0xc0 | addr);
288  tm1638_send_raw(t, data);
289 
290  digitalWrite(t->strobe, HIGH);
291  delayMicroseconds(1);
292 }
293 
294 /* See tm1638.h */
295 void tm1638_set_7seg_raw(const tm1638_p t, uint8_t digit, uint8_t n)
296 {
297  tm1638_send_data(t, digit << 1, n);
298 }
299 
300 /* See tm1638.h */
301 void tm1638_set_7seg_text(const tm1638_p t, const char *str, uint8_t dots)
302 {
303  const char *p = str;
304 
305  for(int i = 0, j = 1; i < 8; i++, j <<= 1)
306  {
307  // We want the loop to finish, but don't walk over the end of the string
308  char c = *p;
309  if (c)
310  p++;
311 
312  uint8_t f = tm1638_font(c);
313 
314  if (dots & j)
315  f |= 128;
316 
317  tm1638_set_7seg_raw(t, i, f);
318  }
319 }
320 
321 /* See tm1638.h */
322 void tm1638_set_led(const tm1638_p t, uint8_t led, uint8_t cols)
323 {
324  tm1638_send_data(t, (led << 1) + 1, cols);
325 }
326 
327 /* See tm1638.h */
328 void tm1638_set_8leds(const tm1638_p t, uint8_t red)
329 {
330  for(int i = 0, j = 128; i < 8; i++, j >>= 1)
331  tm1638_set_led(t, i, (red & j) ? 1 : 0);
332 }
333 
334 /* See tm1638.h */
336 {
337  /* The delays in this code are somewhat arbitrary: they work for me
338  but I make no claims that they are optimal or robust */
339  tm1638_send_command(t, 0x40);
340 
341  digitalWrite(t->strobe, LOW);
342  delayMicroseconds(1);
343 
344  tm1638_send_raw(t, 0xc0);
345  for(int i = 0; i < 16; i++)
346  tm1638_send_raw(t, 0x00);
347 
348  digitalWrite(t->strobe, HIGH);
349  delayMicroseconds(1);
350 }
351 
352 /* See tm1638.h */
353 uint8_t tm1638_font(char c)
354 {
355  const uint8_t f[] = {
356  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
357  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
358  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
360  0x00, 0x86, 0x22, 0x7e, 0x6d, 0x00, 0x00, 0x02,
361  0x30, 0x06, 0x63, 0x00, 0x04, 0x40, 0x80, 0x52,
362  0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x27,
363  0x7f, 0x6f, 0x00, 0x00, 0x00, 0x48, 0x00, 0x53,
364  0x5f, 0x77, 0x7f, 0x39, 0x3f, 0x79, 0x71, 0x3d,
365  0x76, 0x06, 0x1f, 0x69, 0x38, 0x15, 0x37, 0x3f,
366  0x73, 0x67, 0x31, 0x6d, 0x78, 0x3e, 0x2a, 0x1d,
367  0x76, 0x6e, 0x5b, 0x39, 0x64, 0x0f, 0x00, 0x08,
368  0x20, 0x5f, 0x7c, 0x58, 0x5e, 0x7b, 0x31, 0x6f,
369  0x74, 0x04, 0x0e, 0x75, 0x30, 0x55, 0x54, 0x5c,
370  0x73, 0x67, 0x50, 0x6d, 0x78, 0x1c, 0x2a, 0x1d,
371  0x76, 0x6e, 0x47, 0x46, 0x06, 0x70, 0x01, 0x00
372  };
373 
374  return (c > 127) ? 0 : f[(unsigned char)c];
375 }
376 
377 /* See tm1638.h */
378 uint32_t tm1638_read_buttons(const tm1638_p t)
379 {
380  /* The delays in this code are somewhat arbitrary: they work for me
381  but I make no claims that they are optimal or robust */
382  digitalWrite(t->strobe, LOW);
383  delayMicroseconds(1);
384 
385  tm1638_send_raw(t, 0x42);
386 
387  uint32_t x = 0;
388  for(int i = 0; i < 4; i++)
389  {
390  x <<= 8;
391  x |= tm1638_receive_raw(t);
392  }
393 
394  digitalWrite(t->strobe, HIGH);
395  delayMicroseconds(1);
396 
397  return x;
398 }
399 
400 /* See tm1638.h */
402 {
403  uint32_t x = tm1638_read_buttons(t);
404  uint8_t y = 0;
405 
406  for(int i = 0; i < 4; i++)
407  {
408  y <<= 1;
409 
410  if (x & 0x80000000)
411  y |= 0x10;
412 
413  if (x & 0x08000000)
414  y |= 0x01;
415 
416  x <<= 8;
417  }
418 
419  return y;
420 }
421 
void tm1638_set_7seg_text(const tm1638_p t, const char *str, uint8_t dots)
Definition: tm1638.c:301
static void tm1638_send_config(const tm1638_p t)
Definition: tm1638.c:166
uint32_t tm1638_read_buttons(const tm1638_p t)
Definition: tm1638.c:378
tm1638_p tm1638_alloc(uint8_t data, uint8_t clock, uint8_t strobe)
Definition: tm1638.c:103
uint8_t intensity
Definition: tm1638.c:91
static void tm1638_send_data(const tm1638_p t, uint8_t addr, uint8_t data)
Definition: tm1638.c:278
uint8_t data
Definition: tm1638.c:87
bool enable
Definition: tm1638.c:92
void tm1638_free(tm1638_p *t)
Definition: tm1638.c:135
void tm1638_set_7seg_raw(const tm1638_p t, uint8_t digit, uint8_t n)
Definition: tm1638.c:295
void tm1638_send_cls(const tm1638_p t)
Definition: tm1638.c:335
static void tm1638_send_raw(const tm1638_p t, uint8_t x)
Definition: tm1638.c:191
void tm1638_set_led(const tm1638_p t, uint8_t led, uint8_t cols)
Definition: tm1638.c:322
void tm1638_set_8leds(const tm1638_p t, uint8_t red)
Definition: tm1638.c:328
static uint8_t tm1638_receive_raw(const tm1638_p t)
Definition: tm1638.c:217
void tm1638_set_intensity(tm1638_p t, uint8_t intensity)
Definition: tm1638.c:149
uint8_t clock
Definition: tm1638.c:88
uint8_t tm1638_read_8buttons(const tm1638_p t)
Definition: tm1638.c:401
uint8_t tm1638_font(char c)
Definition: tm1638.c:353
static void tm1638_send_command(const tm1638_p t, uint8_t x)
Definition: tm1638.c:257
void tm1638_enable(tm1638_p t, bool enable)
Definition: tm1638.c:142
uint8_t strobe
Definition: tm1638.c:89
A simple interface to TM1638 based displays for the Raspberry Pi.
static uint8_t tm1638_calc_config(const tm1638_p t)
Definition: tm1638.c:179