kopia lustrzana https://github.com/pimoroni/pimoroni-pico
Lots of features added
rodzic
e50827c412
commit
63183d28be
|
@ -4,7 +4,8 @@ add_executable(
|
|||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(galactic_unicorn_demo pico_stdlib hardware_pio hardware_dma pico_graphics galactic_unicorn)
|
||||
target_link_libraries(galactic_unicorn_demo pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn)
|
||||
pico_enable_stdio_usb(galactic_unicorn_demo 1)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(galactic_unicorn_demo)
|
||||
|
@ -17,7 +18,108 @@ add_executable(
|
|||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(galactic_unicorn_demo2 pico_stdlib hardware_pio hardware_dma pico_graphics galactic_unicorn)
|
||||
target_link_libraries(galactic_unicorn_demo2 pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn)
|
||||
pico_enable_stdio_usb(galactic_unicorn_demo2 1)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(galactic_unicorn_demo2)
|
||||
|
||||
|
||||
|
||||
add_executable(
|
||||
nostalgia_prompt
|
||||
nostalgia_prompt.cpp
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(nostalgia_prompt pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn)
|
||||
pico_enable_stdio_usb(nostalgia_prompt 1)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(nostalgia_prompt)
|
||||
|
||||
|
||||
|
||||
add_executable(
|
||||
eighties_super_computer
|
||||
eighties_super_computer.cpp
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(eighties_super_computer pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn)
|
||||
pico_enable_stdio_usb(eighties_super_computer 1)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(eighties_super_computer)
|
||||
|
||||
|
||||
|
||||
|
||||
add_executable(
|
||||
fire_effect
|
||||
fire_effect.cpp
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(fire_effect pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn)
|
||||
pico_enable_stdio_usb(fire_effect 1)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(fire_effect)
|
||||
|
||||
|
||||
|
||||
|
||||
add_executable(
|
||||
scroll_text
|
||||
scroll_text.cpp
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(scroll_text pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn)
|
||||
pico_enable_stdio_usb(scroll_text 1)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(scroll_text)
|
||||
|
||||
|
||||
add_executable(
|
||||
balls
|
||||
balls.cpp
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(balls pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn)
|
||||
pico_enable_stdio_usb(balls 1)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(balls)
|
||||
|
||||
|
||||
|
||||
add_executable(
|
||||
lava_lamp
|
||||
lava_lamp.cpp
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(lava_lamp pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn)
|
||||
pico_enable_stdio_usb(lava_lamp 1)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(lava_lamp)
|
||||
|
||||
|
||||
|
||||
add_executable(
|
||||
feature_test
|
||||
feature_test.cpp
|
||||
audio_samples.cpp
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(feature_test pico_stdlib hardware_pio hardware_adc hardware_dma pico_graphics galactic_unicorn)
|
||||
pico_enable_stdio_usb(feature_test 1)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(feature_test)
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,88 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||
#include "galactic_unicorn.hpp"
|
||||
#include "okcolor.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
PicoGraphics_PenRGB565 graphics(53, 11, nullptr);
|
||||
GalacticUnicorn galactic_unicorn;
|
||||
|
||||
// extra row of pixels for sourcing flames and averaging
|
||||
float heat[53][13] = {0.0f};
|
||||
|
||||
int main() {
|
||||
|
||||
stdio_init_all();
|
||||
|
||||
galactic_unicorn.init();
|
||||
|
||||
while(true) {
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) {
|
||||
galactic_unicorn.adjust_brightness(+0.01);
|
||||
}
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) {
|
||||
galactic_unicorn.adjust_brightness(-0.01);
|
||||
}
|
||||
|
||||
graphics.set_pen(0, 0, 0);
|
||||
graphics.clear();
|
||||
|
||||
|
||||
for(int y = 0; y < 12; y++) {
|
||||
for(int x = 0; x < 53; x++) {
|
||||
if(heat[x][y] > 0.5f) {
|
||||
graphics.set_pen(255, 255, 180);
|
||||
graphics.pixel(Point(x, y));
|
||||
}else if(heat[x][y] > 0.4f) {
|
||||
graphics.set_pen(220, 160, 0);
|
||||
graphics.pixel(Point(x, y));
|
||||
}else if(heat[x][y] > 0.3f) {
|
||||
graphics.set_pen(180, 50, 0);
|
||||
graphics.pixel(Point(x, y));
|
||||
}else if(heat[x][y] > 0.2f) {
|
||||
graphics.set_pen(40, 40, 40);
|
||||
graphics.pixel(Point(x, y));
|
||||
}
|
||||
|
||||
// update this pixel by averaging the below pixels
|
||||
if(x == 0) {
|
||||
heat[x][y] = (heat[x][y] + heat[x][y + 2] + heat[x][y + 1] + heat[x + 1][y + 1]) / 4.0f;
|
||||
} else if(x == 52) {
|
||||
heat[x][y] = (heat[x][y] + heat[x][y + 2] + heat[x][y + 1] + heat[x - 1][y + 1]) / 4.0f;
|
||||
} else {
|
||||
heat[x][y] = (heat[x][y] + heat[x][y + 2] + heat[x][y + 1] + heat[x - 1][y + 1] + heat[x + 1][y + 1]) / 5.0f;
|
||||
}
|
||||
|
||||
heat[x][y] -= 0.01f;
|
||||
heat[x][y] = heat[x][y] < 0.0f ? 0.0f: heat[x][y];
|
||||
}
|
||||
}
|
||||
|
||||
galactic_unicorn.update(graphics);
|
||||
|
||||
// clear the bottom row and then add a new fire seed to it
|
||||
for(int x = 0; x < 53; x++) {
|
||||
heat[x][11] = 0.0f;
|
||||
}
|
||||
|
||||
// add a new random heat source
|
||||
for(int c = 0; c < 5; c++) {
|
||||
int px = (rand() % 51) + 1;
|
||||
heat[px][11] = 1.0f;
|
||||
heat[px + 1][11] = 1.0f;
|
||||
heat[px - 1][11] = 1.0f;
|
||||
heat[px][12] = 1.0f;
|
||||
heat[px + 1][12] = 1.0f;
|
||||
heat[px - 1][12] = 1.0f;
|
||||
}
|
||||
|
||||
sleep_ms(50);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -114,6 +114,9 @@ gpio_set_function(28, GPIO_FUNC_SIO);
|
|||
float brightness = 0.5f;
|
||||
float curve = 4.0f;
|
||||
|
||||
int x = 10;
|
||||
int y = 5;
|
||||
|
||||
while(true) {
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_UP)) {
|
||||
hue_offset += 0.05;
|
||||
|
@ -143,6 +146,27 @@ gpio_set_function(28, GPIO_FUNC_SIO);
|
|||
if(curve < 0.5) curve = 0.5;
|
||||
}
|
||||
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) {
|
||||
x -= 1;
|
||||
sleep_ms(250);
|
||||
}
|
||||
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_B)) {
|
||||
x += 1;
|
||||
sleep_ms(250);
|
||||
}
|
||||
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_C)) {
|
||||
y -= 1;
|
||||
sleep_ms(250);
|
||||
}
|
||||
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_D)) {
|
||||
y += 1;
|
||||
sleep_ms(250);
|
||||
}
|
||||
|
||||
/*
|
||||
for(int y = 0; y < 11; y++) {
|
||||
for(int x = 0; x < 53; x++) {
|
||||
float fx = x / 53.0f;
|
||||
|
@ -150,27 +174,18 @@ gpio_set_function(28, GPIO_FUNC_SIO);
|
|||
float twopi = M_PI * 2;
|
||||
float hue = fy + (sin(fx * twopi / curve));
|
||||
float fade = 1.0f;
|
||||
/* if(hue < 0.0f) {
|
||||
fade += (hue * 10.0f);
|
||||
if(fade < 0.0f) fade = 0.0f;
|
||||
}
|
||||
if(hue > 1.0f) {
|
||||
fade -= ((hue - 1.0f) * 10.0f);
|
||||
if(fade < 0.0f) fade = 0.0f;
|
||||
}*/
|
||||
|
||||
hue += hue_offset;
|
||||
while(hue < 0.0f) {hue += 1.0f;}
|
||||
while(hue > 1.0f) {hue -= 1.0f;}
|
||||
hue = 1.0f - hue;
|
||||
/*
|
||||
uint8_t r = 0, g = 0, b = 0;
|
||||
from_hsv(hue, 1.0f, brightness * fade, r, g, b);*/
|
||||
ok_color::HSL hsl{.h = hue, .s = 1.0f, .l = brightness * fade};
|
||||
ok_color::RGB rgb = ok_color::okhsl_to_srgb(hsl);
|
||||
galactic_unicorn.set_pixel(x, y, rgb.r * 255.0f, rgb.g * 255.0f, rgb.b * 255.0f);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
galactic_unicorn.set_pixel(x, y, 255, 255, 255);
|
||||
/*i++;
|
||||
|
||||
graphics.set_pen(0, 0, 0);
|
||||
|
|
|
@ -37,9 +37,9 @@ void text(std::string t, Point p, float s = 1.0f, float a = 1.0f) {
|
|||
p.x += (53 / 2) - (w / 2);
|
||||
p.y += (11 / 2);
|
||||
graphics.text(t, Point(p.x, p.y), -1, s, a);
|
||||
graphics.text(t, Point(p.x + 1, p.y), -1, s, a);
|
||||
graphics.text(t, Point(p.x + 1, p.y + 1), -1, s, a);
|
||||
graphics.text(t, Point(p.x, p.y + 1), -1, s, a);
|
||||
//graphics.text(t, Point(p.x + 1, p.y), -1, s, a);
|
||||
//graphics.text(t, Point(p.x + 1, p.y + 1), -1, s, a);
|
||||
//graphics.text(t, Point(p.x, p.y + 1), -1, s, a);
|
||||
}
|
||||
|
||||
struct star_t {
|
||||
|
@ -73,6 +73,8 @@ void step_star(star_t &s) {
|
|||
|
||||
int main() {
|
||||
|
||||
stdio_init_all();
|
||||
|
||||
uint8_t hue_map[53][3];
|
||||
for(int i = 0; i < 53; i++) {
|
||||
from_hsv(i / 53.0f, 1.0f, 1.0f, hue_map[i][0], hue_map[i][1], hue_map[i][2]);
|
||||
|
@ -103,18 +105,17 @@ gpio_set_function(28, GPIO_FUNC_SIO);
|
|||
bool x_pressed = false;
|
||||
bool y_pressed = false;
|
||||
*/
|
||||
graphics.set_font("sans");
|
||||
graphics.set_font("bitmap8");
|
||||
|
||||
|
||||
|
||||
uint i = 0;
|
||||
int v = 255;
|
||||
|
||||
float hue_offset = 0.0f;
|
||||
float brightness = 0.5f;
|
||||
float curve = 4.0f;
|
||||
|
||||
while(true) {
|
||||
i++;
|
||||
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_VOLUME_UP)) {
|
||||
hue_offset += 0.05;
|
||||
if(hue_offset > 1.0f) hue_offset = 1.0f;
|
||||
|
@ -125,69 +126,37 @@ gpio_set_function(28, GPIO_FUNC_SIO);
|
|||
}
|
||||
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) {
|
||||
brightness += 0.05;
|
||||
if(brightness > 1.0f) brightness = 1.0f;
|
||||
galactic_unicorn.adjust_brightness(+0.01);
|
||||
}
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) {
|
||||
brightness -= 0.05;
|
||||
if(brightness < 0.0f) brightness = 0.0f;
|
||||
galactic_unicorn.adjust_brightness(-0.01);
|
||||
}
|
||||
|
||||
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) {
|
||||
curve += 0.5;
|
||||
if(curve > 100.0f) curve = 100.0f;
|
||||
}
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_B)) {
|
||||
curve -= 0.5;
|
||||
if(curve < 0.5) curve = 0.5;
|
||||
}
|
||||
i++;
|
||||
|
||||
graphics.set_pen(0, 0, 0);
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_A)) {graphics.set_pen(255, 0, 0);}
|
||||
graphics.clear();
|
||||
|
||||
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) {v = v == 0 ? 0 : v - 1;}
|
||||
|
||||
|
||||
for(int i = 0; i < 100; i++) {
|
||||
star_t &star = stars[i];
|
||||
step_star(star);
|
||||
|
||||
uint b = star.brightness();
|
||||
graphics.set_pen(b, b, b);
|
||||
//graphics.pixel(Point(star.x + (53 / 2), star.y + (11 / 2)));
|
||||
}
|
||||
|
||||
graphics.set_pen(255, 255, 255);
|
||||
float s = 0.8f;//0.65f + (sin(i / 25.0f) * 0.15f);
|
||||
/*
|
||||
graphics.set_pen(255, 255, 255);
|
||||
float s = 0.65f;//0.65f + (sin(i / 25.0f) * 0.15f);
|
||||
float a = 1.0f;// (sin(i / 25.0f) * 100.0f);
|
||||
float x = (sin(i / 25.0f) * 40.0f) * s;
|
||||
float y = (cos(i / 15.0f) * 10.0f) * s;
|
||||
text("Galactic", Point(x, y), s, a);
|
||||
|
||||
uint16_t *p = (uint16_t *)graphics.frame_buffer;
|
||||
for(size_t i = 0; i < 53 * 11; i++) {
|
||||
int x = i % 53;
|
||||
int y = i / 53;
|
||||
uint r = ((*p & 0b1111100000000000) >> 11) << 3;
|
||||
uint g = ((*p & 0b0000011111100000) >> 5) << 2;
|
||||
uint b = ((*p & 0b0000000000011111) >> 0) << 3;
|
||||
p++;
|
||||
float x = (sin(i / 74.0f) * 80.0f) * s;
|
||||
float y = (cos(i / 43.0f) * 6.0f) * s;
|
||||
text("Chester smells!", Point(x, y - 3), s, a);
|
||||
*/
|
||||
|
||||
if(r > 200 && g > 200 && b > 200) {
|
||||
r = hue_map[x][0];
|
||||
g = hue_map[x][1];
|
||||
b = hue_map[x][2];
|
||||
for(int x = 0; x < 53; x++) {
|
||||
for(int y = 0; y < 11; y++) {
|
||||
int v = ((sin((x + y) / 3.0f + i / 15.0f) + 1.5f) / 2.5f) * 255.0f;
|
||||
|
||||
graphics.set_pen(v, v, v);
|
||||
graphics.pixel(Point(x, y));
|
||||
}
|
||||
|
||||
galactic_unicorn.set_pixel(x, y, r, g, b);
|
||||
}
|
||||
|
||||
galactic_unicorn.update(graphics);
|
||||
|
||||
|
||||
|
||||
sleep_ms(10);
|
||||
printf("%d\n", galactic_unicorn.light());
|
||||
sleep_ms(20);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||
#include "galactic_unicorn.hpp"
|
||||
#include "okcolor.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
PicoGraphics_PenRGB565 graphics(53, 11, nullptr);
|
||||
GalacticUnicorn galactic_unicorn;
|
||||
|
||||
float lifetime[53][11];
|
||||
float age[53][11];
|
||||
|
||||
int main() {
|
||||
|
||||
stdio_init_all();
|
||||
|
||||
for(int y = 0; y < 11; y++) {
|
||||
for(int x = 0; x < 53; x++) {
|
||||
lifetime[x][y] = 1.0f + ((rand() % 10) / 100.0f);
|
||||
age[x][y] = ((rand() % 100) / 100.0f) * lifetime[x][y];
|
||||
}
|
||||
}
|
||||
|
||||
galactic_unicorn.init();
|
||||
|
||||
while(true) {
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) {
|
||||
galactic_unicorn.adjust_brightness(+0.01);
|
||||
}
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) {
|
||||
galactic_unicorn.adjust_brightness(-0.01);
|
||||
}
|
||||
|
||||
graphics.set_pen(0, 0, 0);
|
||||
graphics.clear();
|
||||
|
||||
|
||||
for(int y = 0; y < 11; y++) {
|
||||
for(int x = 0; x < 53; x++) {
|
||||
if(age[x][y] < lifetime[x][y] * 0.3f) {
|
||||
graphics.set_pen(230, 150, 0);
|
||||
graphics.pixel(Point(x, y));
|
||||
}else if(age[x][y] < lifetime[x][y] * 0.5f) {
|
||||
float decay = (lifetime[x][y] * 0.5f - age[x][y]) * 5.0f;
|
||||
graphics.set_pen(decay * 230, decay * 150, 0);
|
||||
graphics.pixel(Point(x, y));
|
||||
}
|
||||
|
||||
if(age[x][y] >= lifetime[x][y]) {
|
||||
age[x][y] = 0.0f;
|
||||
lifetime[x][y] = 1.0f + ((rand() % 10) / 100.0f);
|
||||
}
|
||||
|
||||
age[x][y] += 0.01f;
|
||||
}
|
||||
}
|
||||
|
||||
galactic_unicorn.update(graphics);
|
||||
|
||||
sleep_ms(10);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||
#include "galactic_unicorn.hpp"
|
||||
#include "okcolor.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
PicoGraphics_PenRGB565 graphics(53, 11, nullptr);
|
||||
GalacticUnicorn galactic_unicorn;
|
||||
|
||||
// left_channel_bin and right_channel_bin are in audio_samples.cpp
|
||||
extern uint8_t left_channel_bin[];
|
||||
extern uint32_t left_channel_bin_len;
|
||||
extern uint8_t right_channel_bin[];
|
||||
extern uint32_t right_channel_bin_len;
|
||||
|
||||
void gradient(uint8_t r, uint8_t g, uint8_t b) {
|
||||
for(int y = 0; y < 12; y++) {
|
||||
for(int x = 0; x < 53; x++) {
|
||||
graphics.set_pen((r * x) / 52, (g * x) / 52, (b * x) / 52);
|
||||
graphics.pixel(Point(x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*shader_func_t)(int ms, int x, int y);
|
||||
|
||||
void grid(int ms, int x, int y) {
|
||||
int v = (x + y + (ms / 1000)) % 2 == 0 ? 255 : 0;
|
||||
graphics.set_pen(v, v, v);
|
||||
graphics.pixel(Point(x, y));
|
||||
}
|
||||
|
||||
void shader_fill(int ms, shader_func_t f) {
|
||||
for(int y = 0; y < 12; y++) {
|
||||
for(int x = 0; x < 53; x++) {
|
||||
f(ms, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void outline_text(std::string text) {
|
||||
uint ms = to_ms_since_boot(get_absolute_time());
|
||||
|
||||
graphics.set_font("bitmap8");
|
||||
uint8_t v = (sin(ms / 100.0f) + 1.0f) * 127.0f;
|
||||
uint w = graphics.measure_text(text, 1);
|
||||
|
||||
int x = 53 / 2 - w / 2 + 1, y = 2;
|
||||
|
||||
graphics.set_pen(0, 0, 0);
|
||||
graphics.text(text, Point(x - 1, y - 1), -1, 1);
|
||||
graphics.text(text, Point(x , y - 1), -1, 1);
|
||||
graphics.text(text, Point(x + 1, y - 1), -1, 1);
|
||||
graphics.text(text, Point(x - 1, y ), -1, 1);
|
||||
graphics.text(text, Point(x + 1, y ), -1, 1);
|
||||
graphics.text(text, Point(x - 1, y + 1), -1, 1);
|
||||
graphics.text(text, Point(x , y + 1), -1, 1);
|
||||
graphics.text(text, Point(x + 1, y + 1), -1, 1);
|
||||
|
||||
graphics.set_pen(v, v, v);
|
||||
graphics.text(text, Point(x, y), -1, 1);
|
||||
}
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
|
||||
galactic_unicorn.init();
|
||||
|
||||
// galactic_unicorn.play_sample(left_channel_bin, left_channel_bin_len);
|
||||
|
||||
while(true) {
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) {
|
||||
galactic_unicorn.adjust_brightness(+0.01);
|
||||
}
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) {
|
||||
galactic_unicorn.adjust_brightness(-0.01);
|
||||
}
|
||||
|
||||
uint ms = to_ms_since_boot(get_absolute_time());
|
||||
|
||||
uint8_t test = (ms / 5000) % 4;
|
||||
|
||||
graphics.set_pen(0, 0, 0);
|
||||
graphics.clear();
|
||||
|
||||
switch(test) {
|
||||
case 0: {
|
||||
printf("grid pattern");
|
||||
shader_fill(ms, grid);
|
||||
}break;
|
||||
|
||||
case 1: {
|
||||
printf("green gradient");
|
||||
gradient(0, 255, 0);
|
||||
}break;
|
||||
|
||||
case 2: {
|
||||
printf("blue gradient");
|
||||
gradient(0, 0, 255);
|
||||
}break;
|
||||
|
||||
case 3: {
|
||||
printf("white gradient");
|
||||
gradient(255, 255, 255);
|
||||
}break;
|
||||
}
|
||||
|
||||
printf("%d\n", galactic_unicorn.light());
|
||||
|
||||
std::string text = "";
|
||||
if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_A)) {
|
||||
text = "Button A";
|
||||
}
|
||||
if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_B)) {
|
||||
text = "Button B";
|
||||
}
|
||||
if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_C)) {
|
||||
text = "Button C";
|
||||
}
|
||||
if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_D)) {
|
||||
text = "Button D";
|
||||
}
|
||||
if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_VOLUME_UP)) {
|
||||
text = "Louder!";
|
||||
}
|
||||
if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_VOLUME_DOWN)) {
|
||||
text = "quieter";
|
||||
}
|
||||
if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_BRIGHTNESS_UP)) {
|
||||
text = "Brighter!";
|
||||
}
|
||||
if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_BRIGHTNESS_DOWN)) {
|
||||
text = "Darker";
|
||||
}
|
||||
if(galactic_unicorn.is_pressed(GalacticUnicorn::SWITCH_SLEEP)) {
|
||||
text = "Zzz... zzz...";
|
||||
}
|
||||
|
||||
outline_text(text);
|
||||
|
||||
graphics.set_pen(255, 255, 255);
|
||||
graphics.clear();
|
||||
|
||||
galactic_unicorn.update(graphics);
|
||||
|
||||
sleep_ms(50);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||
#include "galactic_unicorn.hpp"
|
||||
#include "okcolor.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
PicoGraphics_PenRGB565 graphics(53, 11, nullptr);
|
||||
GalacticUnicorn galactic_unicorn;
|
||||
|
||||
// extra row of pixels for sourcing flames and averaging
|
||||
float heat[53][15] = {0.0f};
|
||||
|
||||
int main() {
|
||||
|
||||
stdio_init_all();
|
||||
|
||||
galactic_unicorn.init();
|
||||
|
||||
while(true) {
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) {
|
||||
galactic_unicorn.adjust_brightness(+0.01);
|
||||
}
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) {
|
||||
galactic_unicorn.adjust_brightness(-0.01);
|
||||
}
|
||||
|
||||
graphics.set_pen(0, 0, 0);
|
||||
graphics.clear();
|
||||
|
||||
|
||||
for(int y = 0; y < 14; y++) {
|
||||
for(int x = 0; x < 53; x++) {
|
||||
if(heat[x][y] > 0.5f) {
|
||||
graphics.set_pen(255, 255, 180);
|
||||
graphics.pixel(Point(x, y));
|
||||
}else if(heat[x][y] > 0.4f) {
|
||||
graphics.set_pen(220, 160, 0);
|
||||
graphics.pixel(Point(x, y));
|
||||
}else if(heat[x][y] > 0.3f) {
|
||||
graphics.set_pen(180, 50, 0);
|
||||
graphics.pixel(Point(x, y));
|
||||
}else if(heat[x][y] > 0.2f) {
|
||||
graphics.set_pen(40, 40, 40);
|
||||
graphics.pixel(Point(x, y));
|
||||
}
|
||||
|
||||
// update this pixel by averaging the below pixels
|
||||
if(x == 0) {
|
||||
heat[x][y] = (heat[x][y] + heat[x][y + 2] + heat[x][y + 1] + heat[x + 1][y + 1]) / 4.0f;
|
||||
} else if(x == 52) {
|
||||
heat[x][y] = (heat[x][y] + heat[x][y + 2] + heat[x][y + 1] + heat[x - 1][y + 1]) / 4.0f;
|
||||
} else {
|
||||
heat[x][y] = (heat[x][y] + heat[x][y + 2] + heat[x][y + 1] + heat[x - 1][y + 1] + heat[x + 1][y + 1]) / 5.0f;
|
||||
}
|
||||
|
||||
heat[x][y] -= 0.01f;
|
||||
heat[x][y] = heat[x][y] < 0.0f ? 0.0f: heat[x][y];
|
||||
}
|
||||
}
|
||||
|
||||
galactic_unicorn.update(graphics);
|
||||
|
||||
// clear the bottom row and then add a new fire seed to it
|
||||
for(int x = 0; x < 53; x++) {
|
||||
heat[x][14] = 0.0f;
|
||||
}
|
||||
|
||||
// add a new random heat source
|
||||
for(int c = 0; c < 5; c++) {
|
||||
int px = (rand() % 51) + 1;
|
||||
heat[px][13] = 1.0f;
|
||||
heat[px + 1][13] = 1.0f;
|
||||
heat[px - 1][13] = 1.0f;
|
||||
heat[px][14] = 1.0f;
|
||||
heat[px + 1][14] = 1.0f;
|
||||
heat[px - 1][14] = 1.0f;
|
||||
}
|
||||
|
||||
sleep_ms(50);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||
#include "galactic_unicorn.hpp"
|
||||
#include "okcolor.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
PicoGraphics_PenRGB565 graphics(53, 11, nullptr);
|
||||
GalacticUnicorn galactic_unicorn;
|
||||
|
||||
// HSV Conversion expects float inputs in the range of 0.00-1.00 for each channel
|
||||
// Outputs are rgb in the range 0-255 for each channel
|
||||
void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b) {
|
||||
float i = floor(h * 6.0f);
|
||||
float f = h * 6.0f - i;
|
||||
v *= 255.0f;
|
||||
uint8_t p = v * (1.0f - s);
|
||||
uint8_t q = v * (1.0f - f * s);
|
||||
uint8_t t = v * (1.0f - (1.0f - f) * s);
|
||||
|
||||
switch (int(i) % 6) {
|
||||
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;
|
||||
case 5: r = v; g = p; b = q; break;
|
||||
}
|
||||
}
|
||||
|
||||
struct blob_t {
|
||||
float x, y;
|
||||
float r;
|
||||
float dx, dy;
|
||||
};
|
||||
|
||||
constexpr int blob_count = 20;
|
||||
|
||||
int main() {
|
||||
|
||||
stdio_init_all();
|
||||
|
||||
galactic_unicorn.init();
|
||||
|
||||
// randomise blob start positions, directions, and size
|
||||
std::array<blob_t, blob_count> blobs;
|
||||
for(auto &blob : blobs) {
|
||||
blob.x = rand() % 11;
|
||||
blob.y = rand() % 53;
|
||||
blob.r = ((rand() % 40) / 10.0f) + 5.0f;
|
||||
blob.dx = ((rand() % 2) / 10.0f) - 0.05f;
|
||||
blob.dy = ((rand() % 3) / 10.0f) - 0.1f;
|
||||
}
|
||||
|
||||
float hue = 0.0f;
|
||||
|
||||
while(true) {
|
||||
// allow user to adjust brightness
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) {
|
||||
galactic_unicorn.adjust_brightness(+0.01);
|
||||
}
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) {
|
||||
galactic_unicorn.adjust_brightness(-0.01);
|
||||
}
|
||||
|
||||
uint start_ms = to_ms_since_boot(get_absolute_time());
|
||||
|
||||
// calculate the influence of each blob on the liquid based
|
||||
// on their distance to each pixel. this causes blobs to
|
||||
// "merge" into each other when we use fixed thresholds to
|
||||
// determine which colour to draw with
|
||||
float liquid[11][53] = {0.0f};
|
||||
for(auto &blob : blobs) {
|
||||
float r_sq = blob.r * blob.r;
|
||||
for(int y = 0; y < 53; y++) {
|
||||
for(int x = 0; x < 11; x++) {
|
||||
float d_sq = (x - blob.x) * (x - blob.x) + (y - blob.y) * (y - blob.y);
|
||||
if(d_sq <= r_sq) {
|
||||
// add this blobs influence to this pixel
|
||||
liquid[x][y] += 1.0f - (d_sq / r_sq);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update the blob positions
|
||||
for(auto &blob : blobs) {
|
||||
blob.x += blob.dx;
|
||||
blob.y += blob.dy;
|
||||
|
||||
// if we hit the edge then bounce!
|
||||
if(blob.x < 0.0f || blob.x >= 11.0f) {
|
||||
blob.dx *= -1.0f;
|
||||
}
|
||||
if(blob.y < 0.0f || blob.y >= 53.0f) {
|
||||
blob.dy *= -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// rotate the hue
|
||||
hue += 0.001f;
|
||||
|
||||
// calculate dark, medium, and bright shades for rendering the
|
||||
// lava
|
||||
uint8_t dark_r, dark_g, dark_b;
|
||||
from_hsv(hue, 1.0f, 0.3f, dark_r, dark_g, dark_b);
|
||||
uint8_t mid_r, mid_g, mid_b;
|
||||
from_hsv(hue, 1.0f, 0.6f, mid_r, mid_g, mid_b);
|
||||
uint8_t bright_r, bright_g, bright_b;
|
||||
from_hsv(hue, 1.0f, 1.0f, bright_r, bright_g, bright_b);
|
||||
|
||||
// clear the canvas
|
||||
graphics.set_pen(0, 0, 0);
|
||||
graphics.clear();
|
||||
|
||||
// render the lava
|
||||
for(int y = 0; y < 53; y++) {
|
||||
for(int x = 0; x < 11; x++) {
|
||||
float v = liquid[x][y];
|
||||
|
||||
// select a colour for this pixel based on how much
|
||||
// "blobfluence" there is at this position in the liquid
|
||||
if(v >= 1.5f) {
|
||||
graphics.set_pen(bright_r, bright_g, bright_b);
|
||||
graphics.pixel(Point(y, x));
|
||||
}else if(v >= 1.25f) {
|
||||
graphics.set_pen(mid_r, mid_g, mid_b);
|
||||
graphics.pixel(Point(y, x));
|
||||
}else if(v >= 1.0f) {
|
||||
graphics.set_pen(dark_r, dark_g, dark_b);
|
||||
graphics.pixel(Point(y, x));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint end_ms = to_ms_since_boot(get_absolute_time());
|
||||
|
||||
printf("rendering took %dms\n", end_ms - start_ms);
|
||||
|
||||
galactic_unicorn.update(graphics);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||
#include "galactic_unicorn.hpp"
|
||||
#include "okcolor.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
PicoGraphics_PenRGB565 graphics(53, 11, nullptr);
|
||||
GalacticUnicorn galactic_unicorn;
|
||||
|
||||
std::array<std::string, 11> c64 = {
|
||||
"",
|
||||
" OOOOO OOOOOO OO OOOO OO OO XXXXXXX",
|
||||
" OO OO OO OOOO OO OO OO OO XXXXXXX",
|
||||
" OO OO OO OO OO OO OO OO OO XXXXXXX",
|
||||
" OOOOO OOOO OOOOOO OO OO OOOO XXXXXXX",
|
||||
" OOOO OO OO OO OO OO OO XXXXXXX",
|
||||
" OO OO OO OO OO OO OO OO OO XXXXXXX",
|
||||
" OO OO OOOOOO OO OO OOOO OO OO XXXXXXX",
|
||||
" XXXXXXX"
|
||||
};
|
||||
|
||||
std::array<std::string, 11> spectrum = {
|
||||
"",
|
||||
" O OOOO OOOO OOOOO O O O O XXXXXXXX",
|
||||
" O O O O O O O O O O O X XXXXXX",
|
||||
" O O O O O O O X XXXXXX",
|
||||
" O O O OOOOOO O O X XXXXXX",
|
||||
" O O O O O O O X XXXXXX",
|
||||
" OOOOOO OOOO O O OOOOO X XXXXXX",
|
||||
" X X",
|
||||
" XXXXXXXX"
|
||||
};
|
||||
|
||||
std::array<std::string, 11> bbc_micro = {
|
||||
"",
|
||||
" OOOOO OO OOOO OOO OOOO O ",
|
||||
" O O O O O O O O O O ",
|
||||
" O O O O O O O O ",
|
||||
" OOOOO O O OOOO O O O ",
|
||||
" O O OOOOOO O O O O ",
|
||||
" O O O O O O O O O O ",
|
||||
" OOOOO O O OOOO OOO OOOO O ",
|
||||
" XXXXXXX"
|
||||
};
|
||||
|
||||
|
||||
constexpr uint PROMPT_C64 = 0;
|
||||
constexpr uint PROMPT_SPECTRUM = 1;
|
||||
constexpr uint PROMPT_BBC_MICRO = 2;
|
||||
uint prompt = 0;
|
||||
|
||||
int main() {
|
||||
|
||||
stdio_init_all();
|
||||
|
||||
galactic_unicorn.init();
|
||||
|
||||
while(true) {
|
||||
uint time_ms = to_ms_since_boot(get_absolute_time());
|
||||
|
||||
prompt = (time_ms / 3000) % 3;
|
||||
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) {
|
||||
galactic_unicorn.adjust_brightness(+0.01);
|
||||
}
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) {
|
||||
galactic_unicorn.adjust_brightness(-0.01);
|
||||
}
|
||||
|
||||
std::array<std::string, 11> image = c64;
|
||||
if(prompt == PROMPT_C64) {
|
||||
image = c64;
|
||||
}else if(prompt == PROMPT_SPECTRUM) {
|
||||
image = spectrum;
|
||||
}else if(prompt == PROMPT_BBC_MICRO) {
|
||||
image = bbc_micro;
|
||||
}
|
||||
|
||||
if(prompt == PROMPT_C64) {
|
||||
graphics.set_pen(20, 20, 120);
|
||||
}else if(prompt == PROMPT_SPECTRUM){
|
||||
graphics.set_pen(180, 150, 150);
|
||||
}else if(prompt == PROMPT_BBC_MICRO){
|
||||
graphics.set_pen(0, 0, 0);
|
||||
}
|
||||
|
||||
graphics.clear();
|
||||
|
||||
if(prompt == PROMPT_C64) {
|
||||
graphics.set_pen(230, 210, 250);
|
||||
}else if(prompt == PROMPT_SPECTRUM){
|
||||
graphics.set_pen(0, 0, 0);
|
||||
}else if(prompt == PROMPT_BBC_MICRO){
|
||||
graphics.set_pen(255, 255, 255);
|
||||
}
|
||||
|
||||
for(size_t y = 0; y < image.size(); y++) {
|
||||
for(size_t x = 0; x < image[y].length(); x++) {
|
||||
// draw the prompt text
|
||||
if(image[y][x] == 'O') {
|
||||
graphics.pixel(Point(x, y + 1));
|
||||
}
|
||||
|
||||
// draw the caret blinking
|
||||
if(image[y][x] == 'X' && (time_ms / 300) % 2) {
|
||||
graphics.pixel(Point(x, y + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
galactic_unicorn.update(graphics);
|
||||
|
||||
sleep_ms(10);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||
#include "galactic_unicorn.hpp"
|
||||
#include "okcolor.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
PicoGraphics_PenRGB565 graphics(53, 11, nullptr);
|
||||
GalacticUnicorn galactic_unicorn;
|
||||
|
||||
std::string message = "Pirate. Monkey. Robot. Ninja.";
|
||||
|
||||
int main() {
|
||||
|
||||
stdio_init_all();
|
||||
|
||||
galactic_unicorn.init();
|
||||
|
||||
float scroll = -53.0f;
|
||||
|
||||
while(true) {
|
||||
//uint time_ms = to_ms_since_boot(get_absolute_time());
|
||||
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_UP)) {
|
||||
galactic_unicorn.adjust_brightness(+0.01);
|
||||
}
|
||||
if(galactic_unicorn.is_pressed(galactic_unicorn.SWITCH_BRIGHTNESS_DOWN)) {
|
||||
galactic_unicorn.adjust_brightness(-0.01);
|
||||
}
|
||||
|
||||
int width = graphics.measure_text(message, 1);
|
||||
scroll += 0.25f;
|
||||
|
||||
if(scroll > width) {
|
||||
scroll = -53.0f;
|
||||
}
|
||||
|
||||
graphics.set_pen(0, 0, 0);
|
||||
graphics.clear();
|
||||
|
||||
ok_color::HSL hsl{scroll / 100.0f, 1.0f, 0.5f};
|
||||
ok_color::RGB rgb = ok_color::okhsl_to_srgb(hsl);
|
||||
graphics.set_pen(rgb.r * 255, rgb.g * 255, rgb.b * 255);
|
||||
graphics.text(message, Point(0 - scroll, 5), -1, 0.55);
|
||||
/*graphics.text(message, Point(0 - scroll + 1, 5), -1, 0.5);
|
||||
graphics.text(message, Point(0 - scroll, 5 + 1), -1, 0.5);
|
||||
graphics.text(message, Point(0 - scroll + 1, 5 + 1), -1, 0.5);*/
|
||||
/*
|
||||
for(int x = 0; x < 53; x++) {
|
||||
for(int y = 0; y < 2; y++) {
|
||||
float b = sin((x - y * 3 + int(scroll) + 100) / 3.0f);
|
||||
graphics.set_pen(180 * b, 150 * b, 0);
|
||||
graphics.pixel(Point(52 - x, y));
|
||||
graphics.pixel(Point(52 - x, y + 9));
|
||||
}
|
||||
}*/
|
||||
|
||||
galactic_unicorn.update(graphics);
|
||||
|
||||
sleep_ms(10);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,12 +1 @@
|
|||
add_library(galactic_unicorn INTERFACE)
|
||||
|
||||
pico_generate_pio_header(galactic_unicorn ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.pio)
|
||||
|
||||
target_sources(galactic_unicorn INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.cpp
|
||||
)
|
||||
|
||||
target_include_directories(galactic_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(galactic_unicorn INTERFACE pico_stdlib hardware_pio hardware_dma)
|
||||
include(galactic_unicorn.cmake)
|
|
@ -17,6 +17,7 @@ We've included helper functions to handle every aspect of drawing to the display
|
|||
- [init](#init)
|
||||
- [set_pixel](#set_pixel)
|
||||
- [is_pressed](#is_pressed)
|
||||
- [Examples](#examples)
|
||||
|
||||
## Example Program
|
||||
|
||||
|
@ -98,4 +99,16 @@ The button vaule should be a `uint8_t` denoting a pin, and constants `A`, `B`, `
|
|||
|
||||
```c++
|
||||
bool is_a_button_pressed = pico_unicorn.is_pressed(PicoUnicorn::A)
|
||||
```
|
||||
```
|
||||
|
||||
# Examples
|
||||
|
||||
## Game of Life
|
||||
|
||||
## Retro Super-computer
|
||||
|
||||
Random LEDs blink on and off mimicing the look of a movie super computer doing it's work in the eighties.
|
||||
|
||||
## Nostalgia Terminal
|
||||
|
||||
A collection of copies of classic terminal styles including C64, MS-DOS, Spectrum, and more.
|
|
@ -0,0 +1,63 @@
|
|||
;
|
||||
; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
;
|
||||
; SPDX-License-Identifier: BSD-3-Clause
|
||||
;
|
||||
|
||||
; Transmit a mono or stereo I2S audio stream as stereo
|
||||
; This is 16 bits per sample; can be altered by modifying the "set" params,
|
||||
; or made programmable by replacing "set x" with "mov x, y" and using Y as a config register.
|
||||
;
|
||||
; Autopull must be enabled, with threshold set to 32.
|
||||
; Since I2S is MSB-first, shift direction should be to left.
|
||||
; Hence the format of the FIFO word is:
|
||||
;
|
||||
; | 31 : 16 | 15 : 0 |
|
||||
; | sample ws=0 | sample ws=1 |
|
||||
;
|
||||
; Data is output at 1 bit per clock. Use clock divider to adjust frequency.
|
||||
; Fractional divider will probably be needed to get correct bit clock period,
|
||||
; but for common syslck freqs this should still give a constant word select period.
|
||||
;
|
||||
; One output pin is used for the data output.
|
||||
; Two side-set pins are used. Bit 0 is clock, bit 1 is word select.
|
||||
|
||||
; Send 16 bit words to the PIO for mono, 32 bit words for stereo
|
||||
|
||||
.program audio_i2s
|
||||
.side_set 2
|
||||
|
||||
; /--- LRCLK
|
||||
; |/-- BCLK
|
||||
bitloop1: ; ||
|
||||
out pins, 1 side 0b10
|
||||
jmp x-- bitloop1 side 0b11
|
||||
out pins, 1 side 0b00
|
||||
set x, 14 side 0b01
|
||||
|
||||
bitloop0:
|
||||
out pins, 1 side 0b00
|
||||
jmp x-- bitloop0 side 0b01
|
||||
out pins, 1 side 0b10
|
||||
public entry_point:
|
||||
set x, 14 side 0b11
|
||||
|
||||
% c-sdk {
|
||||
|
||||
static inline void audio_i2s_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base) {
|
||||
pio_sm_config sm_config = audio_i2s_program_get_default_config(offset);
|
||||
|
||||
sm_config_set_out_pins(&sm_config, data_pin, 1);
|
||||
sm_config_set_sideset_pins(&sm_config, clock_pin_base);
|
||||
sm_config_set_out_shift(&sm_config, false, true, 32);
|
||||
|
||||
pio_sm_init(pio, sm, offset, &sm_config);
|
||||
|
||||
uint pin_mask = (1u << data_pin) | (3u << clock_pin_base);
|
||||
pio_sm_set_pindirs_with_mask(pio, sm, pin_mask, pin_mask);
|
||||
pio_sm_set_pins(pio, sm, 0); // clear pins
|
||||
|
||||
pio_sm_exec(pio, sm, pio_encode_jmp(offset + audio_i2s_offset_entry_point));
|
||||
}
|
||||
|
||||
%}
|
|
@ -1,12 +1,14 @@
|
|||
add_library(pico_unicorn INTERFACE)
|
||||
add_library(galactic_unicorn INTERFACE)
|
||||
|
||||
pico_generate_pio_header(pico_unicorn ${CMAKE_CURRENT_LIST_DIR}/pico_unicorn.pio)
|
||||
pico_generate_pio_header(galactic_unicorn ${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.pio)
|
||||
pico_generate_pio_header(galactic_unicorn ${CMAKE_CURRENT_LIST_DIR}/audio_i2s.pio)
|
||||
|
||||
target_sources(pico_unicorn INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/pico_unicorn.cpp
|
||||
|
||||
target_sources(galactic_unicorn INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/galactic_unicorn.cpp
|
||||
)
|
||||
|
||||
target_include_directories(pico_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
target_include_directories(galactic_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(pico_unicorn INTERFACE pico_stdlib hardware_pio hardware_dma)
|
||||
target_link_libraries(galactic_unicorn INTERFACE pico_stdlib pico_graphics hardware_adc hardware_pio hardware_dma)
|
||||
|
|
|
@ -2,88 +2,47 @@
|
|||
|
||||
#include "hardware/dma.h"
|
||||
#include "hardware/irq.h"
|
||||
#include "hardware/adc.h"
|
||||
#include "hardware/clocks.h"
|
||||
|
||||
|
||||
#include "galactic_unicorn.pio.h"
|
||||
#include "audio_i2s.pio.h"
|
||||
|
||||
#include "galactic_unicorn.hpp"
|
||||
|
||||
// pixel data is stored as a stream of bits delivered in the
|
||||
// order the PIO needs to manage the shift registers, row
|
||||
// selects, delays, and latching/blanking
|
||||
//
|
||||
// the data consists of 11 rows each of which has 14 frames of
|
||||
// bcd timing data
|
||||
// the pins used are:
|
||||
//
|
||||
// bits are output in order:
|
||||
// - 13: column clock (sideset)
|
||||
// - 14: column data (out base)
|
||||
// - 15: column latch
|
||||
// - 16: column blank
|
||||
// - 17: row select bit 0
|
||||
// - 18: row select bit 1
|
||||
// - 19: row select bit 2
|
||||
// - 20: row select bit 3
|
||||
//
|
||||
// ROW_CLEAR, ROW_DATA1, ROW_DATA0, LED_BLANK, LED_LATCH, LED_CLOCK, LED_DATA0, LED_DATA1
|
||||
// the framebuffer data is structured like this:
|
||||
//
|
||||
// the data is structured like this:
|
||||
//
|
||||
// loop through the eleven rows of the display...
|
||||
//
|
||||
// 1rr00000 // set row select bit on rows 0 and 8 (side set the clock)
|
||||
// 00000000 00000000 00000000 // dummy bytes to align to dwords
|
||||
//
|
||||
// within this row we loop through the 14 bcd frames for this row...
|
||||
//
|
||||
// 0 - 161: 100100rr, 100101rr, 100100gg, 100101gg, 100100bb, 100101bb, ... x 27 # left+right half rgb pixel data doubled for clock pulses, keep BLANK high
|
||||
// 162: 10011000 // LATCH pixel data
|
||||
// 163: 10000000 // turn off BLANK to output pixel data - now at 164 bytes (41 dwords)
|
||||
// 164 - 165: 00001111, 11111111, # bcd tick count (0-65536)
|
||||
// 166: 10010000 // turn BLANK back on
|
||||
// 167: 00000000 // dummy byte to ensure dword aligned
|
||||
// for each row:
|
||||
// for each bcd frame:
|
||||
// 0: 00110110 // row pixel count (minus one)
|
||||
// 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data
|
||||
// 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align
|
||||
// 56: xxxxrrrr // row select bits
|
||||
// 57 - 59: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536)
|
||||
//
|
||||
// .. and back to the start
|
||||
|
||||
/*
|
||||
enum pin {
|
||||
LED_DATA = 8,
|
||||
LED_CLOCK = 9,
|
||||
LED_LATCH = 10,
|
||||
LED_BLANK = 11,
|
||||
ROW_0 = 22,
|
||||
ROW_1 = 21,
|
||||
ROW_2 = 20,
|
||||
ROW_3 = 19,
|
||||
ROW_4 = 18,
|
||||
ROW_5 = 17,
|
||||
ROW_6 = 16,
|
||||
A = 12,
|
||||
B = 13,
|
||||
X = 14,
|
||||
Y = 15,
|
||||
};*/
|
||||
|
||||
enum pin {
|
||||
LED_DATA1 = 12,
|
||||
LED_DATA0 = 13,
|
||||
LED_CLOCK = 14,
|
||||
LED_LATCH = 15,
|
||||
LED_BLANK = 16,
|
||||
|
||||
ROW_DATA0 = 17,
|
||||
ROW_DATA1 = 18,
|
||||
ROW_CLEAR = 19,
|
||||
ROW_CLOCK = 20,
|
||||
|
||||
SWITCH_A = 0,
|
||||
SWITCH_B = 1,
|
||||
SWITCH_C = 3,
|
||||
SWITCH_D = 6,
|
||||
SWITCH_E = 2,
|
||||
SWITCH_VOLUME_UP = 21,
|
||||
SWITCH_VOLUME_DOWN = 26,
|
||||
SWITCH_BRIGHTNESS_UP = 7,
|
||||
SWITCH_BRIGHTNESS_DOWN = 8
|
||||
};
|
||||
|
||||
|
||||
|
||||
constexpr uint32_t ROW_COUNT = 11;
|
||||
constexpr uint32_t ROW_BYTES = 4;
|
||||
constexpr uint32_t ROW_FRAME_BYTES = 168;
|
||||
constexpr uint32_t BCD_FRAMES = 15; // includes fet discharge frame
|
||||
constexpr uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES + ROW_COUNT * ROW_FRAME_BYTES * BCD_FRAMES);
|
||||
constexpr uint32_t BCD_FRAME_COUNT = 14;
|
||||
constexpr uint32_t BCD_FRAME_BYTES = 60;
|
||||
constexpr uint32_t ROW_BYTES = BCD_FRAME_COUNT * BCD_FRAME_BYTES;
|
||||
constexpr uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES);
|
||||
|
||||
// must be aligned for 32bit dma transfer
|
||||
alignas(4) static uint8_t bitstream[BITSTREAM_LENGTH] = {0};
|
||||
|
@ -93,38 +52,7 @@ static uint16_t g_gamma_lut[256] = {0};
|
|||
static uint16_t b_gamma_lut[256] = {0};
|
||||
|
||||
static uint32_t dma_channel;
|
||||
|
||||
static inline void unicorn_jetpack_program_init(PIO pio, uint sm, uint offset) {
|
||||
pio_gpio_init(pio, pin::LED_DATA1);
|
||||
pio_gpio_init(pio, pin::LED_DATA0);
|
||||
pio_gpio_init(pio, pin::LED_CLOCK);
|
||||
pio_gpio_init(pio, pin::LED_LATCH);
|
||||
pio_gpio_init(pio, pin::LED_BLANK);
|
||||
|
||||
pio_gpio_init(pio, pin::ROW_DATA0);
|
||||
pio_gpio_init(pio, pin::ROW_DATA1);
|
||||
pio_gpio_init(pio, pin::ROW_CLEAR);
|
||||
pio_gpio_init(pio, pin::ROW_CLOCK);
|
||||
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin::LED_DATA1, 5, true);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin::ROW_DATA0, 4, true);
|
||||
|
||||
pio_sm_config c = galactic_unicorn_program_get_default_config(offset);
|
||||
|
||||
// osr shifts right, autopull on, autopull threshold 8
|
||||
sm_config_set_out_shift(&c, true, false, 32);
|
||||
|
||||
// configure out, set, and sideset pins
|
||||
sm_config_set_out_pins(&c, pin::LED_DATA1, 8);
|
||||
sm_config_set_sideset_pins(&c, pin::ROW_CLOCK);
|
||||
|
||||
// join fifos as only tx needed (gives 8 deep fifo instead of 4)
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
///pio_sm_set_clkdiv(pio, sm, 4.0f);
|
||||
}
|
||||
static uint32_t audio_dma_channel;
|
||||
|
||||
namespace pimoroni {
|
||||
|
||||
|
@ -154,118 +82,124 @@ namespace pimoroni {
|
|||
pio_sm_restart(bitstream_pio, bitstream_sm);
|
||||
}
|
||||
|
||||
uint16_t GalacticUnicorn::light() {
|
||||
adc_select_input(2);
|
||||
return adc_read();
|
||||
}
|
||||
|
||||
void GalacticUnicorn::init() {
|
||||
// todo: shouldn't need to do this if things were cleaned up properly but without
|
||||
// this any attempt to run a micropython script twice will fail
|
||||
static bool already_init = false;
|
||||
|
||||
// setup pins
|
||||
gpio_init(pin::LED_DATA0); gpio_set_dir(pin::LED_DATA0, GPIO_OUT);
|
||||
gpio_init(pin::LED_DATA1); gpio_set_dir(pin::LED_DATA1, GPIO_OUT);
|
||||
gpio_init(pin::LED_CLOCK); gpio_set_dir(pin::LED_CLOCK, GPIO_OUT);
|
||||
gpio_init(pin::LED_LATCH); gpio_set_dir(pin::LED_LATCH, GPIO_OUT);
|
||||
gpio_init(pin::LED_BLANK); gpio_set_dir(pin::LED_BLANK, GPIO_OUT);
|
||||
|
||||
gpio_init(pin::ROW_DATA0); gpio_set_dir(pin::ROW_DATA0, GPIO_OUT);
|
||||
gpio_init(pin::ROW_DATA1); gpio_set_dir(pin::ROW_DATA1, GPIO_OUT);
|
||||
gpio_init(pin::ROW_CLEAR); gpio_set_dir(pin::ROW_CLEAR, GPIO_OUT);
|
||||
gpio_init(pin::ROW_CLOCK); gpio_set_dir(pin::ROW_CLOCK, GPIO_OUT);
|
||||
|
||||
// create 14-bit gamma luts
|
||||
for(uint16_t v = 0; v < 256; v++) {
|
||||
// gamma correct the provided 0-255 brightness value onto a
|
||||
// 0-65535 range for the pwm counter
|
||||
float r_gamma = 2.8f;
|
||||
r_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, r_gamma) * 16383.0f + 0.5f);
|
||||
|
||||
float g_gamma = 2.8f;
|
||||
g_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, g_gamma) * 16383.0f + 0.5f);
|
||||
|
||||
float b_gamma = 2.8f;
|
||||
b_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, b_gamma) * 16383.0f + 0.5f);
|
||||
float r_gamma = 1.8f;
|
||||
r_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, r_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f);
|
||||
float g_gamma = 2.0f;
|
||||
g_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, g_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f);
|
||||
float b_gamma = 1.8f;
|
||||
b_gamma_lut[v] = (uint16_t)(powf((float)(v) / 255.0f, b_gamma) * (float(1U << (BCD_FRAME_COUNT)) - 1.0f) + 0.5f);
|
||||
}
|
||||
|
||||
// for each row:
|
||||
// for each bcd frame:
|
||||
// 0: 00110110 // row pixel count (minus one)
|
||||
// 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data
|
||||
// 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align
|
||||
// 56: xxxxrrrr // row select bits
|
||||
// 57 - 59: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536)
|
||||
//
|
||||
// .. and back to the start
|
||||
|
||||
// the data is structured like this:
|
||||
//
|
||||
// loop through the eleven rows of the display...
|
||||
//
|
||||
// 1rr00000 // set row select bit on rows 0 and 8 (side set the clock)
|
||||
// 00000000 00000000 00000000 // dummy bytes to align to dwords
|
||||
//
|
||||
// within this row we loop through the 14 bcd frames for this row...
|
||||
//
|
||||
// 0 - 161: 100100rr, 100101rr, 100100gg, 100101gg, 100100bb, 100101bb, ... x 27 # left+right half rgb pixel data doubled for clock pulses, keep BLANK high
|
||||
// 162: 10011000 // LATCH pixel data
|
||||
// 163: 10000000 // turn off BLANK to output pixel data - now at 164 bytes (41 dwords)
|
||||
// 164 - 165: 00001111, 11111111, # bcd tick count (0-65536)
|
||||
// 166: 10010000 // turn BLANK back on
|
||||
// 167: 00000000 // dummy byte to ensure dword aligned
|
||||
//
|
||||
// .. and back to the start
|
||||
|
||||
// initialise the bcd timing values and row selects in the bitstream
|
||||
for(uint8_t row = 0; row < HEIGHT; row++) {
|
||||
uint16_t row_offset = row * (ROW_BYTES + ROW_FRAME_BYTES * BCD_FRAMES);
|
||||
for(uint8_t frame = 0; frame < BCD_FRAME_COUNT; frame++) {
|
||||
// find the offset of this row and frame in the bitstream
|
||||
uint8_t *p = &bitstream[row * ROW_BYTES + (BCD_FRAME_BYTES * frame)];
|
||||
|
||||
// setup row select on rows 0 and 8
|
||||
uint8_t row_select = row == 0 ? 0b10111000 : (row == 8 ? 0b11011000 : 0b10011000);
|
||||
bitstream[row_offset + 0] = row_select;
|
||||
|
||||
for(uint8_t frame = 0; frame < BCD_FRAMES; frame++) {
|
||||
uint16_t frame_offset = row_offset + ROW_BYTES + (ROW_FRAME_BYTES * frame);
|
||||
|
||||
bitstream[frame_offset + 162] = 0b10011000; // LATCH pixel data
|
||||
bitstream[frame_offset + 163] = 0b10001000; // BLANK low to enable column outputs
|
||||
p[ 0] = WIDTH - 1; // row pixel count
|
||||
p[56] = row; // row select
|
||||
|
||||
// set the number of bcd ticks for this frame
|
||||
uint16_t bcd_ticks = frame == BCD_FRAMES - 1 ? 1 : 1 << frame;
|
||||
bitstream[frame_offset + 164] = (bcd_ticks & 0xff);
|
||||
bitstream[frame_offset + 165] = (bcd_ticks & 0xff00) >> 8;
|
||||
|
||||
bitstream[frame_offset + 166] = 0b10010000; // BLANK high again to disable outputs
|
||||
|
||||
// setup empty pixels with BLANK high and a clock pulse
|
||||
for(uint8_t col = 0; col < 162; col += 2) {
|
||||
bitstream[frame_offset + col + 0] = 0b10010000;
|
||||
bitstream[frame_offset + col + 1] = 0b10010100;
|
||||
}
|
||||
|
||||
/*
|
||||
uint16_t row_select_offset = offset + 164;
|
||||
uint16_t bcd_offset = offset + 165;
|
||||
|
||||
// the last bcd frame is used to allow the fets to discharge to avoid ghosting
|
||||
if(frame == BCD_FRAMES - 1) {
|
||||
uint16_t bcd_ticks = 65535;
|
||||
bitstream[bcd_offset + 1] = (bcd_ticks & 0xff00) >> 8;
|
||||
bitstream[bcd_offset] = (bcd_ticks & 0xff);
|
||||
}else{
|
||||
uint8_t row_select = row == 0 ? 0b01000000 : (row == 8 ? 0b00100000 : 0b00000000);
|
||||
bitstream[row_select_offset] = row_select;
|
||||
|
||||
uint16_t bcd_ticks = 1 << frame;
|
||||
bitstream[bcd_offset + 1] = (bcd_ticks & 0xff00) >> 8;
|
||||
bitstream[bcd_offset] = (bcd_ticks & 0xff);
|
||||
}*/
|
||||
uint32_t bcd_ticks = (1 << frame);
|
||||
p[57] = (bcd_ticks & 0xff) >> 0;
|
||||
p[58] = (bcd_ticks & 0xff00) >> 8;
|
||||
p[59] = (bcd_ticks & 0xff0000) >> 16;
|
||||
}
|
||||
/*
|
||||
for(size_t i = 0; i < sizeof(bitstream); i++) {
|
||||
bitstream[i] = 0b11100000;
|
||||
}*/
|
||||
}
|
||||
|
||||
// setup light sensor adc
|
||||
adc_init();
|
||||
adc_gpio_init(LIGHT_SENSOR);
|
||||
|
||||
pio_gpio_init(bitstream_pio, COLUMN_CLOCK);
|
||||
pio_gpio_init(bitstream_pio, COLUMN_DATA);
|
||||
pio_gpio_init(bitstream_pio, COLUMN_LATCH);
|
||||
|
||||
gpio_init(COLUMN_CLOCK); gpio_set_dir(COLUMN_CLOCK, GPIO_OUT); gpio_put(COLUMN_CLOCK, false);
|
||||
gpio_init(COLUMN_DATA); gpio_set_dir(COLUMN_DATA, GPIO_OUT); gpio_put(COLUMN_DATA, false);
|
||||
gpio_init(COLUMN_LATCH); gpio_set_dir(COLUMN_LATCH, GPIO_OUT); gpio_put(COLUMN_LATCH, false);
|
||||
|
||||
sleep_ms(100);
|
||||
|
||||
// configure full output current in register 2
|
||||
|
||||
uint16_t reg1 = 0b1111111111001110;
|
||||
|
||||
// clock the register value to the first 9 driver chips
|
||||
for(int j = 0; j < 9; j++) {
|
||||
for(int i = 0; i < 16; i++) {
|
||||
if(reg1 & (1U << (15 - i))) {
|
||||
gpio_put(COLUMN_DATA, true);
|
||||
}else{
|
||||
gpio_put(COLUMN_DATA, false);
|
||||
}
|
||||
sleep_us(10);
|
||||
gpio_put(COLUMN_CLOCK, true);
|
||||
sleep_us(10);
|
||||
gpio_put(COLUMN_CLOCK, false);
|
||||
}
|
||||
}
|
||||
|
||||
// clock the last chip and latch the value
|
||||
for(int i = 0; i < 16; i++) {
|
||||
if(reg1 & (1U << (15 - i))) {
|
||||
gpio_put(COLUMN_DATA, true);
|
||||
}else{
|
||||
gpio_put(COLUMN_DATA, false);
|
||||
}
|
||||
|
||||
sleep_us(10);
|
||||
gpio_put(COLUMN_CLOCK, true);
|
||||
sleep_us(10);
|
||||
gpio_put(COLUMN_CLOCK, false);
|
||||
|
||||
if(i == 4) {
|
||||
gpio_put(COLUMN_LATCH, true);
|
||||
}
|
||||
}
|
||||
gpio_put(COLUMN_LATCH, false);
|
||||
|
||||
|
||||
gpio_init(MUTE); gpio_set_dir(MUTE, GPIO_OUT); gpio_put(MUTE, true);
|
||||
|
||||
// setup button inputs
|
||||
gpio_set_function(pin::SWITCH_A, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_A, GPIO_IN); gpio_pull_up(pin::SWITCH_A);
|
||||
gpio_set_function(pin::SWITCH_B, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_B, GPIO_IN); gpio_pull_up(pin::SWITCH_B);
|
||||
gpio_set_function(pin::SWITCH_C, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_C, GPIO_IN); gpio_pull_up(pin::SWITCH_C);
|
||||
gpio_set_function(pin::SWITCH_D, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_D, GPIO_IN); gpio_pull_up(pin::SWITCH_D);
|
||||
gpio_set_function(pin::SWITCH_E, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_E, GPIO_IN); gpio_pull_up(pin::SWITCH_E);
|
||||
gpio_init(SWITCH_A); gpio_pull_up(SWITCH_A);
|
||||
gpio_init(SWITCH_B); gpio_pull_up(SWITCH_B);
|
||||
gpio_init(SWITCH_C); gpio_pull_up(SWITCH_C);
|
||||
gpio_init(SWITCH_D); gpio_pull_up(SWITCH_D);
|
||||
|
||||
gpio_set_function(pin::SWITCH_BRIGHTNESS_UP, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_BRIGHTNESS_UP, GPIO_IN); gpio_pull_up(pin::SWITCH_BRIGHTNESS_UP);
|
||||
gpio_set_function(pin::SWITCH_BRIGHTNESS_DOWN, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_BRIGHTNESS_DOWN, GPIO_IN); gpio_pull_up(pin::SWITCH_BRIGHTNESS_DOWN);
|
||||
gpio_init(SWITCH_SLEEP); gpio_pull_up(SWITCH_SLEEP);
|
||||
|
||||
gpio_set_function(pin::SWITCH_VOLUME_UP, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_VOLUME_UP, GPIO_IN); gpio_pull_up(pin::SWITCH_VOLUME_UP);
|
||||
gpio_set_function(pin::SWITCH_VOLUME_DOWN, GPIO_FUNC_SIO); gpio_set_dir(pin::SWITCH_VOLUME_DOWN, GPIO_IN); gpio_pull_up(pin::SWITCH_VOLUME_DOWN);
|
||||
gpio_init(SWITCH_BRIGHTNESS_UP); gpio_pull_up(SWITCH_BRIGHTNESS_UP);
|
||||
gpio_init(SWITCH_BRIGHTNESS_DOWN); gpio_pull_up(SWITCH_BRIGHTNESS_DOWN);
|
||||
|
||||
gpio_init(SWITCH_VOLUME_UP); gpio_pull_up(SWITCH_VOLUME_UP);
|
||||
gpio_init(SWITCH_VOLUME_DOWN); gpio_pull_up(SWITCH_VOLUME_DOWN);
|
||||
|
||||
if(already_init) {
|
||||
// stop and release the dma channel
|
||||
|
@ -288,9 +222,38 @@ namespace pimoroni {
|
|||
|
||||
// setup the pio
|
||||
bitstream_pio = pio0;
|
||||
bitstream_sm = pio_claim_unused_sm(pio0, true);
|
||||
sm_offset = pio_add_program(bitstream_pio, &galactic_unicorn_program);
|
||||
unicorn_jetpack_program_init(bitstream_pio, bitstream_sm, sm_offset);
|
||||
bitstream_sm = pio_claim_unused_sm(bitstream_pio, true);
|
||||
bitstream_sm_offset = pio_add_program(bitstream_pio, &galactic_unicorn_program);
|
||||
|
||||
pio_gpio_init(bitstream_pio, COLUMN_CLOCK);
|
||||
pio_gpio_init(bitstream_pio, COLUMN_DATA);
|
||||
pio_gpio_init(bitstream_pio, COLUMN_LATCH);
|
||||
pio_gpio_init(bitstream_pio, COLUMN_BLANK);
|
||||
|
||||
pio_gpio_init(bitstream_pio, ROW_BIT_0);
|
||||
pio_gpio_init(bitstream_pio, ROW_BIT_1);
|
||||
pio_gpio_init(bitstream_pio, ROW_BIT_2);
|
||||
pio_gpio_init(bitstream_pio, ROW_BIT_3);
|
||||
|
||||
// set all led driving pins as outputs
|
||||
pio_sm_set_consecutive_pindirs(bitstream_pio, bitstream_sm, COLUMN_CLOCK, 8, true);
|
||||
|
||||
pio_sm_config c = galactic_unicorn_program_get_default_config(bitstream_sm_offset);
|
||||
|
||||
// osr shifts right, autopull on, autopull threshold 8
|
||||
sm_config_set_out_shift(&c, true, true, 32);
|
||||
|
||||
// configure out, set, and sideset pins
|
||||
sm_config_set_out_pins(&c, ROW_BIT_0, 4);
|
||||
sm_config_set_set_pins(&c, COLUMN_DATA, 3);
|
||||
sm_config_set_sideset_pins(&c, COLUMN_CLOCK);
|
||||
|
||||
// join fifos as only tx needed (gives 8 deep fifo instead of 4)
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
|
||||
pio_sm_init(bitstream_pio, bitstream_sm, bitstream_sm_offset, &c);
|
||||
pio_sm_set_enabled(bitstream_pio, bitstream_sm, true);
|
||||
|
||||
|
||||
// setup dma transfer for pixel data to the pio
|
||||
dma_channel = dma_claim_unused_channel(true);
|
||||
|
@ -308,6 +271,52 @@ namespace pimoroni {
|
|||
dma_channel_set_read_addr(dma_channel, bitstream, true);
|
||||
|
||||
already_init = true;
|
||||
|
||||
|
||||
// setup audio pio program
|
||||
/*
|
||||
audio_pio = pio0;
|
||||
audio_sm = pio_claim_unused_sm(audio_pio, true);
|
||||
audio_sm_offset = pio_add_program(audio_pio, &audio_i2s_program);
|
||||
audio_i2s_program_init(audio_pio, audio_sm, audio_sm_offset, I2S_DATA, I2S_BCLK);
|
||||
//pio_sm_set_enabled(audio_pio, audio_sm, true);
|
||||
|
||||
uint32_t system_clock_frequency = clock_get_hz(clk_sys);
|
||||
uint32_t divider = system_clock_frequency * 4 / 22050; // avoid arithmetic overflow
|
||||
pio_sm_set_clkdiv_int_frac(audio_pio, audio_sm, divider >> 8u, divider & 0xffu);
|
||||
|
||||
|
||||
|
||||
audio_dma_channel = dma_claim_unused_channel(true);
|
||||
dma_channel_config audio_config = dma_channel_get_default_config(audio_dma_channel);
|
||||
channel_config_set_transfer_data_size(&audio_config, DMA_SIZE_32);
|
||||
channel_config_set_bswap(&audio_config, false); // byte swap to reverse little endian
|
||||
channel_config_set_dreq(&audio_config, pio_get_dreq(audio_pio, audio_sm, true));
|
||||
dma_channel_configure(audio_dma_channel, &audio_config, &audio_pio->txf[audio_sm], NULL, 0, false);
|
||||
dma_channel_set_irq0_enabled(audio_dma_channel, true);
|
||||
irq_set_enabled(pio_get_dreq(audio_pio, audio_sm, true), true);*/
|
||||
//irq_set_exclusive_handler(DMA_IRQ_0, dma_complete);
|
||||
//irq_set_enabled(DMA_IRQ_0, true);
|
||||
|
||||
/* dma_channel_set_trans_count(audio_dma_channel, BITSTREAM_LENGTH / 4, false);
|
||||
dma_channel_set_read_addr(audio_dma_channel, bitstream, true);*/
|
||||
//pio_sm_config audio_i2s_config = audio_i2s_program_get_default_config(audio_sm_offset);
|
||||
|
||||
// osr shifts right, autopull on, autopull threshold 8
|
||||
//sm_config_set_out_shift(&audio_i2s_config, true, true, 32);
|
||||
|
||||
// // configure out, set, and sideset pins
|
||||
// sm_config_set_out_pins(&audio_i2s_config, ROW_BIT_0, 4);
|
||||
// sm_config_set_set_pins(&audio_i2s_config, COLUMN_DATA, 3);
|
||||
// sm_config_set_sideset_pins(&audio_i2s_config, COLUMN_CLOCK);
|
||||
|
||||
// // join fifos as only tx needed (gives 8 deep fifo instead of 4)
|
||||
// sm_config_set_fifo_join(&audio_i2s_config, PIO_FIFO_JOIN_TX);
|
||||
|
||||
|
||||
//pio_sm_init(audio_pio, audio_sm, audio_sm_offset, &audio_i2s_config);
|
||||
//pio_sm_set_enabled(audio_pio, audio_sm, true);
|
||||
|
||||
}
|
||||
|
||||
void GalacticUnicorn::clear() {
|
||||
|
@ -318,65 +327,44 @@ namespace pimoroni {
|
|||
}
|
||||
}
|
||||
|
||||
void GalacticUnicorn::set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) {
|
||||
|
||||
void GalacticUnicorn::play_sample(uint8_t *data, uint32_t length) {
|
||||
dma_channel_transfer_from_buffer_now(audio_dma_channel, data, length / 4);
|
||||
}
|
||||
|
||||
void GalacticUnicorn::set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) {
|
||||
if(x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) return;
|
||||
|
||||
// make those coordinates sane
|
||||
x = (WIDTH - 1) - x;
|
||||
y = (HEIGHT - 1) - y;
|
||||
|
||||
// determine offset in the buffer for this row
|
||||
uint16_t row_offset = y * (ROW_BYTES + ROW_FRAME_BYTES * BCD_FRAMES);
|
||||
uint16_t gamma_r = r_gamma_lut[r];
|
||||
uint16_t gamma_g = g_gamma_lut[g];
|
||||
uint16_t gamma_b = b_gamma_lut[b];
|
||||
|
||||
uint16_t bits[3] = {r_gamma_lut[b], g_gamma_lut[g], b_gamma_lut[r]};
|
||||
//uint16_t gr = r_gamma_lut[r];
|
||||
//uint16_t gg = g_gamma_lut[g];
|
||||
//uint16_t gb = b_gamma_lut[b];
|
||||
// for each row:
|
||||
// for each bcd frame:
|
||||
// 0: 00110110 // row pixel count (minus one)
|
||||
// 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data
|
||||
// 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align
|
||||
// 56: xxxxrrrr // row select bits
|
||||
// 57 - 59: tttttttt, tttttttt, tttttttt // bcd tick count (0-65536)
|
||||
//
|
||||
// .. and back to the start
|
||||
|
||||
// set the appropriate bits in the separate bcd frames
|
||||
for(uint8_t frame = 0; frame < BCD_FRAMES; frame++) {
|
||||
uint16_t frame_offset = (ROW_FRAME_BYTES * frame) + 4;
|
||||
uint16_t offset = row_offset + frame_offset;// + byte_offset;
|
||||
for(uint8_t frame = 0; frame < BCD_FRAME_COUNT; frame++) {
|
||||
uint8_t *p = &bitstream[y * ROW_BYTES + (BCD_FRAME_BYTES * frame) + 1 + x];
|
||||
|
||||
// loop through the eleven rows of the display...
|
||||
//
|
||||
// 1rr00000 // set row select bit on rows 0 and 8 (side set the clock)
|
||||
// 00000000 00000000 00000000 // dummy bytes to align to dwords
|
||||
//
|
||||
// within this row we loop through the 14 bcd frames for this row...
|
||||
//
|
||||
// 0 - 161: 100100rr, 100101rr, 100100gg, 100101gg, 100100bb, 100101bb, ... x 27 # left+right half rgb pixel data doubled for clock pulses, keep BLANK high
|
||||
// 162: 10011000 // LATCH pixel data
|
||||
// 163: 10000000 // turn off BLANK to output pixel data - now at 164 bytes (41 dwords)
|
||||
// 164 - 165: 00001111, 11111111, # bcd tick count (0-65536)
|
||||
// 166: 10010000 // turn BLANK back on
|
||||
// 167: 00000000 // dummy byte to ensure dword aligned
|
||||
//
|
||||
// .. and back to the start
|
||||
uint8_t red_bit = gamma_r & 0b1;
|
||||
uint8_t green_bit = gamma_g & 0b1;
|
||||
uint8_t blue_bit = gamma_b & 0b1;
|
||||
|
||||
// work out the byte offset of this pixel
|
||||
/*if(bit_offset >= 160) {
|
||||
bit_offset -= 160;
|
||||
}*/
|
||||
*p = (blue_bit << 2) | (green_bit << 1) | (red_bit << 0);
|
||||
|
||||
for(int bit = 0; bit < 3; bit++) {
|
||||
int16_t bit_offset = x * 6 + 4 + (bit * 2);
|
||||
|
||||
|
||||
uint8_t bit_position = bit_offset >= 160 ? 1 : 0;
|
||||
uint8_t mask = 0b1 << bit_position;
|
||||
uint8_t value = (bits[bit] & 0b1) << bit_position;
|
||||
|
||||
bitstream[offset + (bit_offset % 160) + 0] &= ~mask;
|
||||
bitstream[offset + (bit_offset % 160) + 0] |= value;
|
||||
bitstream[offset + (bit_offset % 160) + 1] &= ~mask;
|
||||
bitstream[offset + (bit_offset % 160) + 1] |= value;
|
||||
|
||||
//bit_offset += 2;
|
||||
bits[bit] >>= 1;
|
||||
}
|
||||
gamma_r >>= 1;
|
||||
gamma_g >>= 1;
|
||||
gamma_b >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -384,6 +372,55 @@ namespace pimoroni {
|
|||
set_pixel(x, y, v, v, v);
|
||||
}
|
||||
|
||||
void GalacticUnicorn::set_brightness(float value) {
|
||||
value = value < 0.0f ? 0.0f : value;
|
||||
value = value > 1.0f ? 1.0f : value;
|
||||
this->brightness = floor(value * 255.0f);
|
||||
}
|
||||
|
||||
float GalacticUnicorn::get_brightness() {
|
||||
return this->brightness / 255.0f;
|
||||
}
|
||||
|
||||
void GalacticUnicorn::adjust_brightness(float delta) {
|
||||
this->set_brightness(this->get_brightness() + delta);
|
||||
}
|
||||
|
||||
void GalacticUnicorn::set_volume(float value) {
|
||||
value = value < 0.0f ? 0.0f : value;
|
||||
value = value > 1.0f ? 1.0f : value;
|
||||
this->volume = floor(value * 255.0f);
|
||||
}
|
||||
|
||||
float GalacticUnicorn::get_volume() {
|
||||
return this->volume / 255.0f;
|
||||
}
|
||||
|
||||
void GalacticUnicorn::adjust_volume(float delta) {
|
||||
this->set_volume(this->get_volume() + delta);
|
||||
}
|
||||
|
||||
|
||||
void GalacticUnicorn::update(PicoGraphics_PenRGB565 &graphics) {
|
||||
uint16_t *p = (uint16_t *)graphics.frame_buffer;
|
||||
for(size_t j = 0; j < 53 * 11; j++) {
|
||||
int x = j % 53;
|
||||
int y = j / 53;
|
||||
|
||||
uint16_t col = __builtin_bswap16(*p);
|
||||
uint8_t r = ((col & 0b1111100000000000) >> 11) << 3;
|
||||
uint8_t g = ((col & 0b0000011111100000) >> 5) << 2;
|
||||
uint8_t b = ((col & 0b0000000000011111) >> 0) << 3;
|
||||
p++;
|
||||
|
||||
r = (r * this->brightness) >> 8;
|
||||
g = (g * this->brightness) >> 8;
|
||||
b = (b * this->brightness) >> 8;
|
||||
|
||||
set_pixel(x, y, b, g, r);
|
||||
}
|
||||
}
|
||||
|
||||
bool GalacticUnicorn::is_pressed(uint8_t button) {
|
||||
return !gpio_get(button);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "hardware/pio.h"
|
||||
#include "pico_graphics.hpp"
|
||||
|
||||
namespace pimoroni {
|
||||
|
||||
|
@ -8,30 +9,81 @@ namespace pimoroni {
|
|||
public:
|
||||
static const int WIDTH = 53;
|
||||
static const int HEIGHT = 11;
|
||||
static const uint8_t SWITCH_A = 0;
|
||||
static const uint8_t SWITCH_B = 1;
|
||||
static const uint8_t SWITCH_C = 3;
|
||||
static const uint8_t SWITCH_D = 6;
|
||||
static const uint8_t SWITCH_E = 2;
|
||||
static const uint8_t SWITCH_VOLUME_UP = 21;
|
||||
static const uint8_t SWITCH_VOLUME_DOWN = 26;
|
||||
static const uint8_t SWITCH_BRIGHTNESS_UP = 7;
|
||||
static const uint8_t SWITCH_BRIGHTNESS_DOWN = 8;
|
||||
|
||||
// pin assignments
|
||||
static const uint8_t COLUMN_CLOCK = 13;
|
||||
static const uint8_t COLUMN_DATA = 14;
|
||||
static const uint8_t COLUMN_LATCH = 15;
|
||||
static const uint8_t COLUMN_BLANK = 16;
|
||||
|
||||
static const uint8_t ROW_BIT_0 = 17;
|
||||
static const uint8_t ROW_BIT_1 = 18;
|
||||
static const uint8_t ROW_BIT_2 = 19;
|
||||
static const uint8_t ROW_BIT_3 = 20;
|
||||
|
||||
static const uint8_t LIGHT_SENSOR = 28;
|
||||
|
||||
static const uint8_t MUTE = 22;
|
||||
|
||||
static const uint8_t I2S_DATA = 9;
|
||||
static const uint8_t I2S_BCLK = 10;
|
||||
static const uint8_t I2S_LRCLK = 11;
|
||||
|
||||
static const uint8_t I2C_SDA = 4;
|
||||
static const uint8_t I2C_SCL = 5;
|
||||
|
||||
static const uint8_t SWITCH_A = 0;
|
||||
static const uint8_t SWITCH_B = 1;
|
||||
static const uint8_t SWITCH_C = 3;
|
||||
static const uint8_t SWITCH_D = 6;
|
||||
|
||||
static const uint8_t SWITCH_SLEEP = 27;
|
||||
|
||||
static const uint8_t SWITCH_VOLUME_UP = 7;
|
||||
static const uint8_t SWITCH_VOLUME_DOWN = 8;
|
||||
static const uint8_t SWITCH_BRIGHTNESS_UP = 21;
|
||||
static const uint8_t SWITCH_BRIGHTNESS_DOWN = 26;
|
||||
|
||||
private:
|
||||
PIO bitstream_pio = pio0;
|
||||
uint bitstream_sm = 0;
|
||||
uint sm_offset = 0;
|
||||
uint bitstream_sm_offset = 0;
|
||||
|
||||
PIO audio_pio = pio0;
|
||||
uint audio_sm = 0;
|
||||
uint audio_sm_offset = 0;
|
||||
|
||||
uint8_t brightness = 255;
|
||||
uint8_t volume = 127;
|
||||
|
||||
public:
|
||||
~GalacticUnicorn();
|
||||
|
||||
void init();
|
||||
static inline void pio_program_init(PIO pio, uint sm, uint offset);
|
||||
|
||||
void clear();
|
||||
|
||||
void update(PicoGraphics_PenRGB565 &graphics);
|
||||
|
||||
void set_brightness(float value);
|
||||
float get_brightness();
|
||||
void adjust_brightness(float delta);
|
||||
|
||||
void set_volume(float value);
|
||||
float get_volume();
|
||||
void adjust_volume(float delta);
|
||||
|
||||
|
||||
void set_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b);
|
||||
void set_pixel(int x, int y, uint8_t v);
|
||||
|
||||
uint16_t light();
|
||||
|
||||
bool is_pressed(uint8_t button);
|
||||
|
||||
void play_sample(uint8_t *data, uint32_t length);
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -2,65 +2,79 @@
|
|||
.side_set 1 opt
|
||||
|
||||
; out pins:
|
||||
; 0: data1 (base)
|
||||
; 1: data0
|
||||
; 2: clock
|
||||
; 3: latch
|
||||
; 4: blank
|
||||
; 5: row1
|
||||
; 6: row2
|
||||
; 7: row_clear
|
||||
;
|
||||
; - 3: row select bit 0
|
||||
; - 4: row select bit 1
|
||||
; - 5: row select bit 2
|
||||
; - 6: row select bit 3
|
||||
|
||||
; set pins:
|
||||
;
|
||||
; - 0: column data (base)
|
||||
; - 1: column latch
|
||||
; - 2: column blank
|
||||
|
||||
; sideset pin:
|
||||
;
|
||||
; - 0: column clock
|
||||
|
||||
; for each row:
|
||||
; for each bcd frame:
|
||||
; 0: 00110110 // row pixel count (minus one)
|
||||
; 1 - 53: xxxxxbgr, xxxxxbgr, xxxxxbgr, ... // pixel data
|
||||
; 54 - 55: xxxxxxxx, xxxxxxxx // dummy bytes to dword align
|
||||
; 56: xxxxrrrr // row select bits
|
||||
; 57 - 59: tttttttt, tttttttt, tttttttt, // bcd tick count (0-65536)
|
||||
;
|
||||
; .. and back to the start
|
||||
|
||||
; sideset pin: row_clock
|
||||
|
||||
.wrap_target
|
||||
|
||||
|
||||
; set row select pins
|
||||
pull
|
||||
out pins, 8 side 0 [4]
|
||||
nop side 1 [4] ; pulse row select clock
|
||||
out null, 24 ; discard dummy data
|
||||
|
||||
; loop for bcd frames
|
||||
set x, 14
|
||||
bcd_frame:
|
||||
|
||||
; clock out 53 pixels worth of data - two pixels at a time, so 27 (actually 26.5) bits of data
|
||||
set y, 26 ; 26 because `jmp` test is pre decrement
|
||||
|
||||
; loop over row pixels
|
||||
out y, 8 ; get row pixel count (minus 1 because test is pre decrement)
|
||||
pixels:
|
||||
|
||||
pull ifempty
|
||||
out pins, 8 [1] ; two red bits..
|
||||
out pins, 8 [1] ; ..with clock pulse
|
||||
|
||||
pull ifempty
|
||||
out pins, 8 [1] ; two green bits..
|
||||
out pins, 8 [1] ; ..with green pulse
|
||||
|
||||
pull ifempty
|
||||
out pins, 8 [1] ; two blue bits..
|
||||
out pins, 8 [1] ; ..with blue pulse
|
||||
|
||||
jmp y-- pixels
|
||||
|
||||
out pins, 8 ; LATCH pixel data
|
||||
out pins, 8 ; turn off BLANK signal
|
||||
; red bit
|
||||
out x, 1 side 0 [1] ; pull in blue bit from OSR into register x, clear clock
|
||||
set pins, 0b100 ; clear data bit, blank high
|
||||
jmp !x endb ; if bit was zero jump
|
||||
set pins, 0b101 ; set data bit, blank high
|
||||
endb:
|
||||
nop side 1 [2] ; clock in bit
|
||||
|
||||
pull
|
||||
; green bit
|
||||
out x, 1 side 0 [1] ; pull in green bit from OSR into register X, clear clock
|
||||
set pins, 0b100 ; clear data bit, blank high
|
||||
jmp !x endg ; if bit was zero jump
|
||||
set pins, 0b101 ; set data bit, blank high
|
||||
endg:
|
||||
nop side 1 [2] ; clock in bit
|
||||
|
||||
; pull bcd tick count into x register
|
||||
out y, 16
|
||||
; blue bit
|
||||
out x, 1 side 0 [1] ; pull in red bit from OSR into register X, clear clock
|
||||
set pins, 0b100 ; clear data bit, blank high
|
||||
jmp !x endr ; if bit was zero jump
|
||||
set pins, 0b101 ; set data bit, blank high
|
||||
endr:
|
||||
out null, 5 side 1 [2] ; clock in bit
|
||||
|
||||
bcd_count:
|
||||
jmp y-- bcd_count ; loop until bcd delay complete
|
||||
;out null, 5 side 0 ; discard the five dummy bits for this pixel
|
||||
|
||||
; disable led output (blank) and clear latch pin
|
||||
out pins, 8 ; turn off BLANK signal and clear row output
|
||||
out null, 8 ; discard dummy data
|
||||
jmp y-- pixels
|
||||
|
||||
jmp x-- bcd_frame ; loop to next bcd frame
|
||||
out null, 16 ; discard dummy bytes
|
||||
|
||||
out pins, 8 ; output row select
|
||||
|
||||
set pins, 0b110 [5] ; latch high, blank high
|
||||
set pins, 0b000 ; blank low (enable output)
|
||||
|
||||
; loop over bcd delay period
|
||||
out y, 24 ; get bcd delay counter value
|
||||
bcd_delay:
|
||||
jmp y-- bcd_delay
|
||||
|
||||
set pins 0b100 ; blank high (disable output)
|
||||
|
||||
.wrap
|
|
@ -276,8 +276,6 @@ namespace pimoroni {
|
|||
void PicoGraphics::line(Point p1, Point p2) {
|
||||
// fast horizontal line
|
||||
if(p1.y == p2.y) {
|
||||
p1 = p1.clamp(clip);
|
||||
p2 = p2.clamp(clip);
|
||||
int32_t start = std::min(p1.x, p2.x);
|
||||
int32_t end = std::max(p1.x, p2.x);
|
||||
pixel_span(Point(start, p1.y), end - start);
|
||||
|
@ -286,13 +284,11 @@ namespace pimoroni {
|
|||
|
||||
// fast vertical line
|
||||
if(p1.x == p2.x) {
|
||||
p1 = p1.clamp(clip);
|
||||
p2 = p2.clamp(clip);
|
||||
int32_t start = std::min(p1.y, p2.y);
|
||||
int32_t length = std::max(p1.y, p2.y) - start;
|
||||
Point dest(p1.x, start);
|
||||
while(length--) {
|
||||
set_pixel(dest);
|
||||
pixel(dest);
|
||||
dest.y++;
|
||||
}
|
||||
return;
|
||||
|
@ -314,7 +310,7 @@ namespace pimoroni {
|
|||
int32_t y = p1.y << 16;
|
||||
while(s--) {
|
||||
Point p(x, y >> 16);
|
||||
if(clip.contains(p)) set_pixel(p);
|
||||
pixel(p);
|
||||
y += sy;
|
||||
x += sx;
|
||||
}
|
||||
|
@ -327,7 +323,7 @@ namespace pimoroni {
|
|||
int32_t x = p1.x << 16;
|
||||
while(s--) {
|
||||
Point p(x >> 16, y);
|
||||
if(clip.contains(p)) set_pixel(p);
|
||||
pixel(p);
|
||||
y += sy;
|
||||
x += sx;
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue