1 /*
2  * Copyright (c) 2019 Henrik Brix Andersen <henrik@brixandersen.dk>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT holtek_ht16k33
8 
9 /**
10  * @file
11  * @brief LED driver for the HT16K33 I2C LED driver with keyscan
12  */
13 
14 #include <zephyr/drivers/gpio.h>
15 #include <zephyr/drivers/i2c.h>
16 #include <zephyr/input/input.h>
17 #include <zephyr/kernel.h>
18 #include <zephyr/drivers/led.h>
19 #include <zephyr/sys/byteorder.h>
20 #include <zephyr/logging/log.h>
21 
22 LOG_MODULE_REGISTER(ht16k33, CONFIG_LED_LOG_LEVEL);
23 
24 #include "led_context.h"
25 
26 /* HT16K33 commands and options */
27 #define HT16K33_CMD_DISP_DATA_ADDR 0x00
28 
29 #define HT16K33_CMD_SYSTEM_SETUP   0x20
30 #define HT16K33_OPT_S              BIT(0)
31 
32 #define HT16K33_CMD_KEY_DATA_ADDR  0x40
33 
34 #define HT16K33_CMD_INT_FLAG_ADDR  0x60
35 
36 #define HT16K33_CMD_DISP_SETUP     0x80
37 #define HT16K33_OPT_D              BIT(0)
38 #define HT16K33_OPT_B0             BIT(1)
39 #define HT16K33_OPT_B1             BIT(2)
40 #define HT16K33_OPT_BLINK_OFF      0
41 #define HT16K33_OPT_BLINK_2HZ      HT16K33_OPT_B0
42 #define HT16K33_OPT_BLINK_1HZ      HT16K33_OPT_B1
43 #define HT16K33_OPT_BLINK_05HZ     (HT16K33_OPT_B1 | HT16K33_OPT_B0)
44 
45 #define HT16K33_CMD_ROW_INT_SET    0xa0
46 #define HT16K33_OPT_ROW_INT        BIT(0)
47 #define HT16K33_OPT_ACT            BIT(1)
48 #define HT16K33_OPT_ROW            0
49 #define HT16K33_OPT_INT_LOW        HT16K33_OPT_ROW_INT
50 #define HT16K33_OPT_INT_HIGH       (HT16K33_OPT_ACT | HT16K33_OPT_ROW_INT)
51 
52 #define HT16K33_CMD_DIMMING_SET    0xe0
53 
54 /* HT16K33 size definitions */
55 #define HT16K33_DISP_ROWS          16
56 #define HT16K33_DISP_COLS          8
57 #define HT16K33_DISP_DATA_SIZE     HT16K33_DISP_ROWS
58 #define HT16K33_DISP_SEGMENTS      (HT16K33_DISP_ROWS * HT16K33_DISP_COLS)
59 #define HT16K33_DIMMING_LEVELS     16
60 #define HT16K33_KEYSCAN_ROWS       3
61 #define HT16K33_KEYSCAN_COLS       13
62 #define HT16K33_KEYSCAN_DATA_SIZE  6
63 
64 struct ht16k33_cfg {
65 	struct i2c_dt_spec i2c;
66 	bool irq_enabled;
67 #ifdef CONFIG_HT16K33_KEYSCAN
68 	struct gpio_dt_spec irq;
69 #endif /* CONFIG_HT16K33_KEYSCAN */
70 };
71 
72 struct ht16k33_data {
73 	const struct device *dev;
74 	struct led_data dev_data;
75 	 /* Shadow buffer for the display data RAM */
76 	uint8_t buffer[HT16K33_DISP_DATA_SIZE];
77 #ifdef CONFIG_HT16K33_KEYSCAN
78 	struct k_mutex lock;
79 	const struct device *child;
80 	struct gpio_callback irq_cb;
81 	struct k_thread irq_thread;
82 	struct k_sem irq_sem;
83 	struct k_timer timer;
84 	uint16_t key_state[HT16K33_KEYSCAN_ROWS];
85 
86 	K_KERNEL_STACK_MEMBER(irq_thread_stack,
87 			      CONFIG_HT16K33_KEYSCAN_IRQ_THREAD_STACK_SIZE);
88 #endif /* CONFIG_HT16K33_KEYSCAN */
89 };
90 
ht16k33_led_blink(const struct device * dev,uint32_t led,uint32_t delay_on,uint32_t delay_off)91 static int ht16k33_led_blink(const struct device *dev, uint32_t led,
92 			     uint32_t delay_on, uint32_t delay_off)
93 {
94 	/* The HT16K33 blinks all LEDs at the same frequency */
95 	ARG_UNUSED(led);
96 
97 	const struct ht16k33_cfg *config = dev->config;
98 	struct ht16k33_data *data = dev->data;
99 	struct led_data *dev_data = &data->dev_data;
100 	uint32_t period;
101 	uint8_t cmd;
102 
103 	period = delay_on + delay_off;
104 	if (period < dev_data->min_period || period > dev_data->max_period) {
105 		return -EINVAL;
106 	}
107 
108 	cmd = HT16K33_CMD_DISP_SETUP | HT16K33_OPT_D;
109 	if (delay_off == 0) {
110 		cmd |= HT16K33_OPT_BLINK_OFF;
111 	} else if (period > 1500)  {
112 		cmd |= HT16K33_OPT_BLINK_05HZ;
113 	} else if (period > 750)  {
114 		cmd |= HT16K33_OPT_BLINK_1HZ;
115 	} else {
116 		cmd |= HT16K33_OPT_BLINK_2HZ;
117 	}
118 
119 	if (i2c_write_dt(&config->i2c, &cmd, sizeof(cmd))) {
120 		LOG_ERR("Setting HT16K33 blink frequency failed");
121 		return -EIO;
122 	}
123 
124 	return 0;
125 }
126 
ht16k33_led_set_brightness(const struct device * dev,uint32_t led,uint8_t value)127 static int ht16k33_led_set_brightness(const struct device *dev, uint32_t led,
128 				      uint8_t value)
129 {
130 	ARG_UNUSED(led);
131 
132 	const struct ht16k33_cfg *config = dev->config;
133 	struct ht16k33_data *data = dev->data;
134 	struct led_data *dev_data = &data->dev_data;
135 	uint8_t dim;
136 	uint8_t cmd;
137 
138 	if (value < dev_data->min_brightness ||
139 	    value > dev_data->max_brightness) {
140 		return -EINVAL;
141 	}
142 
143 	dim = (value * (HT16K33_DIMMING_LEVELS - 1)) / dev_data->max_brightness;
144 	cmd = HT16K33_CMD_DIMMING_SET | dim;
145 
146 	if (i2c_write_dt(&config->i2c, &cmd, sizeof(cmd))) {
147 		LOG_ERR("Setting HT16K33 brightness failed");
148 		return -EIO;
149 	}
150 
151 	return 0;
152 }
153 
ht16k33_led_set_state(const struct device * dev,uint32_t led,bool on)154 static int ht16k33_led_set_state(const struct device *dev, uint32_t led,
155 				 bool on)
156 {
157 	const struct ht16k33_cfg *config = dev->config;
158 	struct ht16k33_data *data = dev->data;
159 	uint8_t cmd[2];
160 	uint8_t addr;
161 	uint8_t bit;
162 
163 	if (led >= HT16K33_DISP_SEGMENTS) {
164 		return -EINVAL;
165 	}
166 
167 	addr = led / HT16K33_DISP_COLS;
168 	bit = led % HT16K33_DISP_COLS;
169 
170 	cmd[0] = HT16K33_CMD_DISP_DATA_ADDR | addr;
171 	if (on) {
172 		cmd[1] = data->buffer[addr] | BIT(bit);
173 	} else {
174 		cmd[1] = data->buffer[addr] & ~BIT(bit);
175 	}
176 
177 	if (data->buffer[addr] == cmd[1]) {
178 		return 0;
179 	}
180 
181 	if (i2c_write_dt(&config->i2c, cmd, sizeof(cmd))) {
182 		LOG_ERR("Setting HT16K33 LED %s failed", on ? "on" : "off");
183 		return -EIO;
184 	}
185 
186 	data->buffer[addr] = cmd[1];
187 
188 	return 0;
189 }
190 
ht16k33_led_on(const struct device * dev,uint32_t led)191 static int ht16k33_led_on(const struct device *dev, uint32_t led)
192 {
193 	return ht16k33_led_set_state(dev, led, true);
194 }
195 
ht16k33_led_off(const struct device * dev,uint32_t led)196 static int ht16k33_led_off(const struct device *dev, uint32_t led)
197 {
198 	return ht16k33_led_set_state(dev, led, false);
199 }
200 
201 #ifdef CONFIG_HT16K33_KEYSCAN
ht16k33_process_keyscan_data(const struct device * dev)202 static bool ht16k33_process_keyscan_data(const struct device *dev)
203 {
204 	const struct ht16k33_cfg *config = dev->config;
205 	struct ht16k33_data *data = dev->data;
206 	uint8_t keys[HT16K33_KEYSCAN_DATA_SIZE];
207 	bool pressed = false;
208 	uint16_t state;
209 	uint16_t changed;
210 	int row;
211 	int col;
212 	int err;
213 
214 	err = i2c_burst_read_dt(&config->i2c, HT16K33_CMD_KEY_DATA_ADDR, keys, sizeof(keys));
215 	if (err) {
216 		LOG_WRN("Failed to read HT16K33 key data (err %d)", err);
217 		/* Reprocess */
218 		return true;
219 	}
220 
221 	k_mutex_lock(&data->lock, K_FOREVER);
222 
223 	for (row = 0; row < HT16K33_KEYSCAN_ROWS; row++) {
224 		state = sys_get_le16(&keys[row * 2]);
225 		changed = data->key_state[row] ^ state;
226 		data->key_state[row] = state;
227 
228 		if (state) {
229 			pressed = true;
230 		}
231 
232 		for (col = 0; col < HT16K33_KEYSCAN_COLS; col++) {
233 			if ((changed & BIT(col)) == 0) {
234 				continue;
235 			}
236 			input_report_abs(dev, INPUT_ABS_X, col, false, K_FOREVER);
237 			input_report_abs(dev, INPUT_ABS_Y, row, false, K_FOREVER);
238 			input_report_key(dev, INPUT_BTN_TOUCH, state & BIT(col), true, K_FOREVER);
239 		}
240 	}
241 
242 	k_mutex_unlock(&data->lock);
243 
244 	return pressed;
245 }
246 
ht16k33_irq_thread(void * p1,void * p2,void * p3)247 static void ht16k33_irq_thread(void *p1, void *p2, void *p3)
248 {
249 	ARG_UNUSED(p2);
250 	ARG_UNUSED(p3);
251 
252 	struct ht16k33_data *data = p1;
253 	bool pressed;
254 
255 	while (true) {
256 		k_sem_take(&data->irq_sem, K_FOREVER);
257 
258 		do {
259 			k_sem_reset(&data->irq_sem);
260 			pressed = ht16k33_process_keyscan_data(data->dev);
261 			k_msleep(CONFIG_HT16K33_KEYSCAN_DEBOUNCE_MSEC);
262 		} while (pressed);
263 	}
264 }
265 
ht16k33_irq_callback(const struct device * gpiob,struct gpio_callback * cb,uint32_t pins)266 static void ht16k33_irq_callback(const struct device *gpiob,
267 				 struct gpio_callback *cb, uint32_t pins)
268 {
269 	struct ht16k33_data *data;
270 
271 	ARG_UNUSED(gpiob);
272 	ARG_UNUSED(pins);
273 
274 	data = CONTAINER_OF(cb, struct ht16k33_data, irq_cb);
275 	k_sem_give(&data->irq_sem);
276 }
277 
ht16k33_timer_callback(struct k_timer * timer)278 static void ht16k33_timer_callback(struct k_timer *timer)
279 {
280 	struct ht16k33_data *data;
281 
282 	data = CONTAINER_OF(timer, struct ht16k33_data, timer);
283 	k_sem_give(&data->irq_sem);
284 }
285 #endif /* CONFIG_HT16K33_KEYSCAN */
286 
ht16k33_init(const struct device * dev)287 static int ht16k33_init(const struct device *dev)
288 {
289 	const struct ht16k33_cfg *config = dev->config;
290 	struct ht16k33_data *data = dev->data;
291 	struct led_data *dev_data = &data->dev_data;
292 	uint8_t cmd[1 + HT16K33_DISP_DATA_SIZE]; /* 1 byte command + data */
293 	int err;
294 
295 	data->dev = dev;
296 
297 	if (!device_is_ready(config->i2c.bus)) {
298 		LOG_ERR("I2C bus device not ready");
299 		return -EINVAL;
300 	}
301 
302 	memset(&data->buffer, 0, sizeof(data->buffer));
303 
304 	/* Hardware specific limits */
305 	dev_data->min_period = 0U;
306 	dev_data->max_period = 2000U;
307 	dev_data->min_brightness = 0U;
308 	dev_data->max_brightness = 100U;
309 
310 	/* System oscillator on */
311 	cmd[0] = HT16K33_CMD_SYSTEM_SETUP | HT16K33_OPT_S;
312 	err = i2c_write_dt(&config->i2c, cmd, 1);
313 	if (err) {
314 		LOG_ERR("Enabling HT16K33 system oscillator failed (err %d)",
315 			err);
316 		return -EIO;
317 	}
318 
319 	/* Clear display RAM */
320 	memset(cmd, 0, sizeof(cmd));
321 	cmd[0] = HT16K33_CMD_DISP_DATA_ADDR;
322 	err = i2c_write_dt(&config->i2c, cmd, sizeof(cmd));
323 	if (err) {
324 		LOG_ERR("Clearing HT16K33 display RAM failed (err %d)", err);
325 		return -EIO;
326 	}
327 
328 	/* Full brightness */
329 	cmd[0] = HT16K33_CMD_DIMMING_SET | 0x0f;
330 	err = i2c_write_dt(&config->i2c, cmd, 1);
331 	if (err) {
332 		LOG_ERR("Setting HT16K33 brightness failed (err %d)", err);
333 		return -EIO;
334 	}
335 
336 	/* Display on, blinking off */
337 	cmd[0] = HT16K33_CMD_DISP_SETUP | HT16K33_OPT_D | HT16K33_OPT_BLINK_OFF;
338 	err = i2c_write_dt(&config->i2c, cmd, 1);
339 	if (err) {
340 		LOG_ERR("Enabling HT16K33 display failed (err %d)", err);
341 		return -EIO;
342 	}
343 
344 #ifdef CONFIG_HT16K33_KEYSCAN
345 	k_mutex_init(&data->lock);
346 	k_sem_init(&data->irq_sem, 0, 1);
347 
348 	/* Configure interrupt */
349 	if (config->irq_enabled) {
350 		uint8_t keys[HT16K33_KEYSCAN_DATA_SIZE];
351 
352 		if (!gpio_is_ready_dt(&config->irq)) {
353 			LOG_ERR("IRQ device not ready");
354 			return -EINVAL;
355 		}
356 
357 		err = gpio_pin_configure_dt(&config->irq, GPIO_INPUT);
358 		if (err) {
359 			LOG_ERR("Failed to configure IRQ pin (err %d)", err);
360 			return -EINVAL;
361 		}
362 
363 		gpio_init_callback(&data->irq_cb, &ht16k33_irq_callback,
364 				   BIT(config->irq.pin));
365 
366 		err = gpio_add_callback(config->irq.port, &data->irq_cb);
367 		if (err) {
368 			LOG_ERR("Failed to add IRQ callback (err %d)", err);
369 			return -EINVAL;
370 		}
371 
372 		/* Enable interrupt pin */
373 		cmd[0] = HT16K33_CMD_ROW_INT_SET | HT16K33_OPT_INT_LOW;
374 		if (i2c_write_dt(&config->i2c, cmd, 1)) {
375 			LOG_ERR("Enabling HT16K33 IRQ output failed");
376 			return -EIO;
377 		}
378 
379 		/* Flush key data before enabling interrupt */
380 		err = i2c_burst_read_dt(&config->i2c, HT16K33_CMD_KEY_DATA_ADDR, keys,
381 					sizeof(keys));
382 		if (err) {
383 			LOG_ERR("Failed to read HT16K33 key data");
384 			return -EIO;
385 		}
386 
387 		err = gpio_pin_interrupt_configure_dt(&config->irq,
388 						      GPIO_INT_EDGE_FALLING);
389 		if (err) {
390 			LOG_ERR("Failed to configure IRQ pin flags (err %d)",
391 				err);
392 			return -EINVAL;
393 		}
394 	} else {
395 		/* No interrupt pin, enable ROW15 */
396 		cmd[0] = HT16K33_CMD_ROW_INT_SET | HT16K33_OPT_ROW;
397 		if (i2c_write_dt(&config->i2c, cmd, 1)) {
398 			LOG_ERR("Enabling HT16K33 ROW15 output failed");
399 			return -EIO;
400 		}
401 
402 		/* Setup timer for polling key data */
403 		k_timer_init(&data->timer, ht16k33_timer_callback, NULL);
404 		k_timer_start(&data->timer, K_NO_WAIT,
405 			      K_MSEC(CONFIG_HT16K33_KEYSCAN_POLL_MSEC));
406 	}
407 
408 	k_thread_create(&data->irq_thread, data->irq_thread_stack,
409 			CONFIG_HT16K33_KEYSCAN_IRQ_THREAD_STACK_SIZE,
410 			ht16k33_irq_thread, data, NULL, NULL,
411 			K_PRIO_COOP(CONFIG_HT16K33_KEYSCAN_IRQ_THREAD_PRIO),
412 			0, K_NO_WAIT);
413 #endif /* CONFIG_HT16K33_KEYSCAN */
414 
415 	return 0;
416 }
417 
418 static DEVICE_API(led, ht16k33_leds_api) = {
419 	.blink = ht16k33_led_blink,
420 	.set_brightness = ht16k33_led_set_brightness,
421 	.on = ht16k33_led_on,
422 	.off = ht16k33_led_off,
423 };
424 
425 #define HT16K33_DEVICE(id)						\
426 	static const struct ht16k33_cfg ht16k33_##id##_cfg = {		\
427 		.i2c = I2C_DT_SPEC_INST_GET(id),			\
428 		.irq_enabled  = false,					\
429 	};								\
430 									\
431 	static struct ht16k33_data ht16k33_##id##_data;			\
432 									\
433 	DEVICE_DT_INST_DEFINE(id, &ht16k33_init, NULL,			\
434 			    &ht16k33_##id##_data,			\
435 			    &ht16k33_##id##_cfg, POST_KERNEL,		\
436 			    CONFIG_LED_INIT_PRIORITY, &ht16k33_leds_api)
437 
438 #ifdef CONFIG_HT16K33_KEYSCAN
439 #define HT16K33_DEVICE_WITH_IRQ(id)					\
440 	static const struct ht16k33_cfg ht16k33_##id##_cfg = {		\
441 		.i2c = I2C_DT_SPEC_INST_GET(id),			\
442 		.irq_enabled  = true,					\
443 		.irq          =	GPIO_DT_SPEC_INST_GET(id, irq_gpios),	\
444 	};								\
445 									\
446 	static struct ht16k33_data ht16k33_##id##_data;			\
447 									\
448 	DEVICE_DT_INST_DEFINE(id, &ht16k33_init, NULL,			\
449 			    &ht16k33_##id##_data,			\
450 			    &ht16k33_##id##_cfg, POST_KERNEL,		\
451 			    CONFIG_LED_INIT_PRIORITY, &ht16k33_leds_api)
452 #else /* ! CONFIG_HT16K33_KEYSCAN */
453 #define HT16K33_DEVICE_WITH_IRQ(id) HT16K33_DEVICE(id)
454 #endif /* ! CONFIG_HT16K33_KEYSCAN */
455 
456 #define HT16K33_INSTANTIATE(id)					\
457 	COND_CODE_1(DT_INST_NODE_HAS_PROP(id, irq_gpios),	\
458 		    (HT16K33_DEVICE_WITH_IRQ(id)),		\
459 		    (HT16K33_DEVICE(id)));
460 
461 DT_INST_FOREACH_STATUS_OKAY(HT16K33_INSTANTIATE)
462