Salut @tobozo,
I liked the way you represented WiFi channel saturation with your WiFiChanViz
app that I discovered on Twitter:
So I challenged myself to try to remake it by myself for the ESPboy. I kept your idea of setting the height of the channels according to the number of access points occupying them. But I chose a different color scale depending on the best-observed signal quality for each channel.
And I added the ability to browse between channels to see the list of access points broadcasting a WiFi network.
Here is how it looks:

Well, the WiFi antenna of the M5Stack is probably of better quality than the one of the Wemos D1 mini that drives the ESPboy...
I then took a look at your code to compare our approaches. They are pretty similar, although we have a different way of calculating the luminance for the historical perspective fade:
// --------------------------------------------------------
// tobozo's method
// --------------------------------------------------------
// luminosity reducer, taken from Bodmer's antialiased font
static uint16_t luminance(uint16_t color, uint8_t luminance)
{
// Extract rgb colours and stretch range to 0 - 255
uint16_t r = (color & 0xF800) >> 8; r |= (r >> 5);
uint16_t g = (color & 0x07E0) >> 3; g |= (g >> 6);
uint16_t b = (color & 0x001F) << 3; b |= (b >> 5);
b = ((b * (uint16_t)luminance + 255) >> 8) & 0x00F8;
g = ((g * (uint16_t)luminance + 255) >> 8) & 0x00FC;
r = ((r * (uint16_t)luminance + 255) >> 8) & 0x00F8;
return (r << 8) | (g << 3) | (b >> 3);
}
// Use as a gfx replacement for tft.fillScreen(TFT_BLACK).
// Produces a strobe effect by reducing luminosity on all non-black pixels.
// Limitations:
// - 16bits colors only
// - Only fades to black
// - frame rate must be >15fps
// - Sluggish when the sprite has too many (>50%) non black pixels
static void spriteFadeOut( LGFX_Sprite *sprite, uint8_t strength )
{
int32_t w = sprite->width();
int32_t h = sprite->height();
int32_t l = w*h;
uint16_t* framebuf = (uint16_t*)sprite->getBuffer();
for( uint32_t i=0;i<l;i++) {
if( framebuf[i]!=TFT_BLACK ) {
uint16_t pixcolor = (framebuf[i] >> 8) | (framebuf[i] << 8);
pixcolor = luminance( pixcolor, strength );
framebuf[i] = pixcolor<<8 | pixcolor>>8;
}
}
}
// --------------------------------------------------------
// m1cr0lab's method
// --------------------------------------------------------
uint16_t * const fb = (uint16_t*)fb1->getBuffer();
uint16_t const len = GRAPH_WIDTH * GRAPH_HEIGHT;
uint16_t color;
uint8_t. r, g, b;
for (uint16_t i = 0; i < len; ++i) {
if (fb[i]) {
// swaps endianness
color = fb[i] >> 8 | fb[i] << 8;
// extracts the primary colors
r = color >> 11;
g = (color >> 5) & 0x3f;
b = color & 0x1f;
// lowers luminance
r = r > 1 ? r - 1 : 0;
g = g > 2 ? g - 2 : 0;
b = b > 1 ? b - 1 : 0;
// repacks the RGB565 color
color = r << 11 | g << 5 | b;
// restores endianness
fb[i] = color << 8 | color >> 8;
}
}
LovyanGFX library is outstanding!
Oh, and I have to point out a slight error in your WiFiChanViz.ino
code:
for (int i = 0; i < n; ++i) {
int32_t channel = WiFi.channel(i);
dpc[channel]++;
}
Replace this:
dpc[channel]++;
By:
dpc[channel - 1]++;
If you are curious, you can have a look at my code.
En tout cas, merci pour ton travail inspirant ! :wink:
Steph