Adding examples for the EYESPI BFF
Adding CP and Arduino example code for the EYESPI BFF. Both use the 1.54" 240x240 display.
This commit is contained in:
parent
035a6775de
commit
7f1493f854
4 changed files with 1004 additions and 4 deletions
|
|
@ -20,7 +20,7 @@
|
|||
// CONSTANTS, HEADERS and GLOBAL VARIABLES ---------------------------------
|
||||
|
||||
// *** EDIT THIS VALUE TO MATCH THE ADAFRUIT PRODUCT ID FOR YOUR DISPLAY: ***
|
||||
#define SCREEN_PRODUCT_ID 5393
|
||||
#define SCREEN_PRODUCT_ID 3787
|
||||
// You can find the product ID several ways:
|
||||
// - "PID" accompanies each line-item on your receipt or order details page.
|
||||
// - Visit adafruit.com and search for EYESPI displays. On product pages,
|
||||
|
|
@ -28,9 +28,9 @@
|
|||
// - Check the comments in setup() later that reference various screens.
|
||||
|
||||
// **** EDIT PINS TO MATCH YOUR WIRING ****
|
||||
#define TFT_CS 10 // To display chip-select pin
|
||||
#define TFT_RST 9 // To display reset pin
|
||||
#define TFT_DC 8 // To display data/command pin
|
||||
#define TFT_CS PIN_SERIAL2_TX // To display chip-select pin
|
||||
#define TFT_RST -1 // To display reset pin
|
||||
#define TFT_DC PIN_SERIAL2_RX // To display data/command pin
|
||||
// For the remaining pins, this code assumes display is wired to hardware SPI
|
||||
// on the dev board's primary SPI interface. The display libraries can support
|
||||
// secondary SPI (if present) or bitbang (software) SPI, but that's not
|
||||
|
|
|
|||
|
|
@ -0,0 +1,674 @@
|
|||
// SPDX-FileCopyrightText: 2022 Phillip Burgess for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Graphics example for EYESPI-capable color displays. This code:
|
||||
// - Functions as a "Hello World" to verify that microcontroller and screen
|
||||
// are communicating.
|
||||
// - Demonstrates most of the drawing commands of the Adafruit_GFX library.
|
||||
// - Showcases some techniques that might not be obvious or that aren't
|
||||
// built-in but can be handled with a little extra code.
|
||||
// It DOES NOT:
|
||||
// - Support all Adafruit screens, ONLY EYESPI products at the time this was
|
||||
// written! But it's easily adapted by looking at other examples.
|
||||
// - Demonstrate the Adafruit_GFX_Button class, as that's unique to
|
||||
// touch-capable displays. Again, other examples may cover this topic.
|
||||
// This sketch is long, but a lot of it is comments to explain each step. You
|
||||
// can copy just the parts you need as a starting point for your own projects,
|
||||
// and strip comments once understood.
|
||||
|
||||
// CONSTANTS, HEADERS and GLOBAL VARIABLES ---------------------------------
|
||||
|
||||
// *** EDIT THIS VALUE TO MATCH THE ADAFRUIT PRODUCT ID FOR YOUR DISPLAY: ***
|
||||
#define SCREEN_PRODUCT_ID 3787
|
||||
// You can find the product ID several ways:
|
||||
// - "PID" accompanies each line-item on your receipt or order details page.
|
||||
// - Visit adafruit.com and search for EYESPI displays. On product pages,
|
||||
// PID is shown just below product title, and is at the end of URLs.
|
||||
// - Check the comments in setup() later that reference various screens.
|
||||
|
||||
// **** EDIT PINS TO MATCH YOUR WIRING ****
|
||||
#define TFT_CS PIN_SERIAL2_TX // To display chip-select pin
|
||||
#define TFT_RST -1 // To display reset pin
|
||||
#define TFT_DC PIN_SERIAL2_RX // To display data/command pin
|
||||
// For the remaining pins, this code assumes display is wired to hardware SPI
|
||||
// on the dev board's primary SPI interface. The display libraries can support
|
||||
// secondary SPI (if present) or bitbang (software) SPI, but that's not
|
||||
// demonstrated here. See other examples for more varied interfacing options.
|
||||
|
||||
#include <Adafruit_GFX.h> // Core graphics library
|
||||
#include <Fonts/FreeSansBold18pt7b.h> // A custom font
|
||||
#if (SCREEN_PRODUCT_ID == 1480) || (SCREEN_PRODUCT_ID == 2090)
|
||||
#include <Adafruit_ILI9341.h> // Library for ILI9341-based screens
|
||||
Adafruit_ILI9341 display(TFT_CS, TFT_DC, TFT_RST);
|
||||
#else
|
||||
#include <Adafruit_ST7789.h> // Library for ST7789-based screens
|
||||
Adafruit_ST7789 display(TFT_CS, TFT_DC, TFT_RST);
|
||||
#endif
|
||||
|
||||
#define PAUSE 3000 // Delay (millisecondss) between examples
|
||||
uint8_t rotate = 0; // Current screen orientation (0-3)
|
||||
|
||||
// setup() RUNS ONCE AT PROGRAM STARTUP ------------------------------------
|
||||
|
||||
void setup() {
|
||||
// Initialize display hardware
|
||||
#if (SCREEN_PRODUCT_ID == 5393) // 1.47" 320x172 round-rect TFT
|
||||
#define CORNER_RADIUS 22
|
||||
display.init(172, 320);
|
||||
#elif (SCREEN_PRODUCT_ID == 3787) // 1.54" 240x240 TFT
|
||||
display.init(240, 240);
|
||||
#elif (SCREEN_PRODUCT_ID == 5206) // 1.69" 280x240 round-rect TFT
|
||||
#define CORNER_RADIUS 43
|
||||
display.init(240, 280);
|
||||
#elif (SCREEN_PRODUCT_ID == 5394) // 1.9" 320x170 TFT
|
||||
display.init(170, 320);
|
||||
#else // All ILI9341 TFTs (320x240)
|
||||
display.begin();
|
||||
#endif
|
||||
#if !defined(CORNER_RADIUS)
|
||||
#define CORNER_RADIUS 0
|
||||
#endif
|
||||
|
||||
// OPTIONAL: default TFT SPI speed is fairly conservative, you can try
|
||||
// overriding here for faster screen updates. Actual SPI speed may be less
|
||||
// depending on microcontroller's capabilities. Max reliable speed also
|
||||
// depends on wiring length and tidyness.
|
||||
//display.setSPISpeed(40000000);
|
||||
}
|
||||
|
||||
// MAIN LOOP, REPEATS FOREVER ----------------------------------------------
|
||||
|
||||
void loop() {
|
||||
// Each of these functions demonstrates a different Adafruit_GFX concept:
|
||||
show_shapes();
|
||||
show_charts();
|
||||
show_basic_text();
|
||||
show_char_map();
|
||||
show_custom_text();
|
||||
show_bitmap();
|
||||
#if !defined(AVR)
|
||||
// The full set of examples (plus the custom font) won't fit on an 8-bit
|
||||
// Arduino, something's got to go. You can try out this one IF the other
|
||||
// examples are disabled instead.
|
||||
show_canvas();
|
||||
#endif
|
||||
|
||||
if (++rotate > 3) rotate = 0; // Cycle through screen rotations 0-3
|
||||
display.setRotation(rotate); // Takes effect on next drawing command
|
||||
}
|
||||
|
||||
// BASIC SHAPES EXAMPLE ----------------------------------------------------
|
||||
|
||||
void show_shapes() {
|
||||
// Draw outlined and filled shapes. This demonstrates:
|
||||
// - Enclosed shapes supported by GFX (points & lines are shown later).
|
||||
// - Adapting to different-sized displays, and to rounded corners.
|
||||
|
||||
const int16_t cx = display.width() / 2; // Center of screen =
|
||||
const int16_t cy = display.height() / 2; // half of width, height
|
||||
int16_t minor = min(cx, cy); // Lesser of half width or height
|
||||
// Shapes will be drawn in a square region centered on the screen. But one
|
||||
// particular screen -- rounded 240x280 ST7789 -- has VERY rounded corners
|
||||
// that would clip a couple of shapes if drawn full size. If using that
|
||||
// screen type, reduce area by a few pixels to avoid drawing in corners.
|
||||
if (CORNER_RADIUS > 40) minor -= 4;
|
||||
const uint8_t pad = 5; // Space between shapes is 2X this
|
||||
const int16_t size = minor - pad; // Shapes are this width & height
|
||||
const int16_t half = size / 2; // 1/2 of shape size
|
||||
|
||||
display.fillScreen(0); // Start by clearing the screen; color 0 = black
|
||||
|
||||
// Draw outline version of basic shapes: rectangle, triangle, circle and
|
||||
// rounded rectangle in different colors. Rather than hardcoded numbers
|
||||
// for position and size, some arithmetic helps adapt to screen dimensions.
|
||||
display.drawRect(cx - minor, cy - minor, size, size, 0xF800);
|
||||
display.drawTriangle(cx + pad, cy - pad, cx + pad + half, cy - minor,
|
||||
cx + minor - 1, cy - pad, 0x07E0);
|
||||
display.drawCircle(cx - pad - half, cy + pad + half, half, 0x001F);
|
||||
display.drawRoundRect(cx + pad, cy + pad, size, size, size / 5, 0xFFE0);
|
||||
delay(PAUSE);
|
||||
|
||||
// Draw same shapes, same positions, but filled this time.
|
||||
display.fillRect(cx - minor, cy - minor, size, size, 0xF800);
|
||||
display.fillTriangle(cx + pad, cy - pad, cx + pad + half, cy - minor,
|
||||
cx + minor - 1, cy - pad, 0x07E0);
|
||||
display.fillCircle(cx - pad - half, cy + pad + half, half, 0x001F);
|
||||
display.fillRoundRect(cx + pad, cy + pad, size, size, size / 5, 0xFFE0);
|
||||
delay(PAUSE);
|
||||
} // END SHAPE EXAMPLE
|
||||
|
||||
// CHART EXAMPLES ----------------------------------------------------------
|
||||
|
||||
void show_charts() {
|
||||
// Draw some graphs and charts. GFX library doesn't handle these as native
|
||||
// object types, but it only takes a little code to build them from simple
|
||||
// shapes. This demonstrates:
|
||||
// - Drawing points and horizontal, vertical and arbitrary lines.
|
||||
// - Adapting to different-sized displays.
|
||||
// - Graphics being clipped off edge.
|
||||
// - Use of negative values to draw shapes "backward" from an anchor point.
|
||||
// - C technique for finding array size at runtime (vs hardcoding).
|
||||
|
||||
display.fillScreen(0); // Clear screen
|
||||
|
||||
const int16_t cx = display.width() / 2; // Center of screen =
|
||||
const int16_t cy = display.height() / 2; // half of width, height
|
||||
const int16_t minor = min(cx, cy); // Lesser of half width or height
|
||||
const int16_t major = max(cx, cy); // Greater of half width or height
|
||||
|
||||
// Let's start with a relatively simple sine wave graph with axes.
|
||||
// Draw graph axes centered on screen. drawFastHLine() and drawFastVLine()
|
||||
// need fewer arguments than normal 2-point line drawing shown later.
|
||||
display.drawFastHLine(0, cy, display.width(), 0x0210); // Dark blue
|
||||
display.drawFastVLine(cx, 0, display.height(), 0x0210);
|
||||
|
||||
// Then draw some tick marks along the axes. To keep this code simple,
|
||||
// these aren't to any particular scale, but a real program may want that.
|
||||
// The loop here draws them from the center outward and pays no mind
|
||||
// whether the screen is rectangular; any ticks that go off-screen will
|
||||
// be clipped by the library.
|
||||
for (uint8_t i=1; i<=10; i++) {
|
||||
// The Arduino map() function scales an input value (e.g. "i") from an
|
||||
// input range (0-10 here) to an output range (0 to major-1 here).
|
||||
// Very handy for making graphics adjust to different screens!
|
||||
int16_t n = map(i, 0, 10, 0, major - 1); // Tick offset relative to center point
|
||||
display.drawFastVLine(cx - n, cy - 5, 11, 0x210);
|
||||
display.drawFastVLine(cx + n, cy - 5, 11, 0x210);
|
||||
display.drawFastHLine(cx - 5, cy - n, 11, 0x210);
|
||||
display.drawFastHLine(cx - 5, cy + n, 11, 0x210);
|
||||
}
|
||||
|
||||
// Then draw sine wave over this using GFX drawPixel() function.
|
||||
for (int16_t x=0; x<display.width(); x++) { // Each column of screen...
|
||||
// Note the inverted Y axis here (cy-value rather than cy+value)
|
||||
// because GFX, like most graphics libraries, has +Y heading down,
|
||||
// vs. classic Cartesian coords which have +Y heading up.
|
||||
int16_t y = cy - (int16_t)(sin((x - cx) * 0.05) * (float)minor * 0.5);
|
||||
display.drawPixel(x, y, 0xFFFF);
|
||||
}
|
||||
|
||||
delay(PAUSE);
|
||||
|
||||
// Next, let's draw some charts...
|
||||
// NOTE: some other examples in this code take extra steps to avoid placing
|
||||
// anything off in the rounded corners of certain displays. The charts do
|
||||
// not. It's *possible* but would introduce a lot of complexity into code
|
||||
// that's trying to show the basics. We'll leave the clipped charts here as
|
||||
// a teachable moment: not all content suits all displays.
|
||||
|
||||
// A list of data to plot. These are Y values only; X assumed equidistant.
|
||||
const uint8_t data[] = { 31, 42, 36, 58, 67, 88 }; // Percentages, 0-100
|
||||
const uint8_t num_points = sizeof data / sizeof data[0]; // Length of data[] list
|
||||
|
||||
display.fillScreen(0); // Clear screen
|
||||
display.setFont(); // Use default (built-in) font
|
||||
display.setTextSize(2); // and 2X size for chart label
|
||||
|
||||
// Chart label is centered manually; 144 is the width in pixels of
|
||||
// "Widget Sales" at 2X scale (12 chars * 6 px * 2 = 144). A later example
|
||||
// shows automated centering based on string.
|
||||
display.setCursor((display.width() - 144) / 2, 0);
|
||||
display.print(F("Widget Sales")); // F("string") is in program memory, not RAM
|
||||
// The chart-drawing code is then written to skip the top 20 rows where
|
||||
// this label is located.
|
||||
|
||||
// First, a line chart, connecting the values point-to-point:
|
||||
|
||||
// Draw a grid of lines to provide scale & an interesting background.
|
||||
for (uint8_t i=0; i<11; i++) {
|
||||
int16_t x = map(i, 0, 10, 0, display.width() - 1); // Scale grid X to screen
|
||||
display.drawFastVLine(x, 20, display.height(), 0x001F);
|
||||
int16_t y = map(i, 0, 10, 20, display.height() - 1); // Scale grid Y to screen
|
||||
display.drawFastHLine(0, y, display.width(), 0x001F);
|
||||
}
|
||||
// And then draw lines connecting data points. Load up the first point...
|
||||
int16_t prev_x = 0;
|
||||
int16_t prev_y = map(data[0], 0, 100, display.height() - 1, 20);
|
||||
// Then connect lines to each subsequent point...
|
||||
for (uint8_t i=1; i<num_points; i++) {
|
||||
int16_t new_x = map(i, 0, num_points - 1, 0, display.width() - 1);
|
||||
int16_t new_y = map(data[i], 0, 100, display.height() - 1, 20);
|
||||
display.drawLine(prev_x, prev_y, new_x, new_y, 0x07FF);
|
||||
prev_x = new_x;
|
||||
prev_y = new_y;
|
||||
}
|
||||
// For visual interest, let's add a circle around each data point. This is
|
||||
// done in a second pass so the circles are always drawn "on top" of lines.
|
||||
for (uint8_t i=0; i<num_points; i++) {
|
||||
int16_t x = map(i, 0, num_points - 1, 0, display.width() - 1);
|
||||
int16_t y = map(data[i], 0, 100, display.height() - 1, 20);
|
||||
display.drawCircle(x, y, 5, 0xFFFF);
|
||||
}
|
||||
|
||||
delay(PAUSE);
|
||||
|
||||
// Then a bar chart of the same data...
|
||||
|
||||
// Erase the old chart but keep the label at top.
|
||||
display.fillRect(0, 20, display.width(), display.height() - 20, 0);
|
||||
|
||||
// Just draw the Y axis lines; bar chart doesn't really need X lines.
|
||||
for (uint8_t i=0; i<11; i++) {
|
||||
int16_t y = map(i, 0, 10, 20, display.height() - 1);
|
||||
display.drawFastHLine(0, y, display.width(), 0x001F);
|
||||
}
|
||||
|
||||
int bar_width = display.width() / num_points - 4; // 2px pad to either side
|
||||
for (uint8_t i=0; i<num_points; i++) {
|
||||
int16_t x = map(i, 0, num_points, 0, display.width()) + 2; // Left edge of bar
|
||||
int16_t height = map(data[i], 0, 100, 0, display.height() - 20);
|
||||
// Some GFX functions (rects, H/V lines and similar) can accept negative
|
||||
// width/height values. What this does is anchor the shape at the right or
|
||||
// bottom coordinate (rather than the usual left/top) and draw back from
|
||||
// there, hence the -height here (bar is anchored at bottom of screen):
|
||||
display.fillRect(x, display.height() - 1, bar_width, -height, 0xFFE0);
|
||||
}
|
||||
|
||||
delay(PAUSE);
|
||||
|
||||
} // END CHART EXAMPLES
|
||||
|
||||
// TEXT ALIGN FUNCTIONS ----------------------------------------------------
|
||||
|
||||
// Adafruit_GFX only handles left-aligned text. This is normal and by design;
|
||||
// it's a rare need that would further strain AVR by incurring a ton of extra
|
||||
// code to properly handle, and some details would confuse. If needed, these
|
||||
// functions give a fair approximation, with the "gotchas" that multi-line
|
||||
// input won't work, and this operates only as a println(), not print()
|
||||
// (though, unlike println(), cursor X does not reset to column 0, instead
|
||||
// returning to initial column and downward by font's line spacing). If you
|
||||
// can work with those constraints, it's a modest amount of code to copy
|
||||
// into a project. Or, if your project only needs one or two aligned strings,
|
||||
// simply use getTextBounds() for a bounding box and work from there.
|
||||
// DO NOT ATTEMPT TO MAKE THIS A GFX-NATIVE FEATURE, EVERYTHING WILL BREAK.
|
||||
|
||||
typedef enum { // Alignment options passed to functions below
|
||||
GFX_ALIGN_LEFT,
|
||||
GFX_ALIGN_CENTER,
|
||||
GFX_ALIGN_RIGHT
|
||||
} GFXalign;
|
||||
|
||||
// Draw text aligned relative to current cursor position. Arguments:
|
||||
// gfx : An Adafruit_GFX-derived type (e.g. display or canvas object).
|
||||
// str : String to print (as a char *).
|
||||
// align : One of the GFXalign values declared above.
|
||||
// GFX_ALIGN_LEFT is normal left-aligned println() behavior.
|
||||
// GFX_ALIGN_CENTER prints centered on cursor pos.
|
||||
// GFX_ALIGN_RIGHT prints right-aligned to cursor pos.
|
||||
// Cursor advances down one line a la println(). Column is unchanged.
|
||||
void print_aligned(Adafruit_GFX &gfx, const char *str,
|
||||
GFXalign align = GFX_ALIGN_LEFT) {
|
||||
uint16_t w, h;
|
||||
int16_t x, y, cursor_x, cursor_x_save;
|
||||
cursor_x = cursor_x_save = gfx.getCursorX();
|
||||
gfx.getTextBounds(str, 0, gfx.getCursorY(), &x, &y, &w, &h);
|
||||
if (align == GFX_ALIGN_RIGHT) cursor_x -= w;
|
||||
else if (align == GFX_ALIGN_CENTER) cursor_x -= w / 2;
|
||||
//gfx.drawRect(cursor_x, y, w, h, 0xF800); // Debug rect
|
||||
gfx.setCursor(cursor_x - x, gfx.getCursorY()); // Center/right align
|
||||
gfx.println(str);
|
||||
gfx.setCursor(cursor_x_save, gfx.getCursorY()); // Restore cursor X
|
||||
}
|
||||
|
||||
// Equivalent function for strings in flash memory (e.g. F("Foo")). Body
|
||||
// appears identical to above function, but with C++ overloading it it works
|
||||
// from flash instead of RAM. Any changes should be made in both places.
|
||||
void print_aligned(Adafruit_GFX &gfx, const __FlashStringHelper *str,
|
||||
GFXalign align = GFX_ALIGN_LEFT) {
|
||||
uint16_t w, h;
|
||||
int16_t x, y, cursor_x, cursor_x_save;
|
||||
cursor_x = cursor_x_save = gfx.getCursorX();
|
||||
gfx.getTextBounds(str, 0, gfx.getCursorY(), &x, &y, &w, &h);
|
||||
if (align == GFX_ALIGN_RIGHT) cursor_x -= w;
|
||||
else if (align == GFX_ALIGN_CENTER) cursor_x -= w / 2;
|
||||
//gfx.drawRect(cursor_x, y, w, h, 0xF800); // Debug rect
|
||||
gfx.setCursor(cursor_x - x, gfx.getCursorY()); // Center/right align
|
||||
gfx.println(str);
|
||||
gfx.setCursor(cursor_x_save, gfx.getCursorY()); // Restore cursor X
|
||||
}
|
||||
|
||||
// Equivalent function for Arduino Strings; converts to C string (char *)
|
||||
// and calls corresponding print_aligned() implementation.
|
||||
void print_aligned(Adafruit_GFX &gfx, const String &str,
|
||||
GFXalign align = GFX_ALIGN_LEFT) {
|
||||
print_aligned(gfx, const_cast<char *>(str.c_str()));
|
||||
}
|
||||
|
||||
// TEXT EXAMPLES -----------------------------------------------------------
|
||||
|
||||
// This section demonstrates:
|
||||
// - Using the default 5x7 built-in font, including scaling in each axis.
|
||||
// - How to access all characters of this font, including symbols.
|
||||
// - Using a custom font, including alignment techniques that aren't a normal
|
||||
// part of the GFX library (uses functions above).
|
||||
|
||||
void show_basic_text() {
|
||||
// Show text scaling with built-in font.
|
||||
display.fillScreen(0);
|
||||
display.setFont(); // Use default font
|
||||
display.setCursor(0, CORNER_RADIUS); // Initial cursor position
|
||||
display.setTextSize(1); // Default size
|
||||
display.println(F("Standard built-in font"));
|
||||
display.setTextSize(2);
|
||||
display.println(F("BIG TEXT"));
|
||||
display.setTextSize(3);
|
||||
// "BIGGER TEXT" won't fit on narrow screens, so abbreviate there.
|
||||
display.println((display.width() >= 200) ? F("BIGGER TEXT") : F("BIGGER"));
|
||||
display.setTextSize(2, 4);
|
||||
display.println(F("TALL and"));
|
||||
display.setTextSize(4, 2);
|
||||
display.println(F("WIDE"));
|
||||
|
||||
delay(PAUSE);
|
||||
} // END BASIC TEXT EXAMPLE
|
||||
|
||||
void show_char_map() {
|
||||
// "Code Page 437" is a name given to the original IBM PC character set.
|
||||
// Despite age and limited language support, still seen in small embedded
|
||||
// settings as it has some useful symbols and accented characters. The
|
||||
// default 5x7 pixel font of Adafruit_GFX is modeled after CP437. This
|
||||
// function draws a table of all the characters & explains some issues.
|
||||
|
||||
// There are 256 characters in all. Draw table as 16 rows of 16 columns,
|
||||
// plus hexadecimal row & column labels. How big can each cell be drawn?
|
||||
const int cell_size = min(display.width(), display.height()) / 17;
|
||||
if (cell_size < 8) return; // Screen is too small for table, skip example.
|
||||
const int total_size = cell_size * 17; // 16 cells + 1 row or column label
|
||||
|
||||
// Set up for default 5x7 font at 1:1 scale. Custom fonts are NOT used
|
||||
// here as most are only 128 characters to save space (the "7b" at the
|
||||
// end of many GFX font names means "7 bits," i.e. 128 characters).
|
||||
display.setFont();
|
||||
display.setTextSize(1);
|
||||
|
||||
// Early Adafruit_GFX was missing one symbol, throwing off some indices!
|
||||
// But fixing the library would break MANY existing sketches that relied
|
||||
// on the degrees symbol and others. The default behavior is thus "broken"
|
||||
// to keep older code working. New code can access the CORRECT full CP437
|
||||
// table by calling this function like so:
|
||||
display.cp437(true);
|
||||
|
||||
display.fillScreen(0);
|
||||
|
||||
const int16_t x = (display.width() - total_size) / 2; // Upper left corner of
|
||||
int16_t y = (display.height() - total_size) / 2; // table centered on screen
|
||||
if (y >= 4) { // If there's a little extra space above & below, scoot table
|
||||
y += 4; // down a few pixels and show a message centered at top.
|
||||
display.setCursor((display.width() - 114) / 2, 0); // 114 = pixel width
|
||||
display.print(F("CP437 Character Map")); // of this message
|
||||
}
|
||||
|
||||
const int16_t inset_x = (cell_size - 5) / 2; // To center each character within cell,
|
||||
const int16_t inset_y = (cell_size - 8) / 2; // compute X & Y offset from corner.
|
||||
|
||||
for (uint8_t row=0; row<16; row++) { // 16 down...
|
||||
// Draw row and columm headings as hexadecimal single digits. To get the
|
||||
// hex value for a specific character, combine the left & top labels,
|
||||
// e.g. Pi symbol is row E, column 3, thus: display.print((char)0xE3);
|
||||
display.setCursor(x + (row + 1) * cell_size + inset_x, y + inset_y);
|
||||
display.print(row, HEX); // This actually draws column labels
|
||||
display.setCursor(x + inset_x, y + (row + 1) * cell_size + inset_y);
|
||||
display.print(row, HEX); // and THIS is the row labels
|
||||
for (uint8_t col=0; col<16; col++) { // 16 across...
|
||||
if ((row + col) & 1) { // Fill alternating cells w/gray
|
||||
display.fillRect(x + (col + 1) * cell_size, y + (row + 1) * cell_size,
|
||||
cell_size, cell_size, 0x630C);
|
||||
}
|
||||
// drawChar() bypasses usual cursor positioning to go direct to an X/Y
|
||||
// location. If foreground & background match, it's drawn transparent.
|
||||
display.drawChar(x + (col + 1) * cell_size + inset_x,
|
||||
y + (row + 1) * cell_size + inset_y, row * 16 + col,
|
||||
0xFFFF, 0xFFFF, 1);
|
||||
}
|
||||
}
|
||||
|
||||
delay(PAUSE * 2);
|
||||
} // END CHAR MAP EXAMPLE
|
||||
|
||||
void show_custom_text() {
|
||||
// Show use of custom fonts, plus how to do center or right alignment
|
||||
// using some additional functions provided earlier.
|
||||
|
||||
display.fillScreen(0);
|
||||
display.setFont(&FreeSansBold18pt7b);
|
||||
display.setTextSize(1);
|
||||
display.setTextWrap(false); // Allow text off edges
|
||||
|
||||
// Get "M height" of custom font and move initial base line there:
|
||||
uint16_t w, h;
|
||||
int16_t x, y;
|
||||
display.getTextBounds("M", 0, 0, &x, &y, &w, &h);
|
||||
// On rounded 240x280 display in tall orientation, "Custom Font" gets
|
||||
// clipped by top corners. Scoot text down a few pixels in that one case.
|
||||
if (CORNER_RADIUS && (display.height() == 280)) h += 20;
|
||||
display.setCursor(display.width() / 2, h);
|
||||
|
||||
if (display.width() >= 200) {
|
||||
print_aligned(display, F("Custom Font"), GFX_ALIGN_CENTER);
|
||||
display.setCursor(0, display.getCursorY() + 10);
|
||||
print_aligned(display, F("Align Left"), GFX_ALIGN_LEFT);
|
||||
display.setCursor(display.width() / 2, display.getCursorY());
|
||||
print_aligned(display, F("Centered"), GFX_ALIGN_CENTER);
|
||||
// Small rounded screen, when oriented the wide way, "Right" gets
|
||||
// clipped by bottom right corner. Scoot left to compensate.
|
||||
int16_t x_offset = (CORNER_RADIUS && (display.height() < 200)) ? 15 : 0;
|
||||
display.setCursor(display.width() - x_offset, display.getCursorY());
|
||||
print_aligned(display, F("Align Right"), GFX_ALIGN_RIGHT);
|
||||
} else {
|
||||
// On narrow screens, use abbreviated messages
|
||||
print_aligned(display, F("Font &"), GFX_ALIGN_CENTER);
|
||||
print_aligned(display, F("Align"), GFX_ALIGN_CENTER);
|
||||
display.setCursor(0, display.getCursorY() + 10);
|
||||
print_aligned(display, F("Left"), GFX_ALIGN_LEFT);
|
||||
display.setCursor(display.width() / 2, display.getCursorY());
|
||||
print_aligned(display, F("Center"), GFX_ALIGN_CENTER);
|
||||
display.setCursor(display.width(), display.getCursorY());
|
||||
print_aligned(display, F("Right"), GFX_ALIGN_RIGHT);
|
||||
}
|
||||
|
||||
delay(PAUSE);
|
||||
} // END CUSTOM FONT EXAMPLE
|
||||
|
||||
// BITMAP EXAMPLE ----------------------------------------------------------
|
||||
|
||||
// This section demonstrates:
|
||||
// - Embedding a small bitmap in the code (flash memory).
|
||||
// - Drawing that bitmap in various colors, and transparently (only '1' bits
|
||||
// are drawn; '0' bits are skipped, leaving screen contents in place).
|
||||
// - Use of the color565() function to decimate 24-bit RGB to 16 bits.
|
||||
|
||||
#define HEX_WIDTH 16 // Bitmap width in pixels
|
||||
#define HEX_HEIGHT 16 // Bitmap height in pixels
|
||||
// Bitmap data. PROGMEM ensures it's in flash memory (not RAM). And while
|
||||
// it would be valid to leave the brackets empty here (i.e. hex_bitmap[]),
|
||||
// having dimensions with a little math makes the compiler verify the
|
||||
// correct number of bytes are present in the list.
|
||||
PROGMEM const uint8_t hex_bitmap[(HEX_WIDTH + 7) / 8 * HEX_HEIGHT] = {
|
||||
0b00000001, 0b10000000,
|
||||
0b00000111, 0b11100000,
|
||||
0b00011111, 0b11111000,
|
||||
0b01111111, 0b11111110,
|
||||
0b01111111, 0b11111110,
|
||||
0b01111111, 0b11111110,
|
||||
0b01111111, 0b11111110,
|
||||
0b01111111, 0b11111110,
|
||||
0b01111111, 0b11111110,
|
||||
0b01111111, 0b11111110,
|
||||
0b01111111, 0b11111110,
|
||||
0b01111111, 0b11111110,
|
||||
0b01111111, 0b11111110,
|
||||
0b00011111, 0b11111000,
|
||||
0b00000111, 0b11100000,
|
||||
0b00000001, 0b10000000,
|
||||
};
|
||||
#define Y_SPACING (HEX_HEIGHT - 2) // Used by code below for positioning
|
||||
|
||||
void show_bitmap() {
|
||||
display.fillScreen(0);
|
||||
|
||||
// Not screen center, but UL coordinates of center hexagon bitmap
|
||||
const int16_t center_x = (display.width() - HEX_WIDTH) / 2;
|
||||
const int16_t center_y = (display.height() - HEX_HEIGHT) / 2;
|
||||
const uint8_t steps = min((display.height() - HEX_HEIGHT) / Y_SPACING,
|
||||
display.width() / HEX_WIDTH - 1) / 2;
|
||||
|
||||
display.drawBitmap(center_x, center_y, hex_bitmap, HEX_WIDTH, HEX_HEIGHT,
|
||||
0xFFFF); // Draw center hexagon in white
|
||||
|
||||
// Tile the hexagon bitmap repeatedly in a range of hues. Don't mind the
|
||||
// bit of repetition in the math, the optimizer easily picks this up.
|
||||
// Also, if math looks odd, keep in mind "PEMDAS" operator precedence;
|
||||
// multiplication and division occur before addition and subtraction.
|
||||
for (uint8_t a=0; a<=steps; a++) {
|
||||
for (uint8_t b=1; b<=steps; b++) {
|
||||
display.drawBitmap( // Right section centered red: a = green, b = blue
|
||||
center_x + (a + b) * HEX_WIDTH / 2,
|
||||
center_y + (a - b) * Y_SPACING,
|
||||
hex_bitmap, HEX_WIDTH, HEX_HEIGHT,
|
||||
display.color565(255, 255 - 255 * a / steps, 255 - 255 * b / steps));
|
||||
display.drawBitmap( // UL section centered green: a = blue, b = red
|
||||
center_x - b * HEX_WIDTH + a * HEX_WIDTH / 2,
|
||||
center_y - a * Y_SPACING,
|
||||
hex_bitmap, HEX_WIDTH, HEX_HEIGHT,
|
||||
display.color565(255 - 255 * b / steps, 255, 255 - 255 * a / steps));
|
||||
display.drawBitmap( // LL section centered blue: a = red, b = green
|
||||
center_x - a * HEX_WIDTH + b * HEX_WIDTH / 2,
|
||||
center_y + b * Y_SPACING,
|
||||
hex_bitmap, HEX_WIDTH, HEX_HEIGHT,
|
||||
display.color565(255 - 255 * a / steps, 255 - 255 * b / steps, 255));
|
||||
}
|
||||
}
|
||||
|
||||
delay(PAUSE);
|
||||
} // END BITMAP EXAMPLE
|
||||
|
||||
// CANVAS EXAMPLE ----------------------------------------------------------
|
||||
|
||||
// This section demonstrates:
|
||||
// - How to refresh changing values onscreen without erase/redraw flicker.
|
||||
// - Using an offscreen canvas. It's similar to a bitmap above, but rather
|
||||
// than a fixed pattern in flash memory, it's drawable like the screen.
|
||||
// - More tips on text alignment, and adapting to different screen sizes.
|
||||
|
||||
#define PADDING 6 // Pixels between axis label and value
|
||||
|
||||
void show_canvas() {
|
||||
// For this example, let's suppose we want to display live readings from a
|
||||
// sensor such as a three-axis accelerometer, something like:
|
||||
// X: (number)
|
||||
// Y: (number)
|
||||
// Z: (number)
|
||||
// To look extra classy, we want a custom font, and the labels for each
|
||||
// axis are right-aligned so the ':' characters line up...
|
||||
|
||||
display.setFont(&FreeSansBold18pt7b); // Use a custom font
|
||||
display.setTextSize(1); // and reset to 1:1 scale
|
||||
|
||||
const char *label[] = { "X:", "Y:", "Z:" }; // Labels for each axis
|
||||
const uint16_t color[] = { 0xF800, 0x07E0, 0x001F }; // Colors for each value
|
||||
|
||||
// To get the labels right-aligned, one option would be simple trial and
|
||||
// error to find a column that looks good and doesn't clip anything off.
|
||||
// Let's do this dynamically though, so it adapts to any font or labels!
|
||||
// Start by finding the widest of the label strings:
|
||||
uint16_t w, h, max_w = 0;
|
||||
int16_t x, y;
|
||||
for (uint8_t i=0; i<3; i++) { // For each label...
|
||||
display.getTextBounds(label[i], 0, 0, &x, &y, &w, &h);
|
||||
if (w > max_w) max_w = w; // Keep track of widest label
|
||||
}
|
||||
|
||||
// Rounded corners throwing us a curve again. If needed, scoot everything
|
||||
// to the right a bit on wide displays, down a bit on tall ones.
|
||||
int16_t y_offset = 0;
|
||||
if (display.width() > display.height()) max_w += CORNER_RADIUS;
|
||||
else y_offset = CORNER_RADIUS;
|
||||
|
||||
// Now we have max_w for right-aligning the labels. Before we draw them
|
||||
// though...in order to perform flicker-free updates, the numbers we show
|
||||
// will be rendered in either a GFXcanvas1 or GFXcanvas16 object; a 1-bit
|
||||
// or 16-bit offscreen bitmap, RAM permitting. The correct size for this
|
||||
// canvas could also be trial-and-errored, but again let's make this adapt
|
||||
// automatically. The width of the canvas will span from max_w (plus a few
|
||||
// pixels for padding) to the right edge. But the height? Looking at an
|
||||
// uppercase 'M' can work in many situations, but some fonts have ascenders
|
||||
// and descenders on digits, and in some locales a comma (extending below
|
||||
// the baseline) is the decimal separator. Feed ALL the numeric chars into
|
||||
// getTextBounds() for a cumulative height:
|
||||
display.setTextWrap(false); // Keep on one line
|
||||
display.getTextBounds(F("0123456789.,-"), 0, 0, &x, &y, &w, &h);
|
||||
|
||||
// Now declare a GFXcanvas16 object based on the computed width & height:
|
||||
GFXcanvas16 canvas16(display.width() - max_w - PADDING, h);
|
||||
|
||||
// Small devices (e.g. ATmega328p) will almost certainly lack enough RAM
|
||||
// for the canvas. Check if canvas buffer exists. If not, fall back on
|
||||
// using a 1-bit (rather than 16-bit) canvas. Much more RAM friendly, but
|
||||
// not as fast to draw. If a project doesn't require super interactive
|
||||
// updates, consider just going straight for the more compact Canvas1.
|
||||
if (canvas16.getBuffer()) {
|
||||
// If here, 16-bit canvas allocated successfully! Point of interest,
|
||||
// only one canvas is needed for this example, we can reuse it for all
|
||||
// three numbers because the regions are the same size.
|
||||
|
||||
// display and canvas are independent drawable objects; must explicitly
|
||||
// set the same custom font to use on the canvas now:
|
||||
canvas16.setFont(&FreeSansBold18pt7b);
|
||||
|
||||
// Clear display and print labels. Once drawn, these remain untouched.
|
||||
display.fillScreen(0);
|
||||
display.setCursor(max_w, -y + y_offset); // Set baseline for first row
|
||||
for (uint8_t i=0; i<3; i++) print_aligned(display, label[i], GFX_ALIGN_RIGHT);
|
||||
|
||||
// Last part now is to print numbers on the canvas and copy the canvas to
|
||||
// the display, repeating for several seconds...
|
||||
uint32_t elapsed, startTime = millis();
|
||||
while ((elapsed = (millis() - startTime)) <= PAUSE * 2) {
|
||||
for (uint8_t i=0; i<3; i++) { // For each label...
|
||||
canvas16.fillScreen(0); // fillScreen() in this case clears canvas
|
||||
canvas16.setCursor(0, -y); // Reset baseline for custom font
|
||||
canvas16.setTextColor(color[i]);
|
||||
// These aren't real accelerometer readings, just cool-looking numbers.
|
||||
// Notice we print to the canvas, NOT the display:
|
||||
canvas16.print(sin(elapsed / 200.0 + (float)i * M_PI * 2.0 / 3.0), 5);
|
||||
// And HERE is the secret sauce to flicker-free updates. Canvas details
|
||||
// can be passed to the drawRGBBitmap() function, which fully overwrites
|
||||
// prior screen contents in that area. yAdvance is font line spacing.
|
||||
display.drawRGBBitmap(max_w + PADDING, i * FreeSansBold18pt7b.yAdvance +
|
||||
y_offset, canvas16.getBuffer(), canvas16.width(),
|
||||
canvas16.height());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Insufficient RAM for Canvas16. Try declaring a 1-bit canvas instead...
|
||||
GFXcanvas1 canvas1(display.width() - max_w - PADDING, h);
|
||||
// If even this smaller object fails, can't proceed, cancel this example.
|
||||
if (!canvas1.getBuffer()) return;
|
||||
|
||||
// Remainder here is nearly identical to the code above, simply using a
|
||||
// different canvas type. It's stripped of most comments for brevity.
|
||||
canvas1.setFont(&FreeSansBold18pt7b);
|
||||
display.fillScreen(0);
|
||||
display.setCursor(max_w, -y + y_offset);
|
||||
for (uint8_t i=0; i<3; i++) print_aligned(display, label[i], GFX_ALIGN_RIGHT);
|
||||
uint32_t elapsed, startTime = millis();
|
||||
while ((elapsed = (millis() - startTime)) <= PAUSE * 2) {
|
||||
for (uint8_t i=0; i<3; i++) {
|
||||
canvas1.fillScreen(0);
|
||||
canvas1.setCursor(0, -y);
|
||||
canvas1.print(sin(elapsed / 200.0 + (float)i * M_PI * 2.0 / 3.0), 5);
|
||||
// Here's the secret sauce to flicker-free updates with GFXcanvas1.
|
||||
// Canvas details can be passed to the drawBitmap() function, and by
|
||||
// specifying both a foreground AND BACKGROUND color (0), this will fully
|
||||
// overwrite/erase prior screen contents in that area (vs transparent).
|
||||
display.drawBitmap(max_w + PADDING, i * FreeSansBold18pt7b.yAdvance +
|
||||
y_offset, canvas1.getBuffer(), canvas1.width(),
|
||||
canvas1.height(), color[i], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Because canvas object was declared locally to this function, it's freed
|
||||
// automatically when the function returns; no explicit delete needed.
|
||||
} // END CANVAS EXAMPLE
|
||||
326
EYESPI_BFF/CircuitPython_EYESPI_BFF/code.py
Normal file
326
EYESPI_BFF/CircuitPython_EYESPI_BFF/code.py
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
# SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries
|
||||
# SPDX-FileCopyrightText: Adapted from Phil B.'s 16bit_hello Arduino Code
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
'''Graphics example for the EYESPI BFF'''
|
||||
|
||||
import gc
|
||||
import math
|
||||
from random import randint
|
||||
import time
|
||||
import displayio
|
||||
import board
|
||||
import vectorio
|
||||
import terminalio
|
||||
import simpleio
|
||||
from adafruit_st7789 import ST7789
|
||||
from adafruit_bitmap_font import bitmap_font
|
||||
from adafruit_display_text import label, wrap_text_to_lines
|
||||
from adafruit_display_shapes.rect import Rect
|
||||
from adafruit_display_shapes.circle import Circle
|
||||
from adafruit_display_shapes.roundrect import RoundRect
|
||||
from adafruit_display_shapes.triangle import Triangle
|
||||
from adafruit_display_shapes.line import Line
|
||||
|
||||
displayio.release_displays()
|
||||
|
||||
spi = board.SPI()
|
||||
tft_cs = board.TX
|
||||
tft_dc = board.RX
|
||||
|
||||
display_bus = displayio.FourWire(
|
||||
spi, command=tft_dc, chip_select=tft_cs, reset=None
|
||||
)
|
||||
|
||||
display = ST7789(display_bus, width=240, height=240, rowstart=80)
|
||||
|
||||
bitmap = displayio.Bitmap(display.width, display.height, 3)
|
||||
|
||||
red = 0xff0000
|
||||
yellow = 0xcccc00
|
||||
orange = 0xff5500
|
||||
blue = 0x0000ff
|
||||
pink = 0xff00ff
|
||||
purple = 0x5500ff
|
||||
white = 0xffffff
|
||||
green = 0x00ff00
|
||||
aqua = 0x125690
|
||||
|
||||
palette = displayio.Palette(3)
|
||||
palette[0] = 0x000000 # black
|
||||
palette[1] = white
|
||||
palette[2] = yellow
|
||||
|
||||
palette.make_transparent(0)
|
||||
|
||||
tile_grid = displayio.TileGrid(bitmap, pixel_shader=palette)
|
||||
|
||||
group = displayio.Group()
|
||||
|
||||
def clean_up(group_name):
|
||||
for _ in range(len(group_name)):
|
||||
group_name.pop()
|
||||
gc.collect()
|
||||
|
||||
def show_shapes():
|
||||
gc.collect()
|
||||
cx = int(display.width / 2)
|
||||
cy = int(display.height / 2)
|
||||
minor = min(cx, cy)
|
||||
pad = 5
|
||||
size = minor - pad
|
||||
half = int(size / 2)
|
||||
rect = Rect(cx - minor, cy - minor, size, size, stroke = 1, fill=red, outline = red)
|
||||
tri = Triangle(cx + pad, cy - pad, cx + pad + half, cy - minor,
|
||||
cx + minor - 1, cy - pad, fill=green, outline = green)
|
||||
circ = Circle(cx - pad - half, cy + pad + half, half, fill=blue, stroke = 1, outline = blue)
|
||||
rnd = RoundRect(cx + pad, cy + pad, size, size, int(size / 5), stroke = 1,
|
||||
fill=yellow, outline = yellow)
|
||||
|
||||
group.append(rect)
|
||||
group.append(tri)
|
||||
group.append(circ)
|
||||
group.append(rnd)
|
||||
rect.fill = None
|
||||
tri.fill = None
|
||||
circ.fill = None
|
||||
rnd.fill = None
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
rect.fill = red
|
||||
tri.fill = green
|
||||
circ.fill = blue
|
||||
rnd.fill = yellow
|
||||
time.sleep(2)
|
||||
clean_up(group)
|
||||
del rect
|
||||
del tri
|
||||
del circ
|
||||
del rnd
|
||||
gc.collect()
|
||||
|
||||
def sine_chart():
|
||||
gc.collect()
|
||||
cx = int(display.width / 2)
|
||||
cy = int(display.height / 2)
|
||||
minor = min(cx, cy)
|
||||
major = max(cx, cy)
|
||||
|
||||
group.append(Line(cx, 0, cx, display.height, blue)) # v
|
||||
group.append(Line(0, cy, display.width, cy, blue)) # h
|
||||
|
||||
for i in range(10):
|
||||
_n = simpleio.map_range(i, 0, 10, 0, major - 1)
|
||||
n = int(_n)
|
||||
group.append(Line(cx - n, cy - 5, cx - n, (cy - 5) + 11, blue)) # v
|
||||
group.append(Line(cx + n, cy - 5, cx + n, (cy - 5) + 11, blue)) # v
|
||||
group.append(Line(cx - 5, cy - n, (cx - 5) + 11, cy - n, blue)) # h
|
||||
group.append(Line(cx - 5, cy + n, (cx - 5) + 11, cy + n, blue)) # h
|
||||
|
||||
for x in range(display.width):
|
||||
y = cy - int(math.sin((x - cx) * 0.05) * float(minor * 0.5))
|
||||
bitmap[x, y] = 1
|
||||
group.append(tile_grid)
|
||||
time.sleep(2)
|
||||
clean_up(group)
|
||||
|
||||
def widget0():
|
||||
gc.collect()
|
||||
data = [31, 42, 36, 58, 67, 88]
|
||||
num_points = len(data)
|
||||
|
||||
text_area = label.Label(terminalio.FONT, text="Widget Sales", color=white)
|
||||
text_area.anchor_point = (0.5, 0.0)
|
||||
text_area.anchored_position = (display.width / 2, 3)
|
||||
group.append(text_area)
|
||||
for i in range(11):
|
||||
_x = simpleio.map_range(i, 0, 10, 0, display.width - 1)
|
||||
x = int(_x)
|
||||
group.append(Line(x, 20, x, display.height, blue))
|
||||
_y = simpleio.map_range(i, 0, 10, 20, display.height - 1)
|
||||
y = int(_y)
|
||||
group.append(Line(0, y, display.width, y, blue))
|
||||
prev_x = 0
|
||||
_prev_y = simpleio.map_range(data[0], 0, 100, display.height - 1, 20)
|
||||
prev_y = int(_prev_y)
|
||||
for i in range(1, num_points):
|
||||
_new_x = simpleio.map_range(i, 0, num_points - 1, 0, display.width - 1)
|
||||
new_x = int(_new_x)
|
||||
_new_y = simpleio.map_range(data[i], 0, 100, display.height - 1, 20)
|
||||
new_y = int(_new_y)
|
||||
group.append(Line(prev_x, prev_y, new_x, new_y, aqua))
|
||||
prev_x = new_x
|
||||
prev_y = new_y
|
||||
|
||||
for i in range(num_points):
|
||||
_x = simpleio.map_range(i, 0, num_points - 1, 0, display.width - 1)
|
||||
x = int(_x)
|
||||
_y = simpleio.map_range(data[i], 0, 100, display.height - 1, 20)
|
||||
y = int(_y)
|
||||
group.append(Circle(x, y, 5, fill=None, stroke = 2, outline = white))
|
||||
|
||||
time.sleep(2)
|
||||
clean_up(group)
|
||||
|
||||
def widget1():
|
||||
gc.collect()
|
||||
data = [31, 42, 36, 58, 67, 88]
|
||||
num_points = len(data)
|
||||
bar_width = int(display.width / num_points) - 4
|
||||
x_mapped_w = display.width + 2
|
||||
h_mapped_h = display.height + 20
|
||||
|
||||
text_area = label.Label(terminalio.FONT, text="Widget Sales", color=white)
|
||||
text_area.anchor_point = (0.5, 0.0)
|
||||
text_area.anchored_position = (display.width / 2, 3)
|
||||
group.append(text_area)
|
||||
for i in range(11):
|
||||
_y = simpleio.map_range(i, 0, 10, 20, display.height - 1)
|
||||
y = int(_y)
|
||||
group.append(Line(0, y, display.width, y, blue))
|
||||
for i in range(num_points):
|
||||
_x = simpleio.map_range(i, 0, num_points, 0, x_mapped_w)
|
||||
x = int(_x)
|
||||
_height = simpleio.map_range(data[i], 0, 100, h_mapped_h, 0)
|
||||
height = int(_height)
|
||||
group.append(vectorio.Rectangle(pixel_shader=palette, width=bar_width,
|
||||
height=display.height + 1, x=x, y=height, color_index = 2))
|
||||
|
||||
time.sleep(2)
|
||||
clean_up(group)
|
||||
|
||||
def text_align():
|
||||
gc.collect()
|
||||
TEXT = "hello world"
|
||||
|
||||
text_area_top_left = label.Label(terminalio.FONT, text=TEXT, color=red)
|
||||
text_area_top_left.anchor_point = (0.0, 0.0)
|
||||
text_area_top_left.anchored_position = (0, 0)
|
||||
|
||||
text_area_top_middle = label.Label(terminalio.FONT, text=TEXT, color=orange)
|
||||
text_area_top_middle.anchor_point = (0.5, 0.0)
|
||||
text_area_top_middle.anchored_position = (display.width / 2, 0)
|
||||
|
||||
text_area_top_right = label.Label(terminalio.FONT, text=TEXT, color=yellow)
|
||||
text_area_top_right.anchor_point = (1.0, 0.0)
|
||||
text_area_top_right.anchored_position = (display.width, 0)
|
||||
|
||||
text_area_middle_left = label.Label(terminalio.FONT, text=TEXT, color=green)
|
||||
text_area_middle_left.anchor_point = (0.0, 0.5)
|
||||
text_area_middle_left.anchored_position = (0, display.height / 2)
|
||||
|
||||
text_area_middle_middle = label.Label(terminalio.FONT, text=TEXT, color=aqua)
|
||||
text_area_middle_middle.anchor_point = (0.5, 0.5)
|
||||
text_area_middle_middle.anchored_position = (display.width / 2, display.height / 2)
|
||||
|
||||
text_area_middle_right = label.Label(terminalio.FONT, text=TEXT, color=blue)
|
||||
text_area_middle_right.anchor_point = (1.0, 0.5)
|
||||
text_area_middle_right.anchored_position = (display.width, display.height / 2)
|
||||
|
||||
text_area_bottom_left = label.Label(terminalio.FONT, text=TEXT, color=purple)
|
||||
text_area_bottom_left.anchor_point = (0.0, 1.0)
|
||||
text_area_bottom_left.anchored_position = (0, display.height)
|
||||
|
||||
text_area_bottom_middle = label.Label(terminalio.FONT, text=TEXT, color=pink)
|
||||
text_area_bottom_middle.anchor_point = (0.5, 1.0)
|
||||
text_area_bottom_middle.anchored_position = (display.width / 2, display.height)
|
||||
|
||||
text_area_bottom_right = label.Label(terminalio.FONT, text=TEXT, color=white)
|
||||
text_area_bottom_right.anchor_point = (1.0, 1.0)
|
||||
text_area_bottom_right.anchored_position = (display.width, display.height)
|
||||
|
||||
group.append(text_area_top_middle)
|
||||
group.append(text_area_top_left)
|
||||
group.append(text_area_top_right)
|
||||
group.append(text_area_middle_middle)
|
||||
group.append(text_area_middle_left)
|
||||
group.append(text_area_middle_right)
|
||||
group.append(text_area_bottom_middle)
|
||||
group.append(text_area_bottom_left)
|
||||
group.append(text_area_bottom_right)
|
||||
|
||||
time.sleep(2)
|
||||
clean_up(group)
|
||||
|
||||
def custom_font():
|
||||
gc.collect()
|
||||
my_font = bitmap_font.load_font("/Helvetica-Bold-16.pcf")
|
||||
text_sample = "The quick brown fox jumps over the lazy dog."
|
||||
text_sample = "\n".join(wrap_text_to_lines(text_sample, 28))
|
||||
text_area = label.Label(my_font, text="Custom Font", color=white)
|
||||
text_area.anchor_point = (0.0, 0.0)
|
||||
text_area.anchored_position = (0, 0)
|
||||
|
||||
sample_text = label.Label(my_font, text=text_sample)
|
||||
sample_text.anchor_point = (0.5, 0.5)
|
||||
sample_text.anchored_position = (display.width / 2, display.height / 2)
|
||||
|
||||
group.append(text_area)
|
||||
group.append(sample_text)
|
||||
|
||||
time.sleep(2)
|
||||
clean_up(group)
|
||||
|
||||
del my_font
|
||||
gc.collect()
|
||||
|
||||
def bitmap_example():
|
||||
gc.collect()
|
||||
blinka_bitmap = displayio.OnDiskBitmap("/blinka_computer.bmp")
|
||||
blinka_grid = displayio.TileGrid(blinka_bitmap, pixel_shader=blinka_bitmap.pixel_shader)
|
||||
gc.collect()
|
||||
group.append(blinka_grid)
|
||||
|
||||
time.sleep(2)
|
||||
clean_up(group)
|
||||
|
||||
del blinka_grid
|
||||
del blinka_bitmap
|
||||
gc.collect()
|
||||
|
||||
def sensor_values():
|
||||
gc.collect()
|
||||
text_x = "X: %d" % randint(-25, 25)
|
||||
text_y = "Y: %d" % randint(-25, 25)
|
||||
text_z = "Z: %d" % randint(-25, 25)
|
||||
x_text = label.Label(terminalio.FONT, text=text_x, color=red)
|
||||
x_text.anchor_point = (0.0, 0.0)
|
||||
x_text.anchored_position = (2, 0)
|
||||
y_text = label.Label(terminalio.FONT, text=text_y, color=green)
|
||||
y_text.anchor_point = (0.0, 0.0)
|
||||
y_text.anchored_position = (2, 10)
|
||||
z_text = label.Label(terminalio.FONT, text=text_z, color=blue)
|
||||
z_text.anchor_point = (0.0, 0.0)
|
||||
z_text.anchored_position = (2, 20)
|
||||
group.append(x_text)
|
||||
group.append(y_text)
|
||||
group.append(z_text)
|
||||
|
||||
for i in range(40):
|
||||
if i == 10:
|
||||
group.scale = 2
|
||||
elif i == 20:
|
||||
group.scale = 3
|
||||
elif i == 30:
|
||||
group.scale = 4
|
||||
x_text.text = "X: %d" % randint(-50, 50)
|
||||
y_text.text = "Y: %d" % randint(-50, 50)
|
||||
z_text.text = "Z: %d" % randint(-50, 50)
|
||||
time.sleep(0.1)
|
||||
time.sleep(0.1)
|
||||
clean_up(group)
|
||||
group.scale = 1
|
||||
|
||||
display.show(group)
|
||||
|
||||
while True:
|
||||
show_shapes()
|
||||
sine_chart()
|
||||
widget0()
|
||||
widget1()
|
||||
text_align()
|
||||
custom_font()
|
||||
bitmap_example()
|
||||
sensor_values()
|
||||
Loading…
Reference in a new issue