Lines Matching +full:led +full:-
2 * QEMU DM163 8x3-channel constant current led driver
6 * Copyright (C) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
7 * Copyright (C) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
9 * SPDX-License-Identifier: GPL-2.0-or-later
14 * http://www.siti.com.tw/product/spec/LED/DM163.pdf
21 #include "hw/qdev-properties.h"
29 #define TURNED_OFF_ROW (COLOR_BUFFER_SIZE - 1)
61 s->sin = 0; in dm163_reset_hold()
62 s->dck = 0; in dm163_reset_hold()
63 s->rst_b = 0; in dm163_reset_hold()
65 s->lat_b = 1; in dm163_reset_hold()
66 s->selbk = 0; in dm163_reset_hold()
67 s->en_b = 0; in dm163_reset_hold()
69 memset(s->outputs, 0, sizeof(s->outputs)); in dm163_reset_hold()
71 s->activated_rows = 0; in dm163_reset_hold()
72 s->redraw = 0; in dm163_reset_hold()
73 trace_dm163_redraw(s->redraw); in dm163_reset_hold()
75 memset(s->buffer[i], 0, sizeof(s->buffer[0])); in dm163_reset_hold()
77 s->last_buffer_idx = 0; in dm163_reset_hold()
78 memset(s->buffer_idx_of_row, TURNED_OFF_ROW, sizeof(s->buffer_idx_of_row)); in dm163_reset_hold()
79 memset(s->row_persistence_delay, 0, sizeof(s->row_persistence_delay)); in dm163_reset_hold()
86 if (new_state && !s->dck) { in dm163_dck_gpio_handler()
92 s->selbk ? s->bank1_shift_register : s->bank0_shift_register; in dm163_dck_gpio_handler()
94 const bool sout = (s->selbk ? sb[2] & MAKE_64BIT_MASK(63, 1) : in dm163_dck_gpio_handler()
96 qemu_set_irq(s->sout, sout); in dm163_dck_gpio_handler()
100 sb[0] = (sb[0] << 1) | s->sin; in dm163_dck_gpio_handler()
103 s->dck = new_state; in dm163_dck_gpio_handler()
109 s->last_buffer_idx = (s->last_buffer_idx + 1) % RGB_MATRIX_NUM_ROWS; in dm163_propagate_outputs()
111 if (s->rst_b && !s->en_b) { in dm163_propagate_outputs()
112 memcpy(s->outputs, s->latched_outputs, sizeof(s->outputs)); in dm163_propagate_outputs()
114 memset(s->outputs, 0, sizeof(s->outputs)); in dm163_propagate_outputs()
118 const uint16_t b = extract16(s->outputs[3 * x + 0], 6, 8); in dm163_propagate_outputs()
119 const uint16_t g = extract16(s->outputs[3 * x + 1], 6, 8); in dm163_propagate_outputs()
120 const uint16_t r = extract16(s->outputs[3 * x + 2], 6, 8); in dm163_propagate_outputs()
131 /* Led values are sent from the last one to the first one */ in dm163_propagate_outputs()
132 s->buffer[s->last_buffer_idx][RGB_MATRIX_NUM_COLS - x - 1] = rgba; in dm163_propagate_outputs()
135 if (s->activated_rows & (1 << row)) { in dm163_propagate_outputs()
136 s->buffer_idx_of_row[row] = s->last_buffer_idx; in dm163_propagate_outputs()
137 s->redraw |= (1 << row); in dm163_propagate_outputs()
138 trace_dm163_redraw(s->redraw); in dm163_propagate_outputs()
147 s->en_b = new_state; in dm163_en_b_gpio_handler()
152 static uint8_t dm163_bank0(const DM163State *s, uint8_t led) in dm163_bank0() argument
155 * Bank 0 uses 6 bits per led, so a value may be stored accross in dm163_bank0()
158 const uint8_t low_bit = 6 * led; in dm163_bank0()
165 return extract64(s->bank0_shift_register[low_word], low_shift, 6); in dm163_bank0()
168 const uint8_t nb_bits_in_low_word = 64 - low_shift; in dm163_bank0()
169 const uint8_t nb_bits_in_high_word = 6 - nb_bits_in_low_word; in dm163_bank0()
172 extract64(s->bank0_shift_register[low_word], low_shift, in dm163_bank0()
175 extract64(s->bank0_shift_register[high_word], 0, in dm163_bank0()
186 static uint8_t dm163_bank1(const DM163State *s, uint8_t led) in dm163_bank1() argument
188 const uint64_t entry = s->bank1_shift_register[led / RGB_MATRIX_NUM_COLS]; in dm163_bank1()
189 return extract64(entry, 8 * (led % RGB_MATRIX_NUM_COLS), 8); in dm163_bank1()
196 if (s->lat_b && !new_state) { in dm163_lat_b_gpio_handler()
197 for (int led = 0; led < DM163_NUM_LEDS; led++) { in dm163_lat_b_gpio_handler() local
198 s->latched_outputs[led] = dm163_bank0(s, led) * dm163_bank1(s, led); in dm163_lat_b_gpio_handler()
203 s->lat_b = new_state; in dm163_lat_b_gpio_handler()
211 s->rst_b = new_state; in dm163_rst_b_gpio_handler()
220 s->selbk = new_state; in dm163_selbk_gpio_handler()
228 s->sin = new_state; in dm163_sin_gpio_handler()
237 s->activated_rows |= (1 << line); in dm163_rows_gpio_handler()
238 s->buffer_idx_of_row[line] = s->last_buffer_idx; in dm163_rows_gpio_handler()
239 s->redraw |= (1 << line); in dm163_rows_gpio_handler()
240 trace_dm163_redraw(s->redraw); in dm163_rows_gpio_handler()
242 s->activated_rows &= ~(1 << line); in dm163_rows_gpio_handler()
243 s->row_persistence_delay[line] = ROW_PERSISTENCE; in dm163_rows_gpio_handler()
245 trace_dm163_activated_rows(s->activated_rows); in dm163_rows_gpio_handler()
251 s->redraw = 0xFF; in dm163_invalidate_display()
252 trace_dm163_redraw(s->redraw); in dm163_invalidate_display()
257 if (s->row_persistence_delay[row]) { in update_row_persistence_delay()
258 s->row_persistence_delay[row]--; in update_row_persistence_delay()
264 s->buffer_idx_of_row[row] = TURNED_OFF_ROW; in update_row_persistence_delay()
265 s->redraw |= (1 << row); in update_row_persistence_delay()
266 trace_dm163_redraw(s->redraw); in update_row_persistence_delay()
274 for (int x = RGB_MATRIX_NUM_COLS * LED_SQUARE_SIZE - 1; x >= 0; x--) { in update_display_of_row()
276 *dest++ = s->buffer[s->buffer_idx_of_row[row]][x / LED_SQUARE_SIZE]; in update_display_of_row()
280 dpy_gfx_update(s->console, 0, LED_SQUARE_SIZE * row, in update_display_of_row()
282 s->redraw &= ~(1 << row); in update_display_of_row()
283 trace_dm163_redraw(s->redraw); in update_display_of_row()
291 DisplaySurface *surface = qemu_console_surface(s->console); in dm163_update_display()
297 if (!extract8(s->redraw, row, 1)) { in dm163_update_display()
321 qdev_init_gpio_out_named(dev, &s->sout, "sout", 1); in dm163_realize()
323 s->console = graphic_console_init(dev, 0, &dm163_ops, s); in dm163_realize()
324 qemu_console_resize(s->console, RGB_MATRIX_NUM_COLS * LED_SQUARE_SIZE, in dm163_realize()
333 dc->desc = "DM163 8x3-channel constant current LED driver"; in dm163_class_init()
334 dc->vmsd = &vmstate_dm163; in dm163_class_init()
335 dc->realize = dm163_realize; in dm163_class_init()
336 rc->phases.hold = dm163_reset_hold; in dm163_class_init()
337 set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); in dm163_class_init()