diff --git a/drivers/hub75/hub75.cpp b/drivers/hub75/hub75.cpp index a894b70df..42d379b86 100644 --- a/drivers/hub75/hub75.cpp +++ b/drivers/hub75/hub75.cpp @@ -256,6 +256,7 @@ void Hub75::update(PicoGraphics *graphics) { uint8_t r = (col & 0xff0000) >> 16; uint8_t g = (col & 0x00ff00) >> 8; uint8_t b = (col & 0x0000ff) >> 0; + apply_brightness(&r, &g, &b); set_pixel(x, y, r, g, b); p++; } @@ -269,10 +270,105 @@ void Hub75::update(PicoGraphics *graphics) { uint8_t r = (col & 0b1111100000000000) >> 8; uint8_t g = (col & 0b0000011111100000) >> 3; uint8_t b = (col & 0b0000000000011111) << 3; + apply_brightness(&r, &g, &b); set_pixel(x, y, r, g, b); p++; } } } } + +void Hub75::set_brightness(uint8_t brightness) +{ + /* Clamp brightness to a sensible value, 0 - 100 */ + if(brightness > 100) { + user_brightness = 100; + } + else { + user_brightness = brightness; + } +} + +uint8_t Hub75::get_brightness() +{ + return user_brightness; +} + +void Hub75::apply_brightness(uint8_t *r, uint8_t *g, uint8_t *b) { + uint8_t h, s, v; + uint8_t rgbMin, rgbMax; + + /* If brightness is set full, no point in doing work. */ + if(user_brightness > 98 ) { + return; + } + + /* And if it's turned right down, it's off. */ + if(user_brightness < 2 ) { + *r = *g = *b = 0; + return; + } + + /* Convert RGB to HSV. */ + rgbMin = *r < *g ? (*r < *b ? *r : *b) : (*g < *b ? *g : *b); + rgbMax = *r > *g ? (*r > *b ? *r : *b) : (*g > *b ? *g : *b); + v = rgbMax; + if(v == 0) { + h = s = 0; + } else { + s = 255 * long(rgbMax - rgbMin) / v; + if(s == 0) { + h = 0; + } else { + if(rgbMax == *r) { + h = 0 + 43 * (*g - *b) / (rgbMax - rgbMin); + } else if(rgbMax == *g) { + h = 85 + 43 * (*b - *r) / (rgbMax - rgbMin); + } else { + h = 171 + 43 * (*r - *g) / (rgbMax - rgbMin); + } + } + } + + /* Apply the brightness factor to V. */ + v = v * user_brightness / 100; + + /* And then convert it *back* to RGB. */ + uint8_t region,remainder, p, q, t; + if(s == 0) + { + *r = *g = *b = v; + return; + } + region = h / 43; + remainder = (h - (region * 43)) * 6; + p = (v * (255 - s)) >> 8; + q = (v * (255 - ((s * remainder) >> 8))) >> 8; + t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8; + switch(region) + { + case 0: + *r = v; *g = t; *b = p; + break; + case 1: + *r = q; *g = v; *b = p; + break; + case 2: + *r = p; *g = v; *b = t; + break; + case 3: + *r = p; *g = q; *b = v; + break; + case 4: + *r = t; *g = p; *b = v; + break; + default: + *r = v; *g = p; *b = q; + break; + } + + /* All done! */ + return; +} + } \ No newline at end of file diff --git a/drivers/hub75/hub75.hpp b/drivers/hub75/hub75.hpp index cbd8fcbd6..2ce6d6665 100644 --- a/drivers/hub75/hub75.hpp +++ b/drivers/hub75/hub75.hpp @@ -86,6 +86,8 @@ class Hub75 { uint brightness = 6; + uint8_t user_brightness = 100; + // Top half of display - 16 rows on a 32x32 panel unsigned int pin_r0 = 0; @@ -138,5 +140,10 @@ class Hub75 { void stop(irq_handler_t handler); void dma_complete(); void update(PicoGraphics *graphics); + void set_brightness(uint8_t brightness); + uint8_t get_brightness(); + + private: + void apply_brightness(uint8_t *r, uint8_t *g, uint8_t *b); }; } \ No newline at end of file diff --git a/micropython/examples/interstate75/brightness.py b/micropython/examples/interstate75/brightness.py new file mode 100644 index 000000000..8a5984d66 --- /dev/null +++ b/micropython/examples/interstate75/brightness.py @@ -0,0 +1,32 @@ +from interstate75 import Interstate75 +import jpegdec +import time + +# Create the Interstate display +i75 = Interstate75(display=Interstate75.DISPLAY_INTERSTATE75_32X32) +graphics = i75.display + +# Clear the screen +graphics.set_pen(graphics.create_pen(0, 0, 0)) +graphics.clear() + +# Load and render a jpeg +img = jpegdec.JPEG(graphics) +img.open_file("sun.jpg") +img.decode(0, 0, jpegdec.JPEG_SCALE_FULL, dither=False) + +# Set up a brightness variance +delta = -1 +brightness = 100 + +# And loop as we do it +while True: + start = time.ticks_ms() + + i75.set_brightness(brightness) + brightness = brightness + delta + if brightness > 100 or brightness < 1: + delta = delta * -1 + i75.update(graphics) + + print("total took: {} ms".format(time.ticks_ms() - start)) diff --git a/micropython/examples/interstate75/sun.jpg b/micropython/examples/interstate75/sun.jpg new file mode 100644 index 000000000..9797193a1 Binary files /dev/null and b/micropython/examples/interstate75/sun.jpg differ diff --git a/micropython/modules/hub75/README.md b/micropython/modules/hub75/README.md index cdf869fcb..a78558272 100644 --- a/micropython/modules/hub75/README.md +++ b/micropython/modules/hub75/README.md @@ -91,4 +91,16 @@ Calling `.clear()` will clear the whole contents of the display ```python matrix.clear() -``` \ No newline at end of file +``` + +### Setting the brightness + +You can set the global brightness of the whole display; the brightness is an +integer value between `0` (off) and `100` (fully on): + +```python +matrix.set_brightness(75) +``` + +If unset, the brightness of the display defaults to 100. You can also query the +current brightness setting with `.get_brightness()`. \ No newline at end of file diff --git a/micropython/modules/hub75/hub75.c b/micropython/modules/hub75/hub75.c index 50781df89..f77a91a2d 100644 --- a/micropython/modules/hub75/hub75.c +++ b/micropython/modules/hub75/hub75.c @@ -8,6 +8,8 @@ MP_DEFINE_CONST_FUN_OBJ_1(Hub75_clear_obj, Hub75_clear); MP_DEFINE_CONST_FUN_OBJ_1(Hub75_start_obj, Hub75_start); MP_DEFINE_CONST_FUN_OBJ_1(Hub75_stop_obj, Hub75_stop); MP_DEFINE_CONST_FUN_OBJ_2(Hub75_update_obj, Hub75_update); +MP_DEFINE_CONST_FUN_OBJ_2(Hub75_set_brightness_obj, Hub75_set_brightness); +MP_DEFINE_CONST_FUN_OBJ_1(Hub75_get_brightness_obj, Hub75_get_brightness); /***** Binding of Methods *****/ @@ -18,6 +20,8 @@ static const mp_rom_map_elem_t Hub75_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&Hub75_start_obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&Hub75_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&Hub75_update_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_brightness), MP_ROM_PTR(&Hub75_set_brightness_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_brightness), MP_ROM_PTR(&Hub75_get_brightness_obj) }, }; static MP_DEFINE_CONST_DICT(Hub75_locals_dict, Hub75_locals_dict_table); diff --git a/micropython/modules/hub75/hub75.cpp b/micropython/modules/hub75/hub75.cpp index 6e586c7fe..335600336 100644 --- a/micropython/modules/hub75/hub75.cpp +++ b/micropython/modules/hub75/hub75.cpp @@ -142,6 +142,19 @@ mp_obj_t Hub75_update(mp_obj_t self_in, mp_obj_t graphics_in) { return mp_const_none; } +mp_obj_t Hub75_set_brightness(mp_obj_t self_in, mp_obj_t brightness) { + _Hub75_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Hub75_obj_t); + + self->hub75->set_brightness(mp_obj_get_int(brightness)); + + return mp_const_none; +} + +mp_obj_t Hub75_get_brightness(mp_obj_t self_in) { + _Hub75_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Hub75_obj_t); + return mp_obj_new_int(self->hub75->get_brightness()); +} + mp_obj_t Hub75_start(mp_obj_t self_in) { _Hub75_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Hub75_obj_t); self->hub75->start(dma_complete); diff --git a/micropython/modules/hub75/hub75.h b/micropython/modules/hub75/hub75.h index 22666d740..e65e7f3ec 100644 --- a/micropython/modules/hub75/hub75.h +++ b/micropython/modules/hub75/hub75.h @@ -13,4 +13,6 @@ extern mp_obj_t Hub75_start(mp_obj_t self_in); extern mp_obj_t Hub75_stop(mp_obj_t self_in); extern mp_obj_t Hub75_set_pixel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); extern mp_obj_t Hub75_clear(mp_obj_t self_in); -extern mp_obj_t Hub75_update(mp_obj_t self_in, mp_obj_t graphics_in); \ No newline at end of file +extern mp_obj_t Hub75_update(mp_obj_t self_in, mp_obj_t graphics_in); +extern mp_obj_t Hub75_set_brightness(mp_obj_t self_in, mp_obj_t brightness); +extern mp_obj_t Hub75_get_brightness(mp_obj_t self_in); diff --git a/micropython/modules_py/interstate75.md b/micropython/modules_py/interstate75.md index 33974921c..6c29ef78e 100644 --- a/micropython/modules_py/interstate75.md +++ b/micropython/modules_py/interstate75.md @@ -86,6 +86,27 @@ board.set_led(0, 255, 0) # Makes the LED Blue board.set_led(0, 0, 255) # Makes the LED Green ``` +### Brightness + +The Interstate has a global brightness, that affects the entire display. By +default, the display is set to full, but this can be changed via the following +method. + +`.set_brightness(n)` + +Where n is a value between 0 (off) and 100 (full brightness) + +The current brightness of the display can be also be queried: + +`.get_brightness()` + + +example: + +```python +board.set_brightness(50) # Sets the display to half-brightness +``` + ## Display The display is all handled by our custom picographics drivers they can be accessed via `.display`. diff --git a/micropython/modules_py/interstate75.py b/micropython/modules_py/interstate75.py index 6792d8659..328c20ca1 100644 --- a/micropython/modules_py/interstate75.py +++ b/micropython/modules_py/interstate75.py @@ -75,3 +75,9 @@ def switch_pressed(self, switch): def set_led(self, r, g, b): self.__rgb.set_rgb(r, g, b) + + def set_brightness(self, brightness): + self.hub75.set_brightness(brightness) + + def get_brightness(self): + return self.hub75.get_brightness()