2019-01-13 23:51:13 -05:00
|
|
|
/*
|
2021-05-06 09:22:35 -04:00
|
|
|
* This file is part of the CircuitPython project, https://github.com/adafruit/circuitpython
|
2019-01-13 23:51:13 -05:00
|
|
|
*
|
|
|
|
* The MIT License (MIT)
|
|
|
|
*
|
2021-07-08 17:31:10 -04:00
|
|
|
* Copyright (c) 2018 Rose Hooper
|
2019-01-13 23:51:13 -05:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
Add adafruit_pixelmap.PixelMap
.. a fast helper for animations. It is similar to and inspired by the
PixelMap helper in Adafruit LED Animation library, but with an extremely
fast 'paste' method for setting a series of pixels. This is a common
operation for many animations, and can give a substantial speed improvement.
It's named `adafruit_pixelmap` so that we can package a compatible version
in pure Python for systems that can't fit it in C in flash, or for
Blinka.
This is a proof of concept and can make a very fast comet animation:
```python
import time
import adafruit_pixelbuf
import adafruti_pixelmap
import board
import neopixel
from supervisor import ticks_ms
from adafruit_led_animation.animation.solid import Solid
from adafruit_led_animation import color
pixel_pin = board.GP0
pixel_num = 96
pixels = neopixel.NeoPixel(pixel_pin, pixel_num, brightness=1, auto_write=False, pixel_order="RGB")
evens = adafruit_pixelmap.PixelMap(pixels, tuple(range(0, pixel_num, 2)))
odd_indices = tuple((i, i+2) for i in range(1, pixel_num, 4))
print(odd_indices)
odds = adafruit_pixelbuf.PixelMap(pixels, odd_indices)
assert len(odds) == len(odd_indices)
comet_length = 16
comet1 = [color.calculate_intensity(color.GREEN, ((1+i) / comet_length) ** 2.4)
for i in range(comet_length)]
comet2 = [color.calculate_intensity(color.PURPLE, ((1+i) / comet_length) ** 2.4)
for i in range(comet_length)]
pos1 = 0
pos2 = 96//4
while True:
evens.paste(comet1, pos1, wrap=True, reverse=False, others=0)
pos1 = (pos1 + 1) % len(evens)
odds.paste(comet2, pos2, wrap=True, reverse=True, others=0)
pos2 = (pos2 - 1) % len(odds)
pixels.show()
m = ticks_ms()
if m % 2000 > 1000:
time.sleep(.02)
```
2022-11-10 12:02:31 -05:00
|
|
|
#pragma once
|
2019-01-13 23:51:13 -05:00
|
|
|
|
|
|
|
#include "py/obj.h"
|
|
|
|
#include "py/objarray.h"
|
|
|
|
|
2020-01-24 21:23:07 -05:00
|
|
|
typedef struct {
|
|
|
|
uint8_t r;
|
|
|
|
uint8_t g;
|
|
|
|
uint8_t b;
|
|
|
|
uint8_t w;
|
|
|
|
} pixelbuf_rgbw_t;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
uint8_t bpp;
|
|
|
|
pixelbuf_rgbw_t byteorder;
|
|
|
|
bool has_white;
|
|
|
|
bool is_dotstar;
|
|
|
|
mp_obj_t order_string;
|
|
|
|
} pixelbuf_byteorder_details_t;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
mp_obj_base_t base;
|
|
|
|
size_t pixel_count;
|
_pixelbuf: Increase performance of brightness-scaling
On the Pico, this increases the "fill rate" of
pixels[:] = newvalues
considerably. On a strip of 240 RGB LEDs, auto_write=False, the timings
are:
|| Brightness || Before || After || Improvement ||
|| 1.0 || 117 kpix/s || 307 kpix/s || 2.62x ||
|| 0.07 || 117 kpix/s || 273 kpix/s || 2.33x ||
It's worth noting that even the "before" rate is fast compared to the
time to transmit a single neopixel, but any time we can gain back
in the whole pipeline will let marginal animations work a little better.
To set all the pixels in this way and then show() gives a pleasant bump
to the framerate, from about 108Hz to 124Hz (1.15x)
The main source of speed-up is using integer math instead of floating
point math for the calculation of the post-scaled pixel values. A slight
secondary gain is achieved by avoiding the scaling altogether when
the scale factor is 1.0.
Because the math is not exactly the same, some scaled pixel values may
change by +- 1 RGBW "step". In practice, this is unlikely to matter.
The gains are bigger on the Pico and other M0 microcontrollers than M4
microcontrollers with floating point math in the hardware.
Happily, flash size is also improved a bit on the Pico build I did,
going from
> 542552 bytes used, 506024 bytes free in flash firmware space out of 1048576 bytes (1024.0kB).
to
> 542376 bytes used, 506200 bytes free in flash firmware space out of 1048576 bytes (1024.0kB).
2021-02-24 10:29:59 -05:00
|
|
|
uint16_t bytes_per_pixel;
|
|
|
|
uint16_t scaled_brightness;
|
2020-01-24 21:23:07 -05:00
|
|
|
pixelbuf_byteorder_details_t byteorder;
|
|
|
|
mp_float_t brightness;
|
|
|
|
mp_obj_t transmit_buffer_obj;
|
|
|
|
// The post_brightness_buffer is offset into the buffer allocated in transmit_buffer_obj to
|
|
|
|
// account for any header.
|
|
|
|
uint8_t *post_brightness_buffer;
|
|
|
|
uint8_t *pre_brightness_buffer;
|
|
|
|
bool auto_write;
|
|
|
|
} pixelbuf_pixelbuf_obj_t;
|
|
|
|
|
2019-01-13 23:51:13 -05:00
|
|
|
#define PIXEL_R 0
|
|
|
|
#define PIXEL_G 1
|
|
|
|
#define PIXEL_B 2
|
|
|
|
#define PIXEL_W 3
|
|
|
|
|
|
|
|
#define DOTSTAR_LED_START 0b11100000
|
|
|
|
#define DOTSTAR_LED_START_FULL_BRIGHT 0xFF
|