Fresh combined checkin of _pixelbuf library.
This commit is contained in:
parent
9678a5a328
commit
ffe734edf7
@ -78,12 +78,12 @@ Not all of these functions and types are turned on in all CircuitPython ports, f
|
||||
|
||||
.. classmethod:: from_bytes(bytes, byteorder)
|
||||
|
||||
In CircuitPython, `byteorder` parameter must be positional (this is
|
||||
In CircuitPython, ``byteorder`` parameter must be positional (this is
|
||||
compatible with CPython).
|
||||
|
||||
.. method:: to_bytes(size, byteorder)
|
||||
|
||||
In CircuitPython, `byteorder` parameter must be positional (this is
|
||||
In CircuitPython, ``byteorder`` parameter must be positional (this is
|
||||
compatible with CPython).
|
||||
|
||||
.. function:: isinstance()
|
||||
|
@ -191,6 +191,10 @@ LDFLAGS += -mthumb -mcpu=cortex-m4
|
||||
BOOTLOADER_SIZE := 0x4000
|
||||
endif
|
||||
|
||||
ifdef EXCLUDE_PIXELBUF
|
||||
CFLAGS += -DEXCLUDE_PIXELBUF
|
||||
endif
|
||||
|
||||
SRC_ASF := \
|
||||
gcc/gcc/startup_$(CHIP_FAMILY).c \
|
||||
gcc/system_$(CHIP_FAMILY).c \
|
||||
@ -419,6 +423,11 @@ ifneq ($(CHIP_VARIANT),SAMR21G18A)
|
||||
audioio/WaveFile.c
|
||||
endif
|
||||
|
||||
ifndef EXCLUDE_PIXELBUF
|
||||
SRC_SHARED_MODULE += _pixelbuf/__init__.c \
|
||||
_pixelbuf/PixelBuf.c
|
||||
endif
|
||||
|
||||
# The smallest SAMD51 packages don't have I2S. Everything else does.
|
||||
ifneq ($(CHIP_VARIANT),SAMD51G18A)
|
||||
ifneq ($(CHIP_VARIANT),SAMD51G19A)
|
||||
|
@ -9,3 +9,5 @@ LONGINT_IMPL = NONE
|
||||
|
||||
CHIP_VARIANT = SAMD21G18A
|
||||
CHIP_FAMILY = samd21
|
||||
|
||||
EXCLUDE_PIXELBUF = 1
|
||||
|
@ -9,6 +9,8 @@ EXTERNAL_FLASH_DEVICE_COUNT = 2
|
||||
EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C"
|
||||
# Turn off longints for Crickit build to make room for additional frozen libs.
|
||||
LONGINT_IMPL = NONE
|
||||
# Disable pixelbuf to save room
|
||||
EXCLUDE_PIXELBUF = 1
|
||||
|
||||
CHIP_VARIANT = SAMD21G18A
|
||||
CHIP_FAMILY = samd21
|
||||
|
@ -9,3 +9,5 @@ LONGINT_IMPL = NONE
|
||||
|
||||
CHIP_VARIANT = SAMD21G18A
|
||||
CHIP_FAMILY = samd21
|
||||
|
||||
EXCLUDE_PIXELBUF = 1
|
||||
|
@ -16,3 +16,5 @@ CFLAGS_INLINE_LIMIT = 45
|
||||
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_DotStar
|
||||
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HID
|
||||
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_IRRemote
|
||||
|
||||
EXCLUDE_PIXELBUF = 1
|
||||
|
@ -9,3 +9,5 @@ LONGINT_IMPL = NONE
|
||||
|
||||
CHIP_VARIANT = SAMD21E18A
|
||||
CHIP_FAMILY = samd21
|
||||
|
||||
EXCLUDE_PIXELBUF = 1
|
||||
|
@ -241,6 +241,9 @@ extern const struct _mp_obj_module_t usb_midi_module;
|
||||
extern const struct _mp_obj_module_t network_module;
|
||||
extern const struct _mp_obj_module_t socket_module;
|
||||
extern const struct _mp_obj_module_t wiznet_module;
|
||||
#ifndef EXCLUDE_PIXELBUF
|
||||
extern const struct _mp_obj_module_t pixelbuf_module;
|
||||
#endif
|
||||
|
||||
// Internal flash size dependent settings.
|
||||
#if BOARD_FLASH_SIZE > 192000
|
||||
@ -308,6 +311,11 @@ extern const struct _mp_obj_module_t wiznet_module;
|
||||
#define JSON_MODULE
|
||||
#endif
|
||||
|
||||
#ifndef EXCLUDE_PIXELBUF
|
||||
#define PIXELBUF_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR__pixelbuf),(mp_obj_t)&pixelbuf_module }
|
||||
#else
|
||||
#define PIXELBUF_MODULE
|
||||
#endif
|
||||
|
||||
#ifndef EXTRA_BUILTIN_MODULES
|
||||
#define EXTRA_BUILTIN_MODULES \
|
||||
@ -321,7 +329,8 @@ extern const struct _mp_obj_module_t wiznet_module;
|
||||
WIZNET_MODULE \
|
||||
JSON_MODULE \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_rotaryio), (mp_obj_t)&rotaryio_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_gamepad),(mp_obj_t)&gamepad_module }
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_gamepad),(mp_obj_t)&gamepad_module }, \
|
||||
PIXELBUF_MODULE
|
||||
#endif
|
||||
#define EXPRESS_BOARD
|
||||
|
||||
|
@ -148,6 +148,11 @@ SRC_SHARED_MODULE = \
|
||||
os/__init__.c \
|
||||
random/__init__.c \
|
||||
struct/__init__.c
|
||||
|
||||
ifndef EXCLUDE_PIXELBUF
|
||||
SRC_SHARED_MODULE += _pixelbuf/__init__.c \
|
||||
_pixelbuf/PixelBuf.c
|
||||
endif
|
||||
|
||||
SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \
|
||||
$(addprefix shared-module/, $(SRC_SHARED_MODULE))
|
||||
|
@ -214,7 +214,13 @@ SRC_SHARED_MODULE = \
|
||||
bitbangio/OneWire.c \
|
||||
bitbangio/SPI.c \
|
||||
busio/OneWire.c \
|
||||
storage/__init__.c
|
||||
storage/__init__.c
|
||||
|
||||
|
||||
ifndef EXCLUDE_PIXELBUF
|
||||
SRC_SHARED_MODULE += _pixelbuf/__init__.c \
|
||||
_pixelbuf/PixelBuf.c
|
||||
endif
|
||||
|
||||
# uheap/__init__.c \
|
||||
ustack/__init__.c
|
||||
|
506
shared-bindings/_pixelbuf/PixelBuf.c
Normal file
506
shared-bindings/_pixelbuf/PixelBuf.c
Normal file
@ -0,0 +1,506 @@
|
||||
/*
|
||||
* This file is part of the Circuit Python project, https://github.com/adafruit/circuitpython
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Roy Hooper
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/objarray.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/binary.h"
|
||||
#include "py/objproperty.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "PixelBuf.h"
|
||||
#include "shared-bindings/_pixelbuf/types.h"
|
||||
#include "../../shared-module/_pixelbuf/PixelBuf.h"
|
||||
#include "shared-bindings/digitalio/DigitalInOut.h"
|
||||
|
||||
extern const pixelbuf_byteorder_obj_t byteorder_BGR;
|
||||
extern const mp_obj_type_t pixelbuf_byteorder_type;
|
||||
extern const int32_t colorwheel(float pos);
|
||||
|
||||
//| .. currentmodule:: pixelbuf
|
||||
//|
|
||||
//| :class:`PixelBuf` -- A fast RGB[W] pixel buffer for LED and similar devices
|
||||
//| ===========================================================================
|
||||
//|
|
||||
//| :class:`~_pixelbuf.PixelBuf` implements an RGB[W] bytearray abstraction.
|
||||
//|
|
||||
//| .. class:: PixelBuf(size, buf, byteorder=BGR, bpp=3)
|
||||
//|
|
||||
//| Create a PixelBuf object of the specified size, byteorder, and bits per pixel.
|
||||
//|
|
||||
//| When given a second bytearray (``rawbuf``), changing brightness adjusts the
|
||||
//| brightness of all members of ``buf``.
|
||||
//|
|
||||
//| When only given ``buf``, ``brightness`` applies to the next pixel assignment.
|
||||
//|
|
||||
//| When ``dotstar`` is True, and ``bpp`` is 4, the 4th value in a tuple/list
|
||||
//| is the individual pixel brightness (0-1). Not compatible with RGBW Byteorders.
|
||||
//| Compatible `ByteOrder` classes are bpp=3, or bpp=4 and has_luminosity=True (g LBGR).
|
||||
//|
|
||||
//| :param ~int size: Number of pixelsx
|
||||
//| :param ~bytearray buf: Bytearray to store pixel data in
|
||||
//| :param ~_pixelbuf.ByteOrder byteorder: Byte order constant from `_pixelbuf` (also sets the bpp)
|
||||
//| :param ~float brightness: Brightness (0 to 1.0, default 1.0)
|
||||
//| :param ~bytearray rawbuf: Bytearray to store raw pixel colors in
|
||||
//| :param ~int offset: Offset from start of buffer (default 0)
|
||||
//| :param ~bool dotstar: Dotstar mode (default False)
|
||||
//| :param ~bool auto_write: Whether to automatically write pixels (Default False)
|
||||
//| :param ~callable write_function: (optional) Callable to use to send pixels
|
||||
//| :param ~list write_args: (optional) Tuple or list of args to pass to ``write_function``. The
|
||||
//| PixelBuf instance is appended after these args.
|
||||
//|
|
||||
STATIC mp_obj_t pixelbuf_pixelbuf_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) {
|
||||
mp_arg_check_num(n_args, n_kw, 2, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args);
|
||||
enum { ARG_size, ARG_buf, ARG_byteorder, ARG_brightness, ARG_rawbuf, ARG_offset, ARG_dotstar,
|
||||
ARG_auto_write, ARG_write_function, ARG_write_args };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_size, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_byteorder, MP_ARG_OBJ, { .u_obj = mp_const_none } },
|
||||
{ MP_QSTR_brightness, MP_ARG_OBJ, { .u_obj = mp_const_none } },
|
||||
{ MP_QSTR_rawbuf, MP_ARG_OBJ, { .u_obj = mp_const_none } },
|
||||
{ MP_QSTR_offset, MP_ARG_INT, { .u_int = 0 } },
|
||||
{ MP_QSTR_dotstar, MP_ARG_BOOL, { .u_bool = false } },
|
||||
{ MP_QSTR_auto_write, MP_ARG_BOOL, {.u_bool = false} },
|
||||
{ MP_QSTR_write_function, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_write_args, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
};
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
if (mp_obj_is_subclass_fast(args[ARG_byteorder].u_obj, &pixelbuf_byteorder_type))
|
||||
mp_raise_TypeError_varg(translate("byteorder is not an instance of ByteOrder (got a %s)"), mp_obj_get_type_str(args[ARG_byteorder].u_obj));
|
||||
|
||||
pixelbuf_byteorder_obj_t *byteorder = (args[ARG_byteorder].u_obj == mp_const_none) ? MP_OBJ_FROM_PTR(&byteorder_BGR) : args[ARG_byteorder].u_obj;
|
||||
|
||||
if (byteorder->has_white && args[ARG_dotstar].u_bool)
|
||||
mp_raise_ValueError_varg(translate("Can not use dotstar with %s"), mp_obj_get_type_str(byteorder));
|
||||
|
||||
size_t effective_bpp = args[ARG_dotstar].u_bool ? 4 : byteorder->bpp; // Always 4 for DotStar
|
||||
size_t bytes = args[ARG_size].u_int * effective_bpp;
|
||||
size_t offset = args[ARG_offset].u_int;
|
||||
mp_buffer_info_t bufinfo, rawbufinfo;
|
||||
|
||||
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ | MP_BUFFER_WRITE);
|
||||
bool two_buffers = args[ARG_rawbuf].u_obj != mp_const_none;
|
||||
if (two_buffers) {
|
||||
mp_get_buffer_raise(args[ARG_rawbuf].u_obj, &rawbufinfo, MP_BUFFER_READ | MP_BUFFER_WRITE);
|
||||
if (rawbufinfo.len != bufinfo.len) {
|
||||
mp_raise_ValueError(translate("rawbuf is not the same size as buf"));
|
||||
}
|
||||
}
|
||||
|
||||
if (bytes + offset > bufinfo.len)
|
||||
mp_raise_ValueError_varg(translate("buf is too small. need %d bytes"), bytes + offset);
|
||||
|
||||
if (!MP_OBJ_IS_TYPE(args[ARG_write_args].u_obj, &mp_type_list) &&
|
||||
!MP_OBJ_IS_TYPE(args[ARG_write_args].u_obj, &mp_type_tuple) &&
|
||||
args[ARG_write_args].u_obj != mp_const_none)
|
||||
{
|
||||
mp_raise_ValueError(translate("write_args must be a list, tuple, or None"));
|
||||
}
|
||||
|
||||
// Validation complete, allocate and populate object.
|
||||
pixelbuf_pixelbuf_obj_t *self = m_new_obj(pixelbuf_pixelbuf_obj_t);
|
||||
|
||||
self->base.type = &pixelbuf_pixelbuf_type;
|
||||
self->pixels = args[ARG_size].u_int;
|
||||
self->bytes = bytes;
|
||||
self->byteorder = *byteorder; // Copied because we modify for dotstar
|
||||
self->bytearray = args[ARG_buf].u_obj;
|
||||
self->two_buffers = two_buffers;
|
||||
self->rawbytearray = two_buffers ? args[ARG_rawbuf].u_obj : NULL;
|
||||
self->offset = offset;
|
||||
self->dotstar_mode = args[ARG_dotstar].u_bool;
|
||||
self->buf = (uint8_t *)bufinfo.buf + offset;
|
||||
self->rawbuf = two_buffers ? (uint8_t *)rawbufinfo.buf + offset : NULL;
|
||||
self->pixel_step = effective_bpp;
|
||||
self->auto_write = args[ARG_auto_write].u_bool;
|
||||
|
||||
if (self->dotstar_mode) {
|
||||
// Ensure sane configuration
|
||||
if (!self->byteorder.has_luminosity) {
|
||||
self->byteorder.has_luminosity = true;
|
||||
self->byteorder.byteorder.b += 1;
|
||||
self->byteorder.byteorder.g += 1;
|
||||
self->byteorder.byteorder.r += 1;
|
||||
}
|
||||
self->byteorder.byteorder.w = 0;
|
||||
}
|
||||
|
||||
// Show/auto-write callbacks
|
||||
self->write_function = args[ARG_write_function].u_obj;
|
||||
mp_obj_t function_args = args[ARG_write_args].u_obj;
|
||||
mp_obj_t *src_objs = (mp_obj_t *)&mp_const_none_obj;
|
||||
size_t num_items = 0;
|
||||
if (function_args != mp_const_none) {
|
||||
if (MP_OBJ_IS_TYPE(function_args, &mp_type_list)) {
|
||||
mp_obj_list_t *t = MP_OBJ_TO_PTR(function_args);
|
||||
num_items = t->len;
|
||||
src_objs = t->items;
|
||||
} else {
|
||||
mp_obj_tuple_t *l = MP_OBJ_TO_PTR(function_args);
|
||||
num_items = l->len;
|
||||
src_objs = l->items;
|
||||
}
|
||||
}
|
||||
self->write_function_args = mp_obj_new_tuple(num_items + 1, NULL);
|
||||
for (size_t i = 0; i < num_items; i++) {
|
||||
self->write_function_args->items[i] = src_objs[i];
|
||||
}
|
||||
self->write_function_args->items[num_items] = self;
|
||||
|
||||
if (args[ARG_brightness].u_obj == mp_const_none) {
|
||||
self->brightness = 1.0;
|
||||
} else {
|
||||
self->brightness = mp_obj_get_float(args[ARG_brightness].u_obj);
|
||||
if (self->brightness < 0)
|
||||
self->brightness = 0;
|
||||
else if (self->brightness > 1)
|
||||
self->brightness = 1;
|
||||
}
|
||||
|
||||
if (self->dotstar_mode) {
|
||||
// Initialize the buffer with the dotstar start bytes.
|
||||
// Header and end must be setup by caller
|
||||
for (uint i = 0; i < self->pixels * 4; i += 4) {
|
||||
self->buf[i] = DOTSTAR_LED_START_FULL_BRIGHT;
|
||||
if (two_buffers) {
|
||||
self->rawbuf[i] = DOTSTAR_LED_START_FULL_BRIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
//| .. attribute:: bpp
|
||||
//|
|
||||
//| The number of bytes per pixel in the buffer (read-only)
|
||||
//|
|
||||
STATIC mp_obj_t pixelbuf_pixelbuf_obj_get_bpp(mp_obj_t self_in) {
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &pixelbuf_pixelbuf_type));
|
||||
pixelbuf_pixelbuf_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return mp_obj_new_int_from_uint(self->byteorder.bpp);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_pixelbuf_get_bpp_obj, pixelbuf_pixelbuf_obj_get_bpp);
|
||||
|
||||
const mp_obj_property_t pixelbuf_pixelbuf_bpp_obj = {
|
||||
.base.type = &mp_type_property,
|
||||
.proxy = {(mp_obj_t)&pixelbuf_pixelbuf_get_bpp_obj,
|
||||
(mp_obj_t)&mp_const_none_obj,
|
||||
(mp_obj_t)&mp_const_none_obj},
|
||||
};
|
||||
|
||||
|
||||
//| .. attribute:: brightness
|
||||
//|
|
||||
//| Float value between 0 and 1. Output brightness.
|
||||
//| If the PixelBuf was allocated with two both a buf and a rawbuf,
|
||||
//| setting this value causes a recomputation of the values in buf.
|
||||
//| If only a buf was provided, then the brightness only applies to
|
||||
//| future pixel changes.
|
||||
//| In DotStar mode
|
||||
//|
|
||||
STATIC mp_obj_t pixelbuf_pixelbuf_obj_get_brightness(mp_obj_t self_in) {
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &pixelbuf_pixelbuf_type));
|
||||
pixelbuf_pixelbuf_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return mp_obj_new_float(self->brightness);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_pixelbuf_get_brightness_obj, pixelbuf_pixelbuf_obj_get_brightness);
|
||||
|
||||
|
||||
STATIC mp_obj_t pixelbuf_pixelbuf_obj_set_brightness(mp_obj_t self_in, mp_obj_t value) {
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &pixelbuf_pixelbuf_type));
|
||||
pixelbuf_pixelbuf_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
self->brightness = mp_obj_float_get(value);
|
||||
if (self->brightness > 1)
|
||||
self->brightness = 1;
|
||||
else if (self->brightness < 0)
|
||||
self->brightness = 0;
|
||||
if (self->two_buffers)
|
||||
pixelbuf_recalculate_brightness(self);
|
||||
if (self->auto_write)
|
||||
call_write_function(self);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(pixelbuf_pixelbuf_set_brightness_obj, pixelbuf_pixelbuf_obj_set_brightness);
|
||||
|
||||
const mp_obj_property_t pixelbuf_pixelbuf_brightness_obj = {
|
||||
.base.type = &mp_type_property,
|
||||
.proxy = {(mp_obj_t)&pixelbuf_pixelbuf_get_brightness_obj,
|
||||
(mp_obj_t)&pixelbuf_pixelbuf_set_brightness_obj,
|
||||
(mp_obj_t)&mp_const_none_obj},
|
||||
};
|
||||
|
||||
void pixelbuf_recalculate_brightness(pixelbuf_pixelbuf_obj_t *self) {
|
||||
uint8_t *buf = (uint8_t *)self->buf;
|
||||
uint8_t *rawbuf = (uint8_t *)self->rawbuf;
|
||||
// Compensate for shifted buffer (bpp=3 dotstar)
|
||||
for (uint i = 0; i < self->bytes; i++) {
|
||||
// Don't adjust per-pixel luminance bytes in dotstar mode
|
||||
if (!self->dotstar_mode || (i % 4 != 0))
|
||||
buf[i] = rawbuf[i] * self->brightness;
|
||||
}
|
||||
}
|
||||
|
||||
//| .. attribute:: auto_write
|
||||
//|
|
||||
//| Whether to automatically write the pixels after each update.
|
||||
//|
|
||||
STATIC mp_obj_t pixelbuf_pixelbuf_obj_get_auto_write(mp_obj_t self_in) {
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &pixelbuf_pixelbuf_type));
|
||||
pixelbuf_pixelbuf_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return mp_obj_new_bool(self->auto_write);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_pixelbuf_get_auto_write_obj, pixelbuf_pixelbuf_obj_get_auto_write);
|
||||
|
||||
|
||||
STATIC mp_obj_t pixelbuf_pixelbuf_obj_set_auto_write(mp_obj_t self_in, mp_obj_t value) {
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &pixelbuf_pixelbuf_type));
|
||||
pixelbuf_pixelbuf_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
self->auto_write = mp_obj_is_true(value);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(pixelbuf_pixelbuf_set_auto_write_obj, pixelbuf_pixelbuf_obj_set_auto_write);
|
||||
|
||||
const mp_obj_property_t pixelbuf_pixelbuf_auto_write_obj = {
|
||||
.base.type = &mp_type_property,
|
||||
.proxy = {(mp_obj_t)&pixelbuf_pixelbuf_get_auto_write_obj,
|
||||
(mp_obj_t)&pixelbuf_pixelbuf_set_auto_write_obj,
|
||||
(mp_obj_t)&mp_const_none_obj},
|
||||
};
|
||||
|
||||
|
||||
//| .. attribute:: buf
|
||||
//|
|
||||
//| (read-only) bytearray of pixel data after brightness adjustment. If an offset was provided
|
||||
//| then this bytearray is the subset of the bytearray passed in that represents the
|
||||
//| actual pixels.
|
||||
//|
|
||||
STATIC mp_obj_t pixelbuf_pixelbuf_obj_get_buf(mp_obj_t self_in) {
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &pixelbuf_pixelbuf_type));
|
||||
pixelbuf_pixelbuf_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return mp_obj_new_bytearray_by_ref(self->bytes, self->buf);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_pixelbuf_get_buf_obj, pixelbuf_pixelbuf_obj_get_buf);
|
||||
|
||||
const mp_obj_property_t pixelbuf_pixelbuf_buf_obj = {
|
||||
.base.type = &mp_type_property,
|
||||
.proxy = {(mp_obj_t)&pixelbuf_pixelbuf_get_buf_obj,
|
||||
(mp_obj_t)&mp_const_none_obj,
|
||||
(mp_obj_t)&mp_const_none_obj},
|
||||
};
|
||||
|
||||
//| .. attribute:: byteorder
|
||||
//|
|
||||
//| `ByteOrder` class for the buffer (read-only)
|
||||
//|
|
||||
STATIC mp_obj_t pixelbuf_pixelbuf_obj_get_byteorder(mp_obj_t self_in) {
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &pixelbuf_pixelbuf_type));
|
||||
pixelbuf_pixelbuf_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return &self->byteorder;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_pixelbuf_get_byteorder_obj, pixelbuf_pixelbuf_obj_get_byteorder);
|
||||
|
||||
const mp_obj_property_t pixelbuf_pixelbuf_byteorder_obj = {
|
||||
.base.type = &mp_type_property,
|
||||
.proxy = {(mp_obj_t)&pixelbuf_pixelbuf_get_byteorder_obj,
|
||||
(mp_obj_t)&mp_const_none_obj,
|
||||
(mp_obj_t)&mp_const_none_obj},
|
||||
};
|
||||
|
||||
STATIC mp_obj_t pixelbuf_pixelbuf_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &pixelbuf_pixelbuf_type));
|
||||
pixelbuf_pixelbuf_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
switch (op) {
|
||||
case MP_UNARY_OP_BOOL: return mp_const_true;
|
||||
case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->pixels);
|
||||
default: return MP_OBJ_NULL; // op not supported
|
||||
}
|
||||
}
|
||||
|
||||
//| .. method:: show()
|
||||
//|
|
||||
//| Call the associated write function to display the pixels.
|
||||
//|
|
||||
|
||||
STATIC mp_obj_t pixelbuf_pixelbuf_show(mp_obj_t self_in) {
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &pixelbuf_pixelbuf_type));
|
||||
pixelbuf_pixelbuf_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
call_write_function(self);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_pixelbuf_show_obj, pixelbuf_pixelbuf_show);
|
||||
|
||||
void call_write_function(pixelbuf_pixelbuf_obj_t *self) {
|
||||
// execute function if it's set
|
||||
if (self->write_function != mp_const_none) {
|
||||
mp_call_function_n_kw(self->write_function, self->write_function_args->len, 0, self->write_function_args->items);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//| .. method:: []
|
||||
//|
|
||||
//| Get or set pixels. Supports individual pixels and slices.
|
||||
//|
|
||||
STATIC mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &pixelbuf_pixelbuf_type));
|
||||
|
||||
if (value == MP_OBJ_NULL) {
|
||||
// delete item
|
||||
// slice deletion
|
||||
return MP_OBJ_NULL; // op not supported
|
||||
}
|
||||
|
||||
pixelbuf_pixelbuf_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (0) {
|
||||
#if MICROPY_PY_BUILTINS_SLICE
|
||||
} else if (MP_OBJ_IS_TYPE(index_in, &mp_type_slice)) {
|
||||
mp_bound_slice_t slice;
|
||||
|
||||
if (!mp_seq_get_fast_slice_indexes(self->bytes, index_in, &slice))
|
||||
mp_raise_NotImplementedError(translate("Only slices with step=1 (aka None) are supported"));
|
||||
if ((slice.stop * self->pixel_step) > self->bytes)
|
||||
mp_raise_IndexError(translate("Range out of bounds"));
|
||||
|
||||
if (value == MP_OBJ_SENTINEL) { // Get
|
||||
size_t len = slice.stop - slice.start;
|
||||
return pixelbuf_get_pixel_array((uint8_t *) self->buf + slice.start, len, &self->byteorder, self->pixel_step, self->dotstar_mode);
|
||||
} else { // Set
|
||||
#if MICROPY_PY_ARRAY_SLICE_ASSIGN
|
||||
|
||||
if (!(MP_OBJ_IS_TYPE(value, &mp_type_list) || MP_OBJ_IS_TYPE(value, &mp_type_tuple)))
|
||||
mp_raise_ValueError(translate("tuple/list required on RHS"));
|
||||
|
||||
size_t dst_len = slice.stop - slice.start;
|
||||
|
||||
mp_obj_t *src_objs;
|
||||
size_t num_items;
|
||||
if (MP_OBJ_IS_TYPE(value, &mp_type_list)) {
|
||||
mp_obj_list_t *t = MP_OBJ_TO_PTR(value);
|
||||
num_items = t->len;
|
||||
src_objs = t->items;
|
||||
} else {
|
||||
mp_obj_tuple_t *l = MP_OBJ_TO_PTR(value);
|
||||
num_items = l->len;
|
||||
src_objs = l->items;
|
||||
}
|
||||
if (num_items != dst_len)
|
||||
mp_raise_ValueError_varg(translate("Unmatched number of items on RHS (expected %d, got %d)."),
|
||||
dst_len, num_items);
|
||||
|
||||
for (size_t i = slice.start; i < slice.stop; i++) {
|
||||
mp_obj_t *item = src_objs[i-slice.start];
|
||||
if (MP_OBJ_IS_TYPE(value, &mp_type_list) || MP_OBJ_IS_TYPE(value, &mp_type_tuple) || MP_OBJ_IS_INT(value)) {
|
||||
pixelbuf_set_pixel(self->buf + (i * self->pixel_step),
|
||||
self->two_buffers ? self->rawbuf + (i * self->pixel_step) : NULL,
|
||||
self->brightness, item, &self->byteorder, self->dotstar_mode);
|
||||
}
|
||||
}
|
||||
if (self->auto_write)
|
||||
call_write_function(self);
|
||||
return mp_const_none;
|
||||
#else
|
||||
return MP_OBJ_NULL; // op not supported
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
} else { // Single index rather than slice.
|
||||
size_t index = mp_get_index(self->base.type, self->pixels, index_in, false);
|
||||
size_t offset = (index * self->pixel_step);
|
||||
if (offset > self->bytes)
|
||||
mp_raise_IndexError(translate("Pixel beyond bounds of buffer"));
|
||||
|
||||
if (value == MP_OBJ_SENTINEL) { // Get
|
||||
uint8_t *pixelstart = (uint8_t *)(self->two_buffers ? self->rawbuf : self->buf) + offset;
|
||||
return pixelbuf_get_pixel(pixelstart, &self->byteorder, self->dotstar_mode);
|
||||
} else { // Store
|
||||
pixelbuf_set_pixel(self->buf + offset, self->two_buffers ? self->rawbuf + offset : NULL,
|
||||
self->brightness, value, &self->byteorder, self->dotstar_mode);
|
||||
if (self->auto_write)
|
||||
call_write_function(self);
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//| .. method:: fill_wheel(start=0, step=1)
|
||||
//|
|
||||
//| fill the buffer with a colorwheel starting at offset n, and stepping by step
|
||||
//|
|
||||
|
||||
STATIC mp_obj_t pixelbuf_pixelbuf_fill_wheel(mp_obj_t self_in, mp_obj_t start, mp_obj_t step) {
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &pixelbuf_pixelbuf_type));
|
||||
pixelbuf_pixelbuf_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
float i = MP_OBJ_IS_SMALL_INT(start) ? MP_OBJ_SMALL_INT_VALUE(start) : mp_obj_float_get(start);
|
||||
float incr = MP_OBJ_IS_SMALL_INT(step) ? MP_OBJ_SMALL_INT_VALUE(step) : mp_obj_float_get(step);
|
||||
|
||||
bool auto_write = self->auto_write;
|
||||
self->auto_write = false;
|
||||
for (size_t n = 0; n < self->pixels; n++) {
|
||||
mp_obj_t value = MP_OBJ_NEW_SMALL_INT(colorwheel(i));
|
||||
pixelbuf_pixelbuf_subscr(self_in, MP_OBJ_NEW_SMALL_INT(n), value);
|
||||
i += incr;
|
||||
}
|
||||
self->auto_write = auto_write;
|
||||
if (auto_write)
|
||||
call_write_function(self);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(pixelbuf_pixelbuf_fill_wheel_obj, pixelbuf_pixelbuf_fill_wheel);
|
||||
|
||||
STATIC const mp_rom_map_elem_t pixelbuf_pixelbuf_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_auto_write), MP_ROM_PTR(&pixelbuf_pixelbuf_auto_write_obj)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_bpp), MP_ROM_PTR(&pixelbuf_pixelbuf_bpp_obj)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_brightness), MP_ROM_PTR(&pixelbuf_pixelbuf_brightness_obj)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_buf), MP_ROM_PTR(&pixelbuf_pixelbuf_buf_obj)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_byteorder), MP_ROM_PTR(&pixelbuf_pixelbuf_byteorder_obj)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&pixelbuf_pixelbuf_show_obj)},
|
||||
{ MP_ROM_QSTR(MP_QSTR_fill_wheel), MP_ROM_PTR(&pixelbuf_pixelbuf_fill_wheel_obj)},
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(pixelbuf_pixelbuf_locals_dict, pixelbuf_pixelbuf_locals_dict_table);
|
||||
|
||||
|
||||
const mp_obj_type_t pixelbuf_pixelbuf_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_PixelBuf,
|
||||
.subscr = pixelbuf_pixelbuf_subscr,
|
||||
.make_new = pixelbuf_pixelbuf_make_new,
|
||||
.unary_op = pixelbuf_pixelbuf_unary_op,
|
||||
.print = NULL,
|
||||
.locals_dict = (mp_obj_t)&pixelbuf_pixelbuf_locals_dict,
|
||||
};
|
60
shared-bindings/_pixelbuf/PixelBuf.h
Normal file
60
shared-bindings/_pixelbuf/PixelBuf.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of the Circuit Python project, https://github.com/adafruit/circuitpython
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Roy Hooper
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CP_SHARED_BINDINGS_PIXELBUF_PIXELBUF_H
|
||||
#define CP_SHARED_BINDINGS_PIXELBUF_PIXELBUF_H
|
||||
|
||||
#include "shared-bindings/_pixelbuf/types.h"
|
||||
|
||||
const mp_obj_type_t pixelbuf_pixelbuf_type;
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
size_t pixels;
|
||||
size_t bytes;
|
||||
size_t pixel_step;
|
||||
pixelbuf_byteorder_obj_t byteorder;
|
||||
mp_obj_t bytearray;
|
||||
mp_obj_t rawbytearray;
|
||||
mp_float_t brightness;
|
||||
bool two_buffers;
|
||||
size_t offset;
|
||||
bool dotstar_mode;
|
||||
uint8_t *rawbuf;
|
||||
uint8_t *buf;
|
||||
mp_obj_t write_function;
|
||||
mp_obj_tuple_t *write_function_args;
|
||||
bool auto_write;
|
||||
} pixelbuf_pixelbuf_obj_t;
|
||||
|
||||
void pixelbuf_recalculate_brightness(pixelbuf_pixelbuf_obj_t *self);
|
||||
void call_write_function(pixelbuf_pixelbuf_obj_t *self);
|
||||
|
||||
|
||||
#include "common-hal/digitalio/DigitalInOut.h"
|
||||
extern void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* gpio, uint8_t *pixels, uint32_t numBytes);
|
||||
|
||||
#endif // CP_SHARED_BINDINGS_PIXELBUF_PIXELBUF_H
|
326
shared-bindings/_pixelbuf/__init__.c
Normal file
326
shared-bindings/_pixelbuf/__init__.c
Normal file
@ -0,0 +1,326 @@
|
||||
/*
|
||||
* This file is part of the Circuit Python project, https://github.com/adafruit/circuitpython
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Roy Hooper
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/objproperty.h"
|
||||
|
||||
#include "types.h"
|
||||
#include "__init__.h"
|
||||
|
||||
#include "PixelBuf.h"
|
||||
#include "../../shared-module/_pixelbuf/PixelBuf.h"
|
||||
|
||||
|
||||
//| :mod:`_pixelbuf` --- Fast RGB(W) pixel buffer and helpers
|
||||
//| ===========================================================
|
||||
|
||||
//| .. module:: _pixelbuf
|
||||
//| :synopsis: A fast RGB(W) pixel buffer library for like NeoPixel and DotStar.
|
||||
//|
|
||||
//| The `_pixelbuf` module provides :py:class:`PixelBuf` and :py:class:`ByteOrder` classes to accelerate
|
||||
//| Dotstar and Neopixel manipulation.
|
||||
//|
|
||||
|
||||
//| Libraries
|
||||
//|
|
||||
//| .. toctree::
|
||||
//| :maxdepth: 3
|
||||
//|
|
||||
//| PixelBuf
|
||||
|
||||
//| .. class:: ByteOrder
|
||||
//|
|
||||
//| Classes representing byteorders for circuitpython
|
||||
|
||||
|
||||
//| .. attribute:: bpp
|
||||
//|
|
||||
//| The number of bytes per pixel (read-only)
|
||||
//|
|
||||
|
||||
//| .. attribute:: has_white
|
||||
//|
|
||||
//| Whether the pixel has white (in addition to RGB)
|
||||
//|
|
||||
|
||||
//| .. attribute:: has_luminosity
|
||||
//|
|
||||
//| Whether the pixel has luminosity (in addition to RGB)
|
||||
//|
|
||||
|
||||
//| .. attribute:: byteorder
|
||||
//|
|
||||
//| Tuple of byte order (r, g, b) or (r, g, b, w) or (r, g, b, l)
|
||||
//|
|
||||
|
||||
|
||||
STATIC void pixelbuf_byteorder_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
|
||||
mp_check_self(MP_OBJ_IS_TYPE(self_in, &pixelbuf_byteorder_type));
|
||||
pixelbuf_byteorder_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (dest[0] == MP_OBJ_NULL) {
|
||||
// load attribute
|
||||
mp_obj_t val;
|
||||
if (attr == MP_QSTR_bpp) {
|
||||
val = MP_OBJ_NEW_SMALL_INT(self->bpp);
|
||||
} else if (attr == MP_QSTR_has_white) {
|
||||
val = mp_obj_new_bool(self->has_white);
|
||||
} else if (attr == MP_QSTR_has_luminosity) {
|
||||
val = mp_obj_new_bool(self->has_luminosity);
|
||||
} else if (attr == MP_QSTR_byteorder) {
|
||||
mp_obj_t items[4];
|
||||
uint8_t n = self->bpp;
|
||||
if (self->has_luminosity || self->has_white) {
|
||||
n = 4;
|
||||
}
|
||||
uint8_t *values = (uint8_t *)&(self->byteorder);
|
||||
for (uint8_t i=0; i<n; i++) {
|
||||
items[i] = MP_OBJ_NEW_SMALL_INT(values[i]);
|
||||
}
|
||||
val = mp_obj_new_tuple(n, items);
|
||||
} else {
|
||||
mp_raise_AttributeError(translate("no such attribute"));
|
||||
}
|
||||
dest[0] = val;
|
||||
} else {
|
||||
// delete/store attribute (ignored)
|
||||
dest[0] = MP_OBJ_NULL;
|
||||
mp_raise_AttributeError(translate("readonly attribute"));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pixelbuf_byteorder_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
|
||||
pixelbuf_byteorder_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
switch (op) {
|
||||
case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->bpp);
|
||||
default: return MP_OBJ_NULL; // op not supported
|
||||
}
|
||||
}
|
||||
|
||||
const mp_obj_type_t pixelbuf_byteorder_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_ByteOrder,
|
||||
.print = pixelbuf_byteorder_print,
|
||||
.unary_op = pixelbuf_byteorder_unary_op,
|
||||
.attr = pixelbuf_byteorder_attr,
|
||||
};
|
||||
|
||||
|
||||
// This macro is used to simplify RGB subclass definition
|
||||
#define PIXELBUF_BYTEORDER(p_name, p_bpp, p_r, p_g, p_b, p_w, p_has_white, p_has_luminosity) \
|
||||
const pixelbuf_byteorder_obj_t byteorder_## p_name = { \
|
||||
{ &pixelbuf_byteorder_type }, \
|
||||
.name = MP_QSTR_## p_name, \
|
||||
.bpp = p_bpp, \
|
||||
.byteorder = { p_r, p_g, p_b, p_w }, \
|
||||
.has_white = p_has_white, \
|
||||
.has_luminosity = p_has_luminosity, \
|
||||
};
|
||||
|
||||
//| .. function:: wheel(n)
|
||||
//|
|
||||
//| C implementation of the common wheel() function found in many examples.
|
||||
//| Returns the colorwheel RGB value as an integer value for n (usable in :py:class:`PixelBuf`, neopixel, and dotstar).
|
||||
//|
|
||||
|
||||
STATIC mp_obj_t pixelbuf_wheel(mp_obj_t n) {
|
||||
return MP_OBJ_NEW_SMALL_INT(colorwheel(MP_OBJ_IS_SMALL_INT(n) ? MP_OBJ_SMALL_INT_VALUE(n) : mp_obj_float_get(n)));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_wheel_obj, pixelbuf_wheel);
|
||||
|
||||
const int32_t colorwheel(float pos) {
|
||||
if (pos > 255) {
|
||||
pos = pos - ((uint32_t)(pos / 256) * 256);
|
||||
}
|
||||
if (pos < 85)
|
||||
return (uint8_t)(pos * 3) << 16 | (uint8_t)(255 - (pos * 3)) << 8;
|
||||
else if (pos < 170) {
|
||||
pos -= 85;
|
||||
return (uint8_t)(255 - (pos * 3)) << 16 | (uint8_t)(pos * 3);
|
||||
} else {
|
||||
pos -= 170;
|
||||
return (uint8_t)(pos * 3) << 8 | (uint8_t)(255 - pos * 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// RGB
|
||||
//| .. class:: RGB
|
||||
//|
|
||||
//| * **order** Red, Green, Blue
|
||||
//| * **bpp** 3
|
||||
PIXELBUF_BYTEORDER(RGB, 3, 0, 1, 2, 3, false, false)
|
||||
//| .. class:: RBG
|
||||
//|
|
||||
//| * **order** Red, Blue, Green
|
||||
//| * **bpp** 3
|
||||
PIXELBUF_BYTEORDER(RBG, 3, 0, 2, 1, 3, false, false)
|
||||
//| .. class:: GRB
|
||||
//|
|
||||
//| * **order** Green, Red, Blue
|
||||
//| * **bpp** 3
|
||||
//|
|
||||
//| Commonly used by NeoPixel.
|
||||
PIXELBUF_BYTEORDER(GRB, 3, 1, 0, 2, 3, false, false)
|
||||
//| .. class:: GBR
|
||||
//|
|
||||
//| * **order** Green, Blue, Red
|
||||
//| * **bpp** 3
|
||||
PIXELBUF_BYTEORDER(GBR, 3, 1, 2, 0, 3, false, false)
|
||||
//| .. class:: BRG
|
||||
//|
|
||||
//| * **order** Blue, Red, Green
|
||||
//| * **bpp** 3
|
||||
PIXELBUF_BYTEORDER(BRG, 3, 2, 0, 1, 3, false, false)
|
||||
//| .. class:: BGR
|
||||
//|
|
||||
//| * **order** Blue, Green, Red
|
||||
//| * **bpp** 3
|
||||
//|
|
||||
//| Commonly used by Dotstar.
|
||||
PIXELBUF_BYTEORDER(BGR, 3, 2, 1, 0, 3, false, false)
|
||||
|
||||
// RGBW
|
||||
//| .. class:: RGBW
|
||||
//|
|
||||
//| * **order** Red, Green, Blue, White
|
||||
//| * **bpp** 4
|
||||
//| * **has_white** True
|
||||
PIXELBUF_BYTEORDER(RGBW, 4, 0, 1, 2, 3, true, false)
|
||||
//| .. class:: RBGW
|
||||
//|
|
||||
//| * **order** Red, Blue, Green, White
|
||||
//| * **bpp** 4
|
||||
//| * **has_white** True
|
||||
PIXELBUF_BYTEORDER(RBGW, 4, 0, 2, 1, 3, true, false)
|
||||
//| .. class:: GRBW
|
||||
//|
|
||||
//| * **order** Green, Red, Blue, White
|
||||
//| * **bpp** 4
|
||||
//| * **has_white** True
|
||||
//|
|
||||
//| Commonly used by RGBW NeoPixels.
|
||||
PIXELBUF_BYTEORDER(GRBW, 4, 1, 0, 2, 3, true, false)
|
||||
//| .. class:: GBRW
|
||||
//|
|
||||
//| * **order** Green, Blue, Red, White
|
||||
//| * **bpp** 4
|
||||
//| * **has_white** True
|
||||
PIXELBUF_BYTEORDER(GBRW, 4, 1, 2, 0, 3, true, false)
|
||||
//| .. class:: BRGW
|
||||
//|
|
||||
//| * **order** Blue, Red, Green, White
|
||||
//| * **bpp** 4
|
||||
//| * **has_white** True
|
||||
PIXELBUF_BYTEORDER(BRGW, 4, 2, 0, 1, 3, true, false)
|
||||
//| .. class:: BGRW
|
||||
//|
|
||||
//| * **order** Blue, Green, Red, White
|
||||
//| * **bpp** 4
|
||||
//| * **has_white** True
|
||||
PIXELBUF_BYTEORDER(BGRW, 4, 2, 1, 0, 3, true, false)
|
||||
|
||||
// Luminosity + RGB (eg for Dotstar)
|
||||
// Luminosity chosen because the luminosity of a Dotstar at full bright
|
||||
// burns the eyes like looking at the Sun.
|
||||
// https://www.thesaurus.com/browse/luminosity?s=t
|
||||
//| .. class:: LRGB
|
||||
//|
|
||||
//| * **order** *Luminosity*, Red, Green, Blue
|
||||
//| * **bpp** 4
|
||||
//| * **has_luminosity** True
|
||||
PIXELBUF_BYTEORDER(LRGB, 4, 1, 2, 3, 0, false, true)
|
||||
//| .. class:: LRBG
|
||||
//|
|
||||
//| * **order** *Luminosity*, Red, Blue, Green
|
||||
//| * **bpp** 4
|
||||
//| * **has_luminosity** True
|
||||
PIXELBUF_BYTEORDER(LRBG, 4, 1, 3, 2, 0, false, true)
|
||||
//| .. class:: LGRB
|
||||
//|
|
||||
//| * **order** *Luminosity*, Green, Red, Blue
|
||||
//| * **bpp** 4
|
||||
//| * **has_luminosity** True
|
||||
PIXELBUF_BYTEORDER(LGRB, 4, 2, 1, 3, 0, false, true)
|
||||
//| .. class:: LGBR
|
||||
//|
|
||||
//| * **order** *Luminosity*, Green, Blue, Red
|
||||
//| * **bpp** 4
|
||||
//| * **has_luminosity** True
|
||||
PIXELBUF_BYTEORDER(LGBR, 4, 2, 3, 1, 0, false, true)
|
||||
//| .. class:: LBRG
|
||||
//|
|
||||
//| * **order** *Luminosity*, Blue, Red, Green
|
||||
//| * **bpp** 4
|
||||
//| * **has_luminosity** True
|
||||
PIXELBUF_BYTEORDER(LBRG, 4, 3, 1, 2, 0, false, true)
|
||||
//| .. class:: LBGR
|
||||
//|
|
||||
//| * **order** *Luminosity*, Blue, Green, Red
|
||||
//| * **bpp** 4
|
||||
//| * **has_luminosity** True
|
||||
//|
|
||||
//| Actual format commonly used by DotStar (5 bit luninance value)
|
||||
PIXELBUF_BYTEORDER(LBGR, 4, 3, 2, 1, 0, false, true)
|
||||
|
||||
STATIC const mp_rom_map_elem_t pixelbuf_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__pixelbuf) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_PixelBuf), MP_ROM_PTR(&pixelbuf_pixelbuf_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ByteOrder), MP_ROM_PTR(&pixelbuf_byteorder_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_RGB), MP_ROM_PTR(&byteorder_RGB) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_RBG), MP_ROM_PTR(&byteorder_RBG) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GRB), MP_ROM_PTR(&byteorder_GRB) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GBR), MP_ROM_PTR(&byteorder_GBR) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BRG), MP_ROM_PTR(&byteorder_BRG) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BGR), MP_ROM_PTR(&byteorder_BGR) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_RGBW), MP_ROM_PTR(&byteorder_RGBW) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_RBGW), MP_ROM_PTR(&byteorder_RBGW) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GRBW), MP_ROM_PTR(&byteorder_GRBW) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GBRW), MP_ROM_PTR(&byteorder_GBRW) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BRGW), MP_ROM_PTR(&byteorder_BRGW) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BGRW), MP_ROM_PTR(&byteorder_BGRW) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_LRGB), MP_ROM_PTR(&byteorder_LRGB) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_LRBG), MP_ROM_PTR(&byteorder_LRBG) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_LGRB), MP_ROM_PTR(&byteorder_LGRB) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_LGBR), MP_ROM_PTR(&byteorder_LGBR) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_LBRG), MP_ROM_PTR(&byteorder_LBRG) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_LBGR), MP_ROM_PTR(&byteorder_LBGR) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_wheel), MP_ROM_PTR(&pixelbuf_wheel_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(pixelbuf_module_globals, pixelbuf_module_globals_table);
|
||||
|
||||
STATIC void pixelbuf_byteorder_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
pixelbuf_byteorder_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "%q.%q", MP_QSTR__pixelbuf, self->name);
|
||||
return;
|
||||
}
|
||||
|
||||
const mp_obj_module_t pixelbuf_module = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&pixelbuf_module_globals,
|
||||
};
|
35
shared-bindings/_pixelbuf/__init__.h
Normal file
35
shared-bindings/_pixelbuf/__init__.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of the Circuit Python project, https://github.com/adafruit/circuitpython
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Roy Hooper
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CP_SHARED_BINDINGS_PIXELBUF_INIT_H
|
||||
#define CP_SHARED_BINDINGS_PIXELBUF_INIT_H
|
||||
|
||||
STATIC void pixelbuf_byteorder_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
|
||||
const int32_t colorwheel(float pos);
|
||||
|
||||
const mp_obj_type_t pixelbuf_byteorder_type;
|
||||
|
||||
#endif //CP_SHARED_BINDINGS_PIXELBUF_INIT_H
|
48
shared-bindings/_pixelbuf/types.h
Normal file
48
shared-bindings/_pixelbuf/types.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of the Circuit Python project, https://github.com/adafruit/circuitpython
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Roy Hooper
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CIRCUITPYTHON_PIXELBUF_TYPES_H
|
||||
#define CIRCUITPYTHON_PIXELBUF_TYPES_H
|
||||
|
||||
//| :orphan:
|
||||
|
||||
typedef struct {
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
uint8_t w;
|
||||
} pixelbuf_rgbw_t;
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
qstr name;
|
||||
uint8_t bpp;
|
||||
pixelbuf_rgbw_t byteorder;
|
||||
bool has_white;
|
||||
bool has_luminosity;
|
||||
} pixelbuf_byteorder_obj_t;
|
||||
|
||||
#endif // CIRCUITPYTHON_PIXELBUF_TYPES_H
|
@ -61,4 +61,6 @@ Module Supported Ports
|
||||
`touchio` **SAMD/SAMD Express**
|
||||
`uheap` **Debug (All)**
|
||||
`usb_hid` **SAMD/SAMD Express**
|
||||
`_pixelbuf` **SAMD Express**
|
||||
`_stage` **SAMD/SAMD Express**
|
||||
================= ==============================
|
||||
|
120
shared-module/_pixelbuf/PixelBuf.c
Normal file
120
shared-module/_pixelbuf/PixelBuf.c
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* This file is part of the Circuit Python project, https://github.com/adafruit/circuitpython
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Roy Hooper
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/objarray.h"
|
||||
#include "py/runtime.h"
|
||||
#include "PixelBuf.h"
|
||||
#include <string.h>
|
||||
|
||||
void pixelbuf_set_pixel_int(uint8_t *buf, mp_int_t value, pixelbuf_byteorder_obj_t *byteorder) {
|
||||
buf[byteorder->byteorder.r] = value >> 16 & 0xff;
|
||||
buf[byteorder->byteorder.g] = (value >> 8) & 0xff;
|
||||
buf[byteorder->byteorder.b] = value & 0xff;
|
||||
if (byteorder->bpp == 4 && byteorder->has_white &&
|
||||
(buf[byteorder->byteorder.r] == buf[byteorder->byteorder.g] &&
|
||||
buf[byteorder->byteorder.r] == buf[byteorder->byteorder.b])) {
|
||||
buf[byteorder->byteorder.w] = buf[byteorder->byteorder.r];
|
||||
buf[byteorder->byteorder.r] = buf[byteorder->byteorder.g] = buf[byteorder->byteorder.b] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_t *item, pixelbuf_byteorder_obj_t *byteorder, bool dotstar) {
|
||||
if (MP_OBJ_IS_INT(item)) {
|
||||
uint8_t *target = rawbuf ? rawbuf : buf;
|
||||
pixelbuf_set_pixel_int(target, mp_obj_get_int_truncated(item), byteorder);
|
||||
if (dotstar) {
|
||||
buf[0] = DOTSTAR_LED_START_FULL_BRIGHT;
|
||||
if (rawbuf)
|
||||
rawbuf[0] = DOTSTAR_LED_START_FULL_BRIGHT;
|
||||
}
|
||||
if (rawbuf) {
|
||||
buf[byteorder->byteorder.r] = rawbuf[byteorder->byteorder.r] * brightness;
|
||||
buf[byteorder->byteorder.g] = rawbuf[byteorder->byteorder.g] * brightness;
|
||||
buf[byteorder->byteorder.b] = rawbuf[byteorder->byteorder.b] * brightness;
|
||||
} else {
|
||||
buf[byteorder->byteorder.r] *= brightness;
|
||||
buf[byteorder->byteorder.g] *= brightness;
|
||||
buf[byteorder->byteorder.b] *= brightness;
|
||||
}
|
||||
} else {
|
||||
mp_obj_t *items;
|
||||
size_t len;
|
||||
mp_obj_get_array(item, &len, &items);
|
||||
if (len != byteorder->bpp && !dotstar)
|
||||
mp_raise_ValueError_varg(translate("Expected tuple of length %d, got %d"), byteorder->bpp, len);
|
||||
|
||||
buf[byteorder->byteorder.r] = mp_obj_get_int_truncated(items[PIXEL_R]) * brightness;
|
||||
buf[byteorder->byteorder.g] = mp_obj_get_int_truncated(items[PIXEL_G]) * brightness;
|
||||
buf[byteorder->byteorder.b] = mp_obj_get_int_truncated(items[PIXEL_B]) * brightness;
|
||||
if (rawbuf) {
|
||||
rawbuf[byteorder->byteorder.r] = mp_obj_get_int_truncated(items[PIXEL_R]);
|
||||
rawbuf[byteorder->byteorder.g] = mp_obj_get_int_truncated(items[PIXEL_G]);
|
||||
rawbuf[byteorder->byteorder.b] = mp_obj_get_int_truncated(items[PIXEL_B]);
|
||||
}
|
||||
if (len > 3) {
|
||||
if (dotstar) {
|
||||
buf[byteorder->byteorder.w] = DOTSTAR_LED_START | DOTSTAR_BRIGHTNESS(mp_obj_get_float(items[PIXEL_W]));
|
||||
if (rawbuf)
|
||||
rawbuf[byteorder->byteorder.w] = buf[byteorder->byteorder.w];
|
||||
} else {
|
||||
buf[byteorder->byteorder.w] = mp_obj_get_int_truncated(items[PIXEL_W]) * brightness;
|
||||
if (rawbuf)
|
||||
rawbuf[byteorder->byteorder.w] = mp_obj_get_int_truncated(items[PIXEL_W]);
|
||||
}
|
||||
} else if (dotstar) {
|
||||
buf[byteorder->byteorder.w] = DOTSTAR_LED_START_FULL_BRIGHT;
|
||||
if (rawbuf)
|
||||
rawbuf[byteorder->byteorder.w] = DOTSTAR_LED_START_FULL_BRIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_obj_t *byteorder, uint8_t step, bool dotstar) {
|
||||
mp_obj_t elems[len];
|
||||
for (uint i = 0; i < len; i++) {
|
||||
elems[i] = pixelbuf_get_pixel(buf + (i * step), byteorder, dotstar);
|
||||
}
|
||||
return mp_obj_new_tuple(len, elems);
|
||||
}
|
||||
|
||||
mp_obj_t *pixelbuf_get_pixel(uint8_t *buf, pixelbuf_byteorder_obj_t *byteorder, bool dotstar) {
|
||||
mp_obj_t elems[byteorder->bpp];
|
||||
|
||||
elems[0] = mp_obj_new_int(buf[byteorder->byteorder.r]);
|
||||
elems[1] = mp_obj_new_int(buf[byteorder->byteorder.g]);
|
||||
elems[2] = mp_obj_new_int(buf[byteorder->byteorder.b]);
|
||||
if (byteorder->bpp > 3)
|
||||
{
|
||||
if (dotstar)
|
||||
elems[3] = mp_obj_new_float(DOTSTAR_GET_BRIGHTNESS(buf[byteorder->byteorder.w]));
|
||||
else
|
||||
elems[3] = mp_obj_new_int(buf[byteorder->byteorder.w]);
|
||||
}
|
||||
|
||||
return mp_obj_new_tuple(byteorder->bpp, elems);
|
||||
}
|
50
shared-module/_pixelbuf/PixelBuf.h
Normal file
50
shared-module/_pixelbuf/PixelBuf.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of the Circuit Python project, https://github.com/adafruit/circuitpython
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Roy Hooper
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/objarray.h"
|
||||
#include "../../shared-bindings/_pixelbuf/types.h"
|
||||
|
||||
#ifndef PIXELBUF_SHARED_MODULE_H
|
||||
#define PIXELBUF_SHARED_MODULE_H
|
||||
|
||||
#define PIXEL_R 0
|
||||
#define PIXEL_G 1
|
||||
#define PIXEL_B 2
|
||||
#define PIXEL_W 3
|
||||
|
||||
#define DOTSTAR_LED_START 0b11100000
|
||||
#define DOTSTAR_BRIGHTNESS(brightness) ((32 - (uint8_t)(32 - brightness * 31)) & 0b00011111)
|
||||
#define DOTSTAR_GET_BRIGHTNESS(value) ((value & 0b00011111) / 31.0)
|
||||
#define DOTSTAR_LED_START_FULL_BRIGHT 0xFF
|
||||
|
||||
void pixelbuf_set_pixel(uint8_t *buf, uint8_t *rawbuf, float brightness, mp_obj_t *item, pixelbuf_byteorder_obj_t *byteorder, bool dotstar);
|
||||
mp_obj_t *pixelbuf_get_pixel(uint8_t *buf, pixelbuf_byteorder_obj_t *byteorder, bool dotstar);
|
||||
mp_obj_t *pixelbuf_get_pixel_array(uint8_t *buf, uint len, pixelbuf_byteorder_obj_t *byteorder, uint8_t step, bool dotstar);
|
||||
void pixelbuf_set_pixel_int(uint8_t *buf, mp_int_t value, pixelbuf_byteorder_obj_t *byteorder);
|
||||
|
||||
#endif
|
0
shared-module/_pixelbuf/__init__.c
Normal file
0
shared-module/_pixelbuf/__init__.c
Normal file
Loading…
Reference in New Issue
Block a user